You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by wa...@apache.org on 2014/12/02 06:59:34 UTC

[2/2] hadoop git commit: HADOOP-11341. KMS support for whitelist key ACLs. Contributed by Arun Suresh.

HADOOP-11341. KMS support for whitelist key ACLs. Contributed by Arun Suresh.

(cherry picked from commit 31b4d2daa14a7f6e8ee73fd3160e126d8db62ffb)


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/881c7710
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/881c7710
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/881c7710

Branch: refs/heads/branch-2
Commit: 881c77107ea3a4f4d12c2ea5a809bf573f6718e7
Parents: f9c5dec
Author: Andrew Wang <wa...@apache.org>
Authored: Mon Dec 1 21:53:18 2014 -0800
Committer: Andrew Wang <wa...@apache.org>
Committed: Mon Dec 1 21:58:21 2014 -0800

----------------------------------------------------------------------
 hadoop-common-project/hadoop-common/CHANGES.txt |  2 +
 .../hadoop/crypto/key/kms/server/KMSACLs.java   | 31 ++++++++++++--
 .../crypto/key/kms/server/KMSConfiguration.java |  1 +
 .../hadoop-kms/src/site/apt/index.apt.vm        | 38 +++++++++++++++--
 .../hadoop/crypto/key/kms/server/TestKMS.java   | 43 ++++++++++++++++++--
 5 files changed, 105 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/881c7710/hadoop-common-project/hadoop-common/CHANGES.txt
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt
index bd14149..00212f6 100644
--- a/hadoop-common-project/hadoop-common/CHANGES.txt
+++ b/hadoop-common-project/hadoop-common/CHANGES.txt
@@ -39,6 +39,8 @@ Release 2.7.0 - UNRELEASED
     HADOOP-11257: Update "hadoop jar" documentation to warn against using it
     for launching yarn jars (iwasakims via cmccabe)
 
+    HADOOP-11341. KMS support for whitelist key ACLs. (Arun Suresh via wang)
+
   OPTIMIZATIONS
 
     HADOOP-11323. WritableComparator#compare keeps reference to byte array.

http://git-wip-us.apache.org/repos/asf/hadoop/blob/881c7710/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSACLs.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSACLs.java b/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSACLs.java
index 530fe11..0217589 100644
--- a/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSACLs.java
+++ b/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSACLs.java
@@ -73,6 +73,8 @@ public class KMSACLs implements Runnable, KeyACLs {
   private volatile Map<String, HashMap<KeyOpType, AccessControlList>> keyAcls;
   private final Map<KeyOpType, AccessControlList> defaultKeyAcls =
       new HashMap<KeyOpType, AccessControlList>();
+  private final Map<KeyOpType, AccessControlList> whitelistKeyAcls =
+      new HashMap<KeyOpType, AccessControlList>();
   private ScheduledExecutorService executorService;
   private long lastReload;
 
@@ -151,11 +153,21 @@ public class KMSACLs implements Runnable, KeyACLs {
         String aclStr = conf.get(confKey);
         if (aclStr != null) {
           if (aclStr.equals("*")) {
-            LOG.info("Default Key ACL for  KEY_OP '{}' is set to '*'", keyOp);
+            LOG.info("Default Key ACL for KEY_OP '{}' is set to '*'", keyOp);
           }
           defaultKeyAcls.put(keyOp, new AccessControlList(aclStr));
         }
       }
+      if (!whitelistKeyAcls.containsKey(keyOp)) {
+        String confKey = KMSConfiguration.WHITELIST_KEY_ACL_PREFIX + keyOp;
+        String aclStr = conf.get(confKey);
+        if (aclStr != null) {
+          if (aclStr.equals("*")) {
+            LOG.info("Whitelist Key ACL for KEY_OP '{}' is set to '*'", keyOp);
+          }
+          whitelistKeyAcls.put(keyOp, new AccessControlList(aclStr));
+        }
+      }
     }
   }
 
@@ -229,13 +241,23 @@ public class KMSACLs implements Runnable, KeyACLs {
   @Override
   public boolean hasAccessToKey(String keyName, UserGroupInformation ugi,
       KeyOpType opType) {
+    return checkKeyAccess(keyName, ugi, opType)
+        || checkKeyAccess(whitelistKeyAcls, ugi, opType);
+  }
+
+  private boolean checkKeyAccess(String keyName, UserGroupInformation ugi,
+      KeyOpType opType) {
     Map<KeyOpType, AccessControlList> keyAcl = keyAcls.get(keyName);
     if (keyAcl == null) {
-      // Get KeyAcl map of DEFAULT KEY.
+      // If No key acl defined for this key, check to see if
+      // there are key defaults configured for this operation
       keyAcl = defaultKeyAcls;
     }
-    // If No key acl defined for this key, check to see if
-    // there are key defaults configured for this operation
+    return checkKeyAccess(keyAcl, ugi, opType);
+  }
+
+  private boolean checkKeyAccess(Map<KeyOpType, AccessControlList> keyAcl,
+      UserGroupInformation ugi, KeyOpType opType) {
     AccessControlList acl = keyAcl.get(opType);
     if (acl == null) {
       // If no acl is specified for this operation,
@@ -246,6 +268,7 @@ public class KMSACLs implements Runnable, KeyACLs {
     }
   }
 
+
   @Override
   public boolean isACLPresent(String keyName, KeyOpType opType) {
     return (keyAcls.containsKey(keyName) || defaultKeyAcls.containsKey(opType));

http://git-wip-us.apache.org/repos/asf/hadoop/blob/881c7710/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSConfiguration.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSConfiguration.java b/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSConfiguration.java
index bd61ca7..a67c68e 100644
--- a/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSConfiguration.java
+++ b/hadoop-common-project/hadoop-kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMSConfiguration.java
@@ -39,6 +39,7 @@ public class KMSConfiguration {
 
   public static final String KEY_ACL_PREFIX = "key.acl.";
   public static final String DEFAULT_KEY_ACL_PREFIX = "default.key.acl.";
+  public static final String WHITELIST_KEY_ACL_PREFIX = "whitelist.key.acl.";
 
   // Property to set the backing KeyProvider
   public static final String KEY_PROVIDER_URI = CONFIG_PREFIX +

http://git-wip-us.apache.org/repos/asf/hadoop/blob/881c7710/hadoop-common-project/hadoop-kms/src/site/apt/index.apt.vm
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-kms/src/site/apt/index.apt.vm b/hadoop-common-project/hadoop-kms/src/site/apt/index.apt.vm
index 76eb1a6..5d67b3b 100644
--- a/hadoop-common-project/hadoop-kms/src/site/apt/index.apt.vm
+++ b/hadoop-common-project/hadoop-kms/src/site/apt/index.apt.vm
@@ -467,10 +467,20 @@ $ keytool -genkey -alias tomcat -keyalg RSA
   is possible to configure a default key access control for a subset of the
   operation types.
 
+  It is also possible to configure a "whitelist" key ACL for a subset of the
+  operation types. The whitelist key ACL is a whitelist in addition to the
+  explicit or default per-key ACL. That is, if no per-key ACL is explicitly
+  set, a user will be granted access if they are present in the default per-key
+  ACL or the whitelist key ACL. If a per-key ACL is explicitly set, a user
+  will be granted access if they are present in the per-key ACL or the
+  whitelist key ACL.
+
   If no ACL is configured for a specific key AND no default ACL is configured
-  for the requested operation, then access will be DENIED.
+  AND no root key ACL is configured for the requested operation,
+  then access will be DENIED.
   
-  <<NOTE:>> The default ACL does not support <<<ALL>>> operation qualifier.
+  <<NOTE:>> The default and whitelist key ACL does not support <<<ALL>>>
+            operation qualifier.
   
 +---+
   <property>
@@ -491,7 +501,7 @@ $ keytool -genkey -alias tomcat -keyalg RSA
 
   <property>
     <name>key.acl.testKey3.DECRYPT_EEK</name>
-    <value>*</value>
+    <value>admink3</value>
     <description>
       ACL for decryptEncryptedKey operations.
     </description>
@@ -515,6 +525,28 @@ $ keytool -genkey -alias tomcat -keyalg RSA
   </property>
 
   <property>
+    <name>whitelist.key.acl.MANAGEMENT</name>
+    <value>admin1</value>
+    <description>
+      whitelist ACL for MANAGEMENT operations for all keys.
+    </description>
+  </property>
+
+  <!--
+  'testKey3' key ACL is defined. Since a 'whitelist'
+  key is also defined for DECRYPT_EEK, in addition to
+  admink3, admin1 can also perform DECRYPT_EEK operations
+  on 'testKey3'
+  -->
+  <property>
+    <name>whitelist.key.acl.DECRYPT_EEK</name>
+    <value>admin1</value>
+    <description>
+      whitelist ACL for DECRYPT_EEK operations for all keys.
+    </description>
+  </property>
+
+  <property>
     <name>default.key.acl.MANAGEMENT</name>
     <value>user1,user2</value>
     <description>

http://git-wip-us.apache.org/repos/asf/hadoop/blob/881c7710/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java
----------------------------------------------------------------------
diff --git a/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java b/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java
index 97901c8..d840646 100644
--- a/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java
+++ b/hadoop-common-project/hadoop-kms/src/test/java/org/apache/hadoop/crypto/key/kms/server/TestKMS.java
@@ -617,13 +617,15 @@ public class TestKMS {
     for (KMSACLs.Type type : KMSACLs.Type.values()) {
       conf.set(type.getAclConfigKey(), type.toString());
     }
-    conf.set(KMSACLs.Type.CREATE.getAclConfigKey(),"CREATE,ROLLOVER,GET,SET_KEY_MATERIAL,GENERATE_EEK");
-    conf.set(KMSACLs.Type.ROLLOVER.getAclConfigKey(),"CREATE,ROLLOVER,GET,SET_KEY_MATERIAL,GENERATE_EEK");
+    conf.set(KMSACLs.Type.CREATE.getAclConfigKey(),"CREATE,ROLLOVER,GET,SET_KEY_MATERIAL,GENERATE_EEK,DECRYPT_EEK");
+    conf.set(KMSACLs.Type.ROLLOVER.getAclConfigKey(),"CREATE,ROLLOVER,GET,SET_KEY_MATERIAL,GENERATE_EEK,DECRYPT_EEK");
     conf.set(KMSACLs.Type.GENERATE_EEK.getAclConfigKey(),"CREATE,ROLLOVER,GET,SET_KEY_MATERIAL,GENERATE_EEK");
     conf.set(KMSACLs.Type.DECRYPT_EEK.getAclConfigKey(),"CREATE,ROLLOVER,GET,SET_KEY_MATERIAL,GENERATE_EEK");
 
-
     conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "test_key.MANAGEMENT", "CREATE");
+    conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "some_key.MANAGEMENT", "ROLLOVER");
+    conf.set(KMSConfiguration.WHITELIST_KEY_ACL_PREFIX + "MANAGEMENT", "DECRYPT_EEK");
+
     conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "all_access.ALL", "GENERATE_EEK");
     conf.set(KeyAuthorizationKeyProvider.KEY_ACL + "all_access.DECRYPT_EEK", "ROLLOVER");
     conf.set(KMSConfiguration.DEFAULT_KEY_ACL_PREFIX + "MANAGEMENT", "ROLLOVER");
@@ -676,6 +678,41 @@ public class TestKMS {
           }
         });
 
+        // Test whitelist key access..
+        // DECRYPT_EEK is whitelisted for MANAGEMENT operations only
+        doAs("DECRYPT_EEK", new PrivilegedExceptionAction<Void>() {
+          @Override
+          public Void run() throws Exception {
+            KeyProvider kp = new KMSClientProvider(uri, conf);
+            try {
+              Options options = new KeyProvider.Options(conf);
+              Map<String, String> attributes = options.getAttributes();
+              HashMap<String,String> newAttribs = new HashMap<String, String>(attributes);
+              newAttribs.put("key.acl.name", "some_key");
+              options.setAttributes(newAttribs);
+              KeyProvider.KeyVersion kv = kp.createKey("kk0", options);
+              Assert.assertNull(kv.getMaterial());
+              KeyVersion rollVersion = kp.rollNewVersion("kk0");
+              Assert.assertNull(rollVersion.getMaterial());
+              KeyProviderCryptoExtension kpce =
+                  KeyProviderCryptoExtension.createKeyProviderCryptoExtension(kp);
+              try {
+                kpce.generateEncryptedKey("kk0");
+                Assert.fail("User [DECRYPT_EEK] should not be allowed to generate_eek on kk0");
+              } catch (Exception e) {
+                // Ignore
+              }
+              newAttribs = new HashMap<String, String>(attributes);
+              newAttribs.put("key.acl.name", "all_access");
+              options.setAttributes(newAttribs);
+              kp.createKey("kkx", options);
+            } catch (Exception ex) {
+              Assert.fail(ex.getMessage());
+            }
+            return null;
+          }
+        });
+
         doAs("ROLLOVER", new PrivilegedExceptionAction<Void>() {
           @Override
           public Void run() throws Exception {