Return-Path: X-Original-To: apmail-hadoop-common-commits-archive@www.apache.org Delivered-To: apmail-hadoop-common-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id F29C111B4E for ; Wed, 9 Apr 2014 19:47:07 +0000 (UTC) Received: (qmail 16288 invoked by uid 500); 9 Apr 2014 19:47:06 -0000 Delivered-To: apmail-hadoop-common-commits-archive@hadoop.apache.org Received: (qmail 15198 invoked by uid 500); 9 Apr 2014 19:47:04 -0000 Mailing-List: contact common-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: common-dev@hadoop.apache.org Delivered-To: mailing list common-commits@hadoop.apache.org Received: (qmail 15146 invoked by uid 99); 9 Apr 2014 19:47:03 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 09 Apr 2014 19:47:03 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 09 Apr 2014 19:47:02 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id E5A3B2388993; Wed, 9 Apr 2014 19:46:41 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1586105 - in /hadoop/common/trunk/hadoop-common-project/hadoop-common: ./ src/main/java/org/apache/hadoop/crypto/key/ src/test/java/org/apache/hadoop/crypto/key/ Date: Wed, 09 Apr 2014 19:46:41 -0000 To: common-commits@hadoop.apache.org From: tucu@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140409194641.E5A3B2388993@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: tucu Date: Wed Apr 9 19:46:41 2014 New Revision: 1586105 URL: http://svn.apache.org/r1586105 Log: HADOOP-10429. KeyStores should have methods to generate the materials themselves, KeyShell should use them. (tucu) Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyProvider.java hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyShell.java hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/key/TestKeyProvider.java Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt?rev=1586105&r1=1586104&r2=1586105&view=diff ============================================================================== --- hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt (original) +++ hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt Wed Apr 9 19:46:41 2014 @@ -132,6 +132,9 @@ Trunk (Unreleased) HADOOP-10427. KeyProvider implementations should be thread safe. (tucu) + HADOOP-10429. KeyStores should have methods to generate the materials + themselves, KeyShell should use them. (tucu) + BUG FIXES HADOOP-9451. Fault single-layer config if node group topology is enabled. Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyProvider.java URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyProvider.java?rev=1586105&r1=1586104&r2=1586105&view=diff ============================================================================== --- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyProvider.java (original) +++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyProvider.java Wed Apr 9 19:46:41 2014 @@ -24,6 +24,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.URI; +import java.security.NoSuchAlgorithmException; import java.util.Date; import java.util.List; @@ -34,6 +35,8 @@ import org.apache.hadoop.classification. import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; +import javax.crypto.KeyGenerator; + /** * A provider of secret key material for Hadoop applications. Provides an * abstraction to separate key storage from users of encryption. It @@ -317,6 +320,56 @@ public abstract class KeyProvider { Options options) throws IOException; /** + * Get the algorithm from the cipher. + * + * @return the algorithm name + */ + private String getAlgorithm(String cipher) { + int slash = cipher.indexOf('/'); + if (slash == -1) { + return cipher; + } else { + return cipher.substring(0, slash); + } + } + + /** + * Generates a key material. + * + * @param size length of the key. + * @param algorithm algorithm to use for generating the key. + * @return the generated key. + * @throws NoSuchAlgorithmException + */ + protected byte[] generateKey(int size, String algorithm) + throws NoSuchAlgorithmException { + algorithm = getAlgorithm(algorithm); + KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm); + keyGenerator.init(size); + byte[] key = keyGenerator.generateKey().getEncoded(); + return key; + } + + /** + * Create a new key generating the material for it. + * The given key must not already exist. + *

+ * This implementation generates the key material and calls the + * {@link #createKey(String, byte[], Options)} method. + * + * @param name the base name of the key + * @param options the options for the new key. + * @return the version name of the first version of the key. + * @throws IOException + * @throws NoSuchAlgorithmException + */ + public KeyVersion createKey(String name, Options options) + throws NoSuchAlgorithmException, IOException { + byte[] material = generateKey(options.getBitLength(), options.getCipher()); + return createKey(name, material, options); + } + + /** * Delete the given key. * @param name the name of the key to delete * @throws IOException @@ -335,6 +388,23 @@ public abstract class KeyProvider { ) throws IOException; /** + * Roll a new version of the given key generating the material for it. + *

+ * This implementation generates the key material and calls the + * {@link #rollNewVersion(String, byte[])} method. + * + * @param name the basename of the key + * @return the name of the new version of the key + * @throws IOException + */ + public KeyVersion rollNewVersion(String name) throws NoSuchAlgorithmException, + IOException { + Metadata meta = getMetadata(name); + byte[] material = generateKey(meta.getBitLength(), meta.getCipher()); + return rollNewVersion(name, material); + } + + /** * Ensures that any changes to the keys are written to persistent store. * @throws IOException */ Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyShell.java URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyShell.java?rev=1586105&r1=1586104&r2=1586105&view=diff ============================================================================== --- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyShell.java (original) +++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyShell.java Wed Apr 9 19:46:41 2014 @@ -185,16 +185,6 @@ public class KeyShell extends Configured return provider; } - protected byte[] generateKey(int size, String algorithm) - throws NoSuchAlgorithmException { - out.println("Generating key using size: " + size + " and algorithm: " - + algorithm); - KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm); - keyGenerator.init(size); - byte[] key = keyGenerator.generateKey().getEncoded(); - return key; - } - protected void printProviderWritten() { out.println(provider.getClass().getName() + " has been updated."); } @@ -289,9 +279,7 @@ public class KeyShell extends Configured out.println("Rolling key version from KeyProvider: " + provider.toString() + " for key name: " + keyName); try { - byte[] material = null; - material = generateKey(md.getBitLength(), md.getAlgorithm()); - provider.rollNewVersion(keyName, material); + provider.rollNewVersion(keyName); out.println(keyName + " has been successfully rolled."); provider.flush(); printProviderWritten(); @@ -423,9 +411,7 @@ public class KeyShell extends Configured warnIfTransientProvider(); try { Options options = KeyProvider.options(getConf()); - String alg = getAlgorithm(options.getCipher()); - byte[] material = generateKey(options.getBitLength(), alg); - provider.createKey(keyName, material, options); + provider.createKey(keyName, options); out.println(keyName + " has been successfully created."); provider.flush(); printProviderWritten(); @@ -441,19 +427,6 @@ public class KeyShell extends Configured } } - /** - * Get the algorithm from the cipher. - * @return the algorithm name - */ - public String getAlgorithm(String cipher) { - int slash = cipher.indexOf('/'); - if (slash == - 1) { - return cipher; - } else { - return cipher.substring(0, slash); - } - } - @Override public String getUsage() { return USAGE + ":\n\n" + DESC; Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/key/TestKeyProvider.java URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/key/TestKeyProvider.java?rev=1586105&r1=1586104&r2=1586105&view=diff ============================================================================== --- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/key/TestKeyProvider.java (original) +++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/crypto/key/TestKeyProvider.java Wed Apr 9 19:46:41 2014 @@ -17,6 +17,7 @@ */ package org.apache.hadoop.crypto.key; +import junit.framework.Assert; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; @@ -24,9 +25,11 @@ import org.junit.Test; import java.io.IOException; import java.net.URI; +import java.security.NoSuchAlgorithmException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -34,6 +37,8 @@ import static org.junit.Assert.assertArr public class TestKeyProvider { + private static final String CIPHER = "AES"; + @Test public void testBuildVersionName() throws Exception { assertEquals("/a/b@3", KeyProvider.buildVersionName("/a/b", 3)); @@ -109,4 +114,82 @@ public class TestKeyProvider { assertEquals(new Path("user:///"), KeyProvider.unnestUri(new URI("outer://user/"))); } + + private static class MyKeyProvider extends KeyProvider { + private String algorithm; + private int size; + private byte[] material; + + @Override + public KeyVersion getKeyVersion(String versionName) + throws IOException { + return null; + } + + @Override + public List getKeys() throws IOException { + return null; + } + + @Override + public List getKeyVersions(String name) + throws IOException { + return null; + } + + @Override + public Metadata getMetadata(String name) throws IOException { + return new Metadata(CIPHER, 128, new Date(), 0); + } + + @Override + public KeyVersion createKey(String name, byte[] material, + Options options) throws IOException { + this.material = material; + return null; + } + + @Override + public void deleteKey(String name) throws IOException { + + } + + @Override + public KeyVersion rollNewVersion(String name, byte[] material) + throws IOException { + this.material = material; + return null; + } + + @Override + public void flush() throws IOException { + + } + + @Override + protected byte[] generateKey(int size, String algorithm) + throws NoSuchAlgorithmException { + this.size = size; + this.algorithm = algorithm; + return super.generateKey(size, algorithm); + } + } + + @Test + public void testMaterialGeneration() throws Exception { + MyKeyProvider kp = new MyKeyProvider(); + KeyProvider.Options options = new KeyProvider.Options(new Configuration()); + options.setCipher(CIPHER); + options.setBitLength(128); + kp.createKey("hello", options); + Assert.assertEquals(128, kp.size); + Assert.assertEquals(CIPHER, kp.algorithm); + Assert.assertNotNull(kp.material); + + kp = new MyKeyProvider(); + kp.rollNewVersion("hello"); + Assert.assertEquals(128, kp.size); + Assert.assertEquals(CIPHER, kp.algorithm); + Assert.assertNotNull(kp.material); + } }