You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by mb...@apache.org on 2014/12/04 17:06:43 UTC

[1/3] hbase git commit: HBASE-12634 Fix the AccessController#requireGlobalPermission(ns) with NS

Repository: hbase
Updated Branches:
  refs/heads/0.98 769f93ff0 -> 6c927313c
  refs/heads/branch-1 bb07de196 -> ffbfe01bb
  refs/heads/master c45772e76 -> 04444299a


HBASE-12634 Fix the AccessController#requireGlobalPermission(ns) with NS

Signed-off-by: Matteo Bertozzi <ma...@cloudera.com>


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

Branch: refs/heads/master
Commit: 04444299ab8bf69618d7e07a6ec7071ce9234d9d
Parents: c45772e
Author: Ashish Singhi <as...@huawei.com>
Authored: Thu Dec 4 15:57:01 2014 +0530
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Thu Dec 4 14:12:26 2014 +0000

----------------------------------------------------------------------
 .../hbase/security/access/AccessController.java |  5 +-
 .../security/access/TestNamespaceCommands.java  | 58 +++++++++++++++-----
 2 files changed, 48 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/04444299/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
index 1218368..9bd7daf 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
@@ -497,7 +497,8 @@ public class AccessController extends BaseMasterAndRegionObserver
   private void requireGlobalPermission(String request, Action perm,
                                        String namespace) throws IOException {
     User user = getActiveUser();
-    if (authManager.authorize(user, perm)) {
+    if (authManager.authorize(user, perm)
+        || (namespace != null && authManager.authorize(user, namespace, perm))) {
       logResult(AuthResult.allow(request, "Global check allowed", user, perm, namespace));
     } else {
       logResult(AuthResult.deny(request, "Global check failed", user, perm, namespace));
@@ -1145,7 +1146,7 @@ public class AccessController extends BaseMasterAndRegionObserver
   @Override
   public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx,
       NamespaceDescriptor ns) throws IOException {
-    requireGlobalPermission("createNamespace", Action.ADMIN, ns.getName());
+    requirePermission("createNamespace", Action.ADMIN);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/hbase/blob/04444299/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
index 0f28c66..5928f93 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
@@ -22,9 +22,6 @@ import static org.junit.Assert.assertTrue;
 
 import java.util.List;
 
-import com.google.common.collect.ListMultimap;
-import com.google.protobuf.BlockingRpcChannel;
-
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.HBaseTestingUtility;
 import org.apache.hadoop.hbase.HColumnDescriptor;
@@ -50,15 +47,14 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import com.google.common.collect.ListMultimap;
+import com.google.protobuf.BlockingRpcChannel;
 
 @Category({SecurityTests.class, MediumTests.class})
 public class TestNamespaceCommands extends SecureTestUtil {
   private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
   private static String TestNamespace = "ns1";
+  private static String TestNamespace2 = "ns2";
   private static Configuration conf;
   private static MasterCoprocessorEnvironment CP_ENV;
   private static AccessController ACCESS_CONTROLLER;
@@ -71,6 +67,8 @@ public class TestNamespaceCommands extends SecureTestUtil {
   private static User USER_CREATE;
   // user with permission on namespace for testing all operations.
   private static User USER_NSP_WRITE;
+  // user with admin permission on namespace.
+  private static User USER_NSP_ADMIN;
 
   private static String TEST_TABLE = TestNamespace + ":testtable";
   private static byte[] TEST_FAMILY = Bytes.toBytes("f1");
@@ -84,6 +82,7 @@ public class TestNamespaceCommands extends SecureTestUtil {
     USER_RW = User.createUserForTesting(conf, "rw_user", new String[0]);
     USER_CREATE = User.createUserForTesting(conf, "create_user", new String[0]);
     USER_NSP_WRITE = User.createUserForTesting(conf, "namespace_write", new String[0]);
+    USER_NSP_ADMIN = User.createUserForTesting(conf, "namespace_admin", new String[0]);
 
     UTIL.startMiniCluster();
     // Wait for the ACL table to become available
@@ -94,14 +93,19 @@ public class TestNamespaceCommands extends SecureTestUtil {
         .findCoprocessor(AccessController.class.getName());
 
     UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TestNamespace).build());
+    UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TestNamespace2).build());
 
     grantOnNamespace(UTIL, USER_NSP_WRITE.getShortName(),
       TestNamespace, Permission.Action.WRITE, Permission.Action.CREATE);
+
+    grantOnNamespace(UTIL, USER_NSP_ADMIN.getShortName(), TestNamespace, Permission.Action.ADMIN);
+    grantOnNamespace(UTIL, USER_NSP_ADMIN.getShortName(), TestNamespace2, Permission.Action.ADMIN);
   }
   
   @AfterClass
   public static void afterClass() throws Exception {
     UTIL.getHBaseAdmin().deleteNamespace(TestNamespace);
+    UTIL.getHBaseAdmin().deleteNamespace(TestNamespace2);
     UTIL.shutdownMiniCluster();
   }
 
@@ -118,7 +122,7 @@ public class TestNamespaceCommands extends SecureTestUtil {
       assertTrue(result != null);
       ListMultimap<String, TablePermission> perms =
           AccessControlLists.getNamespacePermissions(conf, TestNamespace);
-      assertEquals(2, perms.size());
+      assertEquals(3, perms.size());
       List<TablePermission> namespacePerms = perms.get(userTestNamespace);
       assertTrue(perms.containsKey(userTestNamespace));
       assertEquals(1, namespacePerms.size());
@@ -134,7 +138,7 @@ public class TestNamespaceCommands extends SecureTestUtil {
         Permission.Action.WRITE);
 
       perms = AccessControlLists.getNamespacePermissions(conf, TestNamespace);
-      assertEquals(1, perms.size());
+      assertEquals(2, perms.size());
     } finally {
       acl.close();
     }
@@ -150,12 +154,40 @@ public class TestNamespaceCommands extends SecureTestUtil {
       }
     };
     // verify that superuser or hbase admin can modify namespaces.
-    verifyAllowed(modifyNamespace, SUPERUSER);
+    verifyAllowed(modifyNamespace, SUPERUSER, USER_NSP_ADMIN);
     // all others should be denied
     verifyDenied(modifyNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW);
   }
   
   @Test
+  public void testCreateAndDeleteNamespace() throws Exception {
+    AccessTestAction createNamespace = new AccessTestAction() {
+      public Object run() throws Exception {
+        ACCESS_CONTROLLER.preCreateNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
+          NamespaceDescriptor.create(TestNamespace2).build());
+        return null;
+      }
+    };
+
+    AccessTestAction deleteNamespace = new AccessTestAction() {
+      public Object run() throws Exception {
+        ACCESS_CONTROLLER.preDeleteNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
+          TestNamespace2);
+        return null;
+      }
+    };
+
+    // verify that only superuser can create namespaces.
+    verifyAllowed(createNamespace, SUPERUSER);
+ // verify that superuser or hbase admin can delete namespaces.
+    verifyAllowed(deleteNamespace, SUPERUSER, USER_NSP_ADMIN);
+
+    // all others should be denied
+    verifyDenied(createNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW, USER_NSP_ADMIN);
+    verifyDenied(deleteNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW);
+  }
+
+  @Test
   public void testGrantRevoke() throws Exception{
     final String testUser = "testUser";
 
@@ -195,10 +227,10 @@ public class TestNamespaceCommands extends SecureTestUtil {
 
     // Only HBase super user should be able to grant and revoke permissions to
     // namespaces
-    verifyAllowed(grantAction, SUPERUSER);
+    verifyAllowed(grantAction, SUPERUSER, USER_NSP_ADMIN);
     verifyDenied(grantAction, USER_CREATE, USER_RW);
-    verifyAllowed(revokeAction, SUPERUSER);
-    verifyDenied(revokeAction, USER_CREATE, USER_RW);    
+    verifyAllowed(revokeAction, SUPERUSER, USER_NSP_ADMIN);
+    verifyDenied(revokeAction, USER_CREATE, USER_RW);
   }
 
   @Test


[2/3] hbase git commit: HBASE-12634 Fix the AccessController#requireGlobalPermission(ns) with NS

Posted by mb...@apache.org.
HBASE-12634 Fix the AccessController#requireGlobalPermission(ns) with NS

Signed-off-by: Matteo Bertozzi <ma...@cloudera.com>


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

Branch: refs/heads/branch-1
Commit: ffbfe01bbeb00d91f8df1ce6ddc041af9887dca7
Parents: bb07de1
Author: Ashish Singhi <as...@huawei.com>
Authored: Thu Dec 4 15:57:01 2014 +0530
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Thu Dec 4 15:35:53 2014 +0000

----------------------------------------------------------------------
 .../hbase/security/access/AccessController.java |  5 +-
 .../security/access/TestNamespaceCommands.java  | 58 +++++++++++++++-----
 2 files changed, 48 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/ffbfe01b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
index 7ab77a5..e106d7a 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
@@ -497,7 +497,8 @@ public class AccessController extends BaseMasterAndRegionObserver
   private void requireGlobalPermission(String request, Action perm,
                                        String namespace) throws IOException {
     User user = getActiveUser();
-    if (authManager.authorize(user, perm)) {
+    if (authManager.authorize(user, perm)
+        || (namespace != null && authManager.authorize(user, namespace, perm))) {
       logResult(AuthResult.allow(request, "Global check allowed", user, perm, namespace));
     } else {
       logResult(AuthResult.deny(request, "Global check failed", user, perm, namespace));
@@ -1125,7 +1126,7 @@ public class AccessController extends BaseMasterAndRegionObserver
   @Override
   public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx,
       NamespaceDescriptor ns) throws IOException {
-    requireGlobalPermission("createNamespace", Action.ADMIN, ns.getName());
+    requirePermission("createNamespace", Action.ADMIN);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/hbase/blob/ffbfe01b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
index 56b3814..5ed56ef 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
@@ -22,9 +22,6 @@ import static org.junit.Assert.assertTrue;
 
 import java.util.List;
 
-import com.google.common.collect.ListMultimap;
-import com.google.protobuf.BlockingRpcChannel;
-
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.HBaseTestingUtility;
 import org.apache.hadoop.hbase.HColumnDescriptor;
@@ -49,15 +46,14 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import com.google.common.collect.ListMultimap;
+import com.google.protobuf.BlockingRpcChannel;
 
 @Category(MediumTests.class)
 public class TestNamespaceCommands extends SecureTestUtil {
   private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
   private static String TestNamespace = "ns1";
+  private static String TestNamespace2 = "ns2";
   private static Configuration conf;
   private static MasterCoprocessorEnvironment CP_ENV;
   private static AccessController ACCESS_CONTROLLER;
@@ -70,6 +66,8 @@ public class TestNamespaceCommands extends SecureTestUtil {
   private static User USER_CREATE;
   // user with permission on namespace for testing all operations.
   private static User USER_NSP_WRITE;
+  // user with admin permission on namespace.
+  private static User USER_NSP_ADMIN;
 
   private static String TEST_TABLE = TestNamespace + ":testtable";
   private static byte[] TEST_FAMILY = Bytes.toBytes("f1");
@@ -83,6 +81,7 @@ public class TestNamespaceCommands extends SecureTestUtil {
     USER_RW = User.createUserForTesting(conf, "rw_user", new String[0]);
     USER_CREATE = User.createUserForTesting(conf, "create_user", new String[0]);
     USER_NSP_WRITE = User.createUserForTesting(conf, "namespace_write", new String[0]);
+    USER_NSP_ADMIN = User.createUserForTesting(conf, "namespace_admin", new String[0]);
 
     UTIL.startMiniCluster();
     // Wait for the ACL table to become available
@@ -93,14 +92,19 @@ public class TestNamespaceCommands extends SecureTestUtil {
         .findCoprocessor(AccessController.class.getName());
 
     UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TestNamespace).build());
+    UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TestNamespace2).build());
 
     grantOnNamespace(UTIL, USER_NSP_WRITE.getShortName(),
       TestNamespace, Permission.Action.WRITE, Permission.Action.CREATE);
+
+    grantOnNamespace(UTIL, USER_NSP_ADMIN.getShortName(), TestNamespace, Permission.Action.ADMIN);
+    grantOnNamespace(UTIL, USER_NSP_ADMIN.getShortName(), TestNamespace2, Permission.Action.ADMIN);
   }
   
   @AfterClass
   public static void afterClass() throws Exception {
     UTIL.getHBaseAdmin().deleteNamespace(TestNamespace);
+    UTIL.getHBaseAdmin().deleteNamespace(TestNamespace2);
     UTIL.shutdownMiniCluster();
   }
 
@@ -117,7 +121,7 @@ public class TestNamespaceCommands extends SecureTestUtil {
       assertTrue(result != null);
       ListMultimap<String, TablePermission> perms =
           AccessControlLists.getNamespacePermissions(conf, TestNamespace);
-      assertEquals(2, perms.size());
+      assertEquals(3, perms.size());
       List<TablePermission> namespacePerms = perms.get(userTestNamespace);
       assertTrue(perms.containsKey(userTestNamespace));
       assertEquals(1, namespacePerms.size());
@@ -133,7 +137,7 @@ public class TestNamespaceCommands extends SecureTestUtil {
         Permission.Action.WRITE);
 
       perms = AccessControlLists.getNamespacePermissions(conf, TestNamespace);
-      assertEquals(1, perms.size());
+      assertEquals(2, perms.size());
     } finally {
       acl.close();
     }
@@ -149,12 +153,40 @@ public class TestNamespaceCommands extends SecureTestUtil {
       }
     };
     // verify that superuser or hbase admin can modify namespaces.
-    verifyAllowed(modifyNamespace, SUPERUSER);
+    verifyAllowed(modifyNamespace, SUPERUSER, USER_NSP_ADMIN);
     // all others should be denied
     verifyDenied(modifyNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW);
   }
   
   @Test
+  public void testCreateAndDeleteNamespace() throws Exception {
+    AccessTestAction createNamespace = new AccessTestAction() {
+      public Object run() throws Exception {
+        ACCESS_CONTROLLER.preCreateNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
+          NamespaceDescriptor.create(TestNamespace2).build());
+        return null;
+      }
+    };
+
+    AccessTestAction deleteNamespace = new AccessTestAction() {
+      public Object run() throws Exception {
+        ACCESS_CONTROLLER.preDeleteNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
+          TestNamespace2);
+        return null;
+      }
+    };
+
+    // verify that only superuser can create namespaces.
+    verifyAllowed(createNamespace, SUPERUSER);
+ // verify that superuser or hbase admin can delete namespaces.
+    verifyAllowed(deleteNamespace, SUPERUSER, USER_NSP_ADMIN);
+
+    // all others should be denied
+    verifyDenied(createNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW, USER_NSP_ADMIN);
+    verifyDenied(deleteNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW);
+  }
+
+  @Test
   public void testGrantRevoke() throws Exception{
     final String testUser = "testUser";
 
@@ -194,10 +226,10 @@ public class TestNamespaceCommands extends SecureTestUtil {
 
     // Only HBase super user should be able to grant and revoke permissions to
     // namespaces
-    verifyAllowed(grantAction, SUPERUSER);
+    verifyAllowed(grantAction, SUPERUSER, USER_NSP_ADMIN);
     verifyDenied(grantAction, USER_CREATE, USER_RW);
-    verifyAllowed(revokeAction, SUPERUSER);
-    verifyDenied(revokeAction, USER_CREATE, USER_RW);    
+    verifyAllowed(revokeAction, SUPERUSER, USER_NSP_ADMIN);
+    verifyDenied(revokeAction, USER_CREATE, USER_RW);
   }
 
   @Test


[3/3] hbase git commit: HBASE-12634 Fix the AccessController#requireGlobalPermission(ns) with NS

Posted by mb...@apache.org.
HBASE-12634 Fix the AccessController#requireGlobalPermission(ns) with NS

Signed-off-by: Matteo Bertozzi <ma...@cloudera.com>


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/6c927313
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/6c927313
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/6c927313

Branch: refs/heads/0.98
Commit: 6c927313c5ac7275bce3f9cdc4d215db28264601
Parents: 769f93f
Author: Ashish Singhi <as...@huawei.com>
Authored: Thu Dec 4 15:57:01 2014 +0530
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Thu Dec 4 15:42:02 2014 +0000

----------------------------------------------------------------------
 .../hbase/security/access/AccessController.java |  5 +-
 .../security/access/TestNamespaceCommands.java  | 58 +++++++++++++++-----
 2 files changed, 48 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/6c927313/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
index ceb6eec..19709e6 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java
@@ -496,7 +496,8 @@ public class AccessController extends BaseMasterAndRegionObserver
   private void requireGlobalPermission(String request, Action perm,
                                        String namespace) throws IOException {
     User user = getActiveUser();
-    if (authManager.authorize(user, perm)) {
+    if (authManager.authorize(user, perm)
+        || (namespace != null && authManager.authorize(user, namespace, perm))) {
       logResult(AuthResult.allow(request, "Global check allowed", user, perm, namespace));
     } else {
       logResult(AuthResult.deny(request, "Global check failed", user, perm, namespace));
@@ -1148,7 +1149,7 @@ public class AccessController extends BaseMasterAndRegionObserver
   @Override
   public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx,
       NamespaceDescriptor ns) throws IOException {
-    requireGlobalPermission("createNamespace", Action.ADMIN, ns.getName());
+    requirePermission("createNamespace", Action.ADMIN);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/hbase/blob/6c927313/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
index a9601d5..6c53941 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java
@@ -22,9 +22,6 @@ import static org.junit.Assert.assertTrue;
 
 import java.util.List;
 
-import com.google.common.collect.ListMultimap;
-import com.google.protobuf.BlockingRpcChannel;
-
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hbase.HBaseTestingUtility;
 import org.apache.hadoop.hbase.HColumnDescriptor;
@@ -48,15 +45,14 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import com.google.common.collect.ListMultimap;
+import com.google.protobuf.BlockingRpcChannel;
 
 @Category(MediumTests.class)
 public class TestNamespaceCommands extends SecureTestUtil {
   private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
   private static String TestNamespace = "ns1";
+  private static String TestNamespace2 = "ns2";
   private static Configuration conf;
   private static MasterCoprocessorEnvironment CP_ENV;
   private static AccessController ACCESS_CONTROLLER;
@@ -69,6 +65,8 @@ public class TestNamespaceCommands extends SecureTestUtil {
   private static User USER_CREATE;
   // user with permission on namespace for testing all operations.
   private static User USER_NSP_WRITE;
+  // user with admin permission on namespace.
+  private static User USER_NSP_ADMIN;
 
   private static String TEST_TABLE = TestNamespace + ":testtable";
   private static byte[] TEST_FAMILY = Bytes.toBytes("f1");
@@ -82,6 +80,7 @@ public class TestNamespaceCommands extends SecureTestUtil {
     USER_RW = User.createUserForTesting(conf, "rw_user", new String[0]);
     USER_CREATE = User.createUserForTesting(conf, "create_user", new String[0]);
     USER_NSP_WRITE = User.createUserForTesting(conf, "namespace_write", new String[0]);
+    USER_NSP_ADMIN = User.createUserForTesting(conf, "namespace_admin", new String[0]);
 
     UTIL.startMiniCluster();
     // Wait for the ACL table to become available
@@ -92,14 +91,19 @@ public class TestNamespaceCommands extends SecureTestUtil {
         .findCoprocessor(AccessController.class.getName());
 
     UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TestNamespace).build());
+    UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TestNamespace2).build());
 
     grantOnNamespace(UTIL, USER_NSP_WRITE.getShortName(),
       TestNamespace, Permission.Action.WRITE, Permission.Action.CREATE);
+
+    grantOnNamespace(UTIL, USER_NSP_ADMIN.getShortName(), TestNamespace, Permission.Action.ADMIN);
+    grantOnNamespace(UTIL, USER_NSP_ADMIN.getShortName(), TestNamespace2, Permission.Action.ADMIN);
   }
   
   @AfterClass
   public static void afterClass() throws Exception {
     UTIL.getHBaseAdmin().deleteNamespace(TestNamespace);
+    UTIL.getHBaseAdmin().deleteNamespace(TestNamespace2);
     UTIL.shutdownMiniCluster();
   }
 
@@ -116,7 +120,7 @@ public class TestNamespaceCommands extends SecureTestUtil {
       assertTrue(result != null);
       ListMultimap<String, TablePermission> perms =
           AccessControlLists.getNamespacePermissions(conf, TestNamespace);
-      assertEquals(2, perms.size());
+      assertEquals(3, perms.size());
       List<TablePermission> namespacePerms = perms.get(userTestNamespace);
       assertTrue(perms.containsKey(userTestNamespace));
       assertEquals(1, namespacePerms.size());
@@ -132,7 +136,7 @@ public class TestNamespaceCommands extends SecureTestUtil {
         Permission.Action.WRITE);
 
       perms = AccessControlLists.getNamespacePermissions(conf, TestNamespace);
-      assertEquals(1, perms.size());
+      assertEquals(2, perms.size());
     } finally {
       acl.close();
     }
@@ -148,12 +152,40 @@ public class TestNamespaceCommands extends SecureTestUtil {
       }
     };
     // verify that superuser or hbase admin can modify namespaces.
-    verifyAllowed(modifyNamespace, SUPERUSER);
+    verifyAllowed(modifyNamespace, SUPERUSER, USER_NSP_ADMIN);
     // all others should be denied
     verifyDenied(modifyNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW);
   }
   
   @Test
+  public void testCreateAndDeleteNamespace() throws Exception {
+    AccessTestAction createNamespace = new AccessTestAction() {
+      public Object run() throws Exception {
+        ACCESS_CONTROLLER.preCreateNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
+          NamespaceDescriptor.create(TestNamespace2).build());
+        return null;
+      }
+    };
+
+    AccessTestAction deleteNamespace = new AccessTestAction() {
+      public Object run() throws Exception {
+        ACCESS_CONTROLLER.preDeleteNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
+          TestNamespace2);
+        return null;
+      }
+    };
+
+    // verify that only superuser can create namespaces.
+    verifyAllowed(createNamespace, SUPERUSER);
+ // verify that superuser or hbase admin can delete namespaces.
+    verifyAllowed(deleteNamespace, SUPERUSER, USER_NSP_ADMIN);
+
+    // all others should be denied
+    verifyDenied(createNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW, USER_NSP_ADMIN);
+    verifyDenied(deleteNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW);
+  }
+
+  @Test
   public void testGrantRevoke() throws Exception{
     final String testUser = "testUser";
 
@@ -193,10 +225,10 @@ public class TestNamespaceCommands extends SecureTestUtil {
 
     // Only HBase super user should be able to grant and revoke permissions to
     // namespaces
-    verifyAllowed(grantAction, SUPERUSER);
+    verifyAllowed(grantAction, SUPERUSER, USER_NSP_ADMIN);
     verifyDenied(grantAction, USER_CREATE, USER_RW);
-    verifyAllowed(revokeAction, SUPERUSER);
-    verifyDenied(revokeAction, USER_CREATE, USER_RW);    
+    verifyAllowed(revokeAction, SUPERUSER, USER_NSP_ADMIN);
+    verifyDenied(revokeAction, USER_CREATE, USER_RW);
   }
 
   @Test