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/11 19:16:07 UTC

[1/2] hbase git commit: HBASE-12674 Add permission check to getNamespaceDescriptor()

Repository: hbase
Updated Branches:
  refs/heads/branch-1 75cf81aae -> c4aee2e28
  refs/heads/master f67162547 -> 7030d2187


HBASE-12674 Add permission check to getNamespaceDescriptor()


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

Branch: refs/heads/master
Commit: 7030d2187dc03668ebaa0cb528088dc2bdde8c70
Parents: f671625
Author: Matteo Bertozzi <ma...@cloudera.com>
Authored: Thu Dec 11 16:55:42 2014 +0000
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Thu Dec 11 17:43:51 2014 +0000

----------------------------------------------------------------------
 .../BaseMasterAndRegionObserver.java            | 10 ++++++
 .../hbase/coprocessor/BaseMasterObserver.java   | 10 ++++++
 .../hbase/coprocessor/MasterObserver.java       | 18 +++++++++++
 .../org/apache/hadoop/hbase/master/HMaster.java | 32 ++++++++++++++++++--
 .../hbase/master/MasterCoprocessorHost.java     | 22 ++++++++++++++
 .../hbase/security/access/AccessController.java |  6 ++++
 .../hbase/coprocessor/TestMasterObserver.java   | 27 +++++++++++++++++
 .../security/access/TestNamespaceCommands.java  | 15 +++++++++
 8 files changed, 137 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/7030d218/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java
index fbf505e..85abbf8 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java
@@ -159,6 +159,16 @@ public abstract class BaseMasterAndRegionObserver extends BaseRegionObserver
   }
 
   @Override
+  public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      String namespace) throws IOException {
+  }
+
+  @Override
+  public void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      NamespaceDescriptor ns) throws IOException {
+  }
+
+  @Override
   public void preListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
       List<NamespaceDescriptor> descriptors) throws IOException {
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/7030d218/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java
index e33288d..de1645e 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java
@@ -152,6 +152,16 @@ public class BaseMasterObserver implements MasterObserver {
   }
 
   @Override
+  public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      String namespace) throws IOException {
+  }
+
+  @Override
+  public void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      NamespaceDescriptor ns) throws IOException {
+  }
+
+  @Override
   public void preListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
       List<NamespaceDescriptor> descriptors) throws IOException {
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/7030d218/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
index bad2c5f..ab9f709 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
@@ -789,6 +789,24 @@ public interface MasterObserver extends Coprocessor {
       NamespaceDescriptor ns) throws IOException;
 
   /**
+   * Called before a getNamespaceDescriptor request has been processed.
+   * @param ctx the environment to interact with the framework and master
+   * @param namespace the name of the namespace
+   * @throws IOException
+   */
+  void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      String namespace) throws IOException;
+
+  /**
+   * Called after a getNamespaceDescriptor request has been processed.
+   * @param ctx the environment to interact with the framework and master
+   * @param ns the NamespaceDescriptor
+   * @throws IOException
+   */
+  void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      NamespaceDescriptor ns) throws IOException;
+
+  /**
    * Called before a listNamespaceDescriptors request has been processed.
    * @param ctx the environment to interact with the framework and master
    * @param descriptors an empty list, can be filled with what to return if bypassing

http://git-wip-us.apache.org/repos/asf/hbase/blob/7030d218/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
index 3d87c67..06b0e3c 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
@@ -1227,7 +1227,7 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
     }
 
     String namespace = hTableDescriptor.getTableName().getNamespaceAsString();
-    getNamespaceDescriptor(namespace); // ensure namespace exists
+    ensureNamespaceExists(namespace);
 
     HRegionInfo[] newRegions = getHRegionInfos(hTableDescriptor, splitKeys);
     checkInitialized();
@@ -2028,13 +2028,39 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
     }
   }
 
+  /**
+   * Ensure that the specified namespace exists, otherwise throws a NamespaceNotFoundException
+   *
+   * @param name the namespace to check
+   * @throws IOException if the namespace manager is not ready yet.
+   * @throws NamespaceNotFoundException if the namespace does not exists
+   */
+  private void ensureNamespaceExists(final String name)
+      throws IOException, NamespaceNotFoundException {
+    checkNamespaceManagerReady();
+    NamespaceDescriptor nsd = tableNamespaceManager.get(name);
+    if (nsd == null) {
+      throw new NamespaceNotFoundException(name);
+    }
+  }
+
   @Override
   public NamespaceDescriptor getNamespaceDescriptor(String name) throws IOException {
     checkNamespaceManagerReady();
+
+    if (cpHost != null) {
+      cpHost.preGetNamespaceDescriptor(name);
+    }
+
     NamespaceDescriptor nsd = tableNamespaceManager.get(name);
     if (nsd == null) {
       throw new NamespaceNotFoundException(name);
     }
+
+    if (cpHost != null) {
+      cpHost.postGetNamespaceDescriptor(nsd);
+    }
+
     return nsd;
   }
 
@@ -2060,13 +2086,13 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
 
   @Override
   public List<HTableDescriptor> listTableDescriptorsByNamespace(String name) throws IOException {
-    getNamespaceDescriptor(name); // check that namespace exists
+    ensureNamespaceExists(name);
     return listTableDescriptors(name, null, null, true);
   }
 
   @Override
   public List<TableName> listTableNamesByNamespace(String name) throws IOException {
-    getNamespaceDescriptor(name); // check that namespace exists
+    ensureNamespaceExists(name);
     return listTableNames(name, null, true);
   }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/7030d218/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java
index 679e62a..2997172 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java
@@ -150,6 +150,28 @@ public class MasterCoprocessorHost
     });
   }
 
+  public void preGetNamespaceDescriptor(final String namespaceName)
+      throws IOException {
+    execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
+      @Override
+      public void call(MasterObserver oserver, ObserverContext<MasterCoprocessorEnvironment> ctx)
+          throws IOException {
+        oserver.preGetNamespaceDescriptor(ctx, namespaceName);
+      }
+    });
+  }
+
+  public void postGetNamespaceDescriptor(final NamespaceDescriptor ns)
+      throws IOException {
+    execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
+      @Override
+      public void call(MasterObserver oserver, ObserverContext<MasterCoprocessorEnvironment> ctx)
+          throws IOException {
+        oserver.postGetNamespaceDescriptor(ctx, ns);
+      }
+    });
+  }
+
   public boolean preListNamespaceDescriptors(final List<NamespaceDescriptor> descriptors)
       throws IOException {
     return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {

http://git-wip-us.apache.org/repos/asf/hbase/blob/7030d218/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 f959bb0..c7abb81 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
@@ -1207,6 +1207,12 @@ public class AccessController extends BaseMasterAndRegionObserver
   }
 
   @Override
+  public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx, String namespace)
+      throws IOException {
+    requireGlobalPermission("getNamespaceDescriptor", Action.ADMIN, namespace);
+  }
+
+  @Override
   public void postListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
       List<NamespaceDescriptor> descriptors) throws IOException {
     // Retains only those which passes authorization checks, as the checks weren't done as part

http://git-wip-us.apache.org/repos/asf/hbase/blob/7030d218/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java
index cca3496..3f5fe9c 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java
@@ -93,6 +93,8 @@ public class TestMasterObserver {
     private boolean postDeleteNamespaceCalled;
     private boolean preModifyNamespaceCalled;
     private boolean postModifyNamespaceCalled;
+    private boolean preGetNamespaceDescriptorCalled;
+    private boolean postGetNamespaceDescriptorCalled;
     private boolean preListNamespaceDescriptorsCalled;
     private boolean postListNamespaceDescriptorsCalled;
     private boolean preAddColumnCalled;
@@ -175,6 +177,8 @@ public class TestMasterObserver {
       postDeleteNamespaceCalled = false;
       preModifyNamespaceCalled = false;
       postModifyNamespaceCalled = false;
+      preGetNamespaceDescriptorCalled = false;
+      postGetNamespaceDescriptorCalled = false;
       preListNamespaceDescriptorsCalled = false;
       postListNamespaceDescriptorsCalled = false;
       preAddColumnCalled = false;
@@ -398,6 +402,23 @@ public class TestMasterObserver {
       return preModifyNamespaceCalled && !postModifyNamespaceCalled;
     }
 
+
+    @Override
+    public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+        String namespace) throws IOException {
+      preGetNamespaceDescriptorCalled = true;
+    }
+
+    @Override
+    public void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+        NamespaceDescriptor ns) throws IOException {
+      postGetNamespaceDescriptorCalled = true;
+    }
+
+    public boolean wasGetNamespaceDescriptorCalled() {
+      return preGetNamespaceDescriptorCalled && postGetNamespaceDescriptorCalled;
+    }
+
     @Override
     public void preListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
         List<NamespaceDescriptor> descriptors) throws IOException {
@@ -1424,6 +1445,8 @@ public class TestMasterObserver {
     assertTrue("Test namespace should be created", cp.wasCreateNamespaceCalled());
 
     assertNotNull(admin.getNamespaceDescriptor(testNamespace));
+    assertTrue("Test namespace descriptor should have been called",
+        cp.wasGetNamespaceDescriptorCalled());
 
     // turn off bypass, run the tests again
     cp.enableBypass(true);
@@ -1434,11 +1457,15 @@ public class TestMasterObserver {
         cp.preModifyNamespaceCalledOnly());
 
     assertNotNull(admin.getNamespaceDescriptor(testNamespace));
+    assertTrue("Test namespace descriptor should have been called",
+        cp.wasGetNamespaceDescriptorCalled());
 
     admin.deleteNamespace(testNamespace);
     assertTrue("Test namespace should not have been deleted", cp.preDeleteNamespaceCalledOnly());
 
     assertNotNull(admin.getNamespaceDescriptor(testNamespace));
+    assertTrue("Test namespace descriptor should have been called",
+        cp.wasGetNamespaceDescriptorCalled());
 
     cp.enableBypass(false);
     cp.resetStates();

http://git-wip-us.apache.org/repos/asf/hbase/blob/7030d218/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 e26a9ca..2ee1100 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
@@ -192,6 +192,21 @@ public class TestNamespaceCommands extends SecureTestUtil {
   }
 
   @Test
+  public void testGetNamespaceDescriptor() throws Exception {
+    AccessTestAction getNamespaceAction = new AccessTestAction() {
+      public Object run() throws Exception {
+        ACCESS_CONTROLLER.preGetNamespaceDescriptor(ObserverContext.createAndPrepare(CP_ENV, null),
+          TEST_NAMESPACE);
+        return null;
+      }
+    };
+    // verify that superuser or hbase admin can get the namespace descriptor.
+    verifyAllowed(getNamespaceAction, SUPERUSER, USER_NSP_ADMIN);
+    // all others should be denied
+    verifyDenied(getNamespaceAction, USER_NSP_WRITE, USER_CREATE, USER_RW);
+  }
+
+  @Test
   public void testListNamespaces() throws Exception {
     AccessTestAction listAction = new AccessTestAction() {
       @Override


[2/2] hbase git commit: HBASE-12674 Add permission check to getNamespaceDescriptor()

Posted by mb...@apache.org.
HBASE-12674 Add permission check to getNamespaceDescriptor()


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

Branch: refs/heads/branch-1
Commit: c4aee2e2836d671b6da7d6e7052aad78ed88f74f
Parents: 75cf81a
Author: Matteo Bertozzi <ma...@cloudera.com>
Authored: Thu Dec 11 16:55:42 2014 +0000
Committer: Matteo Bertozzi <ma...@cloudera.com>
Committed: Thu Dec 11 18:00:58 2014 +0000

----------------------------------------------------------------------
 .../BaseMasterAndRegionObserver.java            | 10 ++++++
 .../hbase/coprocessor/BaseMasterObserver.java   | 10 ++++++
 .../hbase/coprocessor/MasterObserver.java       | 18 +++++++++++
 .../org/apache/hadoop/hbase/master/HMaster.java | 32 ++++++++++++++++++--
 .../hbase/master/MasterCoprocessorHost.java     | 22 ++++++++++++++
 .../hbase/security/access/AccessController.java |  6 ++++
 .../hbase/coprocessor/TestMasterObserver.java   | 27 +++++++++++++++++
 .../security/access/TestNamespaceCommands.java  | 15 +++++++++
 8 files changed, 137 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/c4aee2e2/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java
index 5893b16..98c0563 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterAndRegionObserver.java
@@ -158,6 +158,16 @@ public abstract class BaseMasterAndRegionObserver extends BaseRegionObserver
   }
 
   @Override
+  public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      String namespace) throws IOException {
+  }
+
+  @Override
+  public void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      NamespaceDescriptor ns) throws IOException {
+  }
+
+  @Override
   public void preListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
       List<NamespaceDescriptor> descriptors) throws IOException {
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/c4aee2e2/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java
index 6c69f81..4748a1b 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/BaseMasterObserver.java
@@ -151,6 +151,16 @@ public class BaseMasterObserver implements MasterObserver {
   }
 
   @Override
+  public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      String namespace) throws IOException {
+  }
+
+  @Override
+  public void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      NamespaceDescriptor ns) throws IOException {
+  }
+
+  @Override
   public void preListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
       List<NamespaceDescriptor> descriptors) throws IOException {
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/c4aee2e2/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
index 9f0428b..2d99754 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java
@@ -789,6 +789,24 @@ public interface MasterObserver extends Coprocessor {
       NamespaceDescriptor ns) throws IOException;
 
   /**
+   * Called before a getNamespaceDescriptor request has been processed.
+   * @param ctx the environment to interact with the framework and master
+   * @param namespace the name of the namespace
+   * @throws IOException
+   */
+  void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      String namespace) throws IOException;
+
+  /**
+   * Called after a getNamespaceDescriptor request has been processed.
+   * @param ctx the environment to interact with the framework and master
+   * @param ns the NamespaceDescriptor
+   * @throws IOException
+   */
+  void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+      NamespaceDescriptor ns) throws IOException;
+
+  /**
    * Called before a listNamespaceDescriptors request has been processed.
    * @param ctx the environment to interact with the framework and master
    * @param descriptors an empty list, can be filled with what to return if bypassing

http://git-wip-us.apache.org/repos/asf/hbase/blob/c4aee2e2/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
index 7961e0e..9023092 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
@@ -1248,7 +1248,7 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
     }
 
     String namespace = hTableDescriptor.getTableName().getNamespaceAsString();
-    getNamespaceDescriptor(namespace); // ensure namespace exists
+    ensureNamespaceExists(namespace);
 
     HRegionInfo[] newRegions = getHRegionInfos(hTableDescriptor, splitKeys);
     checkInitialized();
@@ -2044,13 +2044,39 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
     }
   }
 
+  /**
+   * Ensure that the specified namespace exists, otherwise throws a NamespaceNotFoundException
+   *
+   * @param name the namespace to check
+   * @throws IOException if the namespace manager is not ready yet.
+   * @throws NamespaceNotFoundException if the namespace does not exists
+   */
+  private void ensureNamespaceExists(final String name)
+      throws IOException, NamespaceNotFoundException {
+    checkNamespaceManagerReady();
+    NamespaceDescriptor nsd = tableNamespaceManager.get(name);
+    if (nsd == null) {
+      throw new NamespaceNotFoundException(name);
+    }
+  }
+
   @Override
   public NamespaceDescriptor getNamespaceDescriptor(String name) throws IOException {
     checkNamespaceManagerReady();
+
+    if (cpHost != null) {
+      cpHost.preGetNamespaceDescriptor(name);
+    }
+
     NamespaceDescriptor nsd = tableNamespaceManager.get(name);
     if (nsd == null) {
       throw new NamespaceNotFoundException(name);
     }
+
+    if (cpHost != null) {
+      cpHost.postGetNamespaceDescriptor(nsd);
+    }
+
     return nsd;
   }
 
@@ -2076,13 +2102,13 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
 
   @Override
   public List<HTableDescriptor> listTableDescriptorsByNamespace(String name) throws IOException {
-    getNamespaceDescriptor(name); // check that namespace exists
+    ensureNamespaceExists(name);
     return listTableDescriptors(name, null, null, true);
   }
 
   @Override
   public List<TableName> listTableNamesByNamespace(String name) throws IOException {
-    getNamespaceDescriptor(name); // check that namespace exists
+    ensureNamespaceExists(name);
     return listTableNames(name, null, true);
   }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/c4aee2e2/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java
index 397434a..14c2568 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java
@@ -139,6 +139,28 @@ public class MasterCoprocessorHost
     });
   }
 
+  public void preGetNamespaceDescriptor(final String namespaceName)
+      throws IOException {
+    execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
+      @Override
+      public void call(MasterObserver oserver, ObserverContext<MasterCoprocessorEnvironment> ctx)
+          throws IOException {
+        oserver.preGetNamespaceDescriptor(ctx, namespaceName);
+      }
+    });
+  }
+
+  public void postGetNamespaceDescriptor(final NamespaceDescriptor ns)
+      throws IOException {
+    execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {
+      @Override
+      public void call(MasterObserver oserver, ObserverContext<MasterCoprocessorEnvironment> ctx)
+          throws IOException {
+        oserver.postGetNamespaceDescriptor(ctx, ns);
+      }
+    });
+  }
+
   public boolean preListNamespaceDescriptors(final List<NamespaceDescriptor> descriptors)
       throws IOException {
     return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() {

http://git-wip-us.apache.org/repos/asf/hbase/blob/c4aee2e2/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 9f382c6..5050afb 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
@@ -1185,6 +1185,12 @@ public class AccessController extends BaseMasterAndRegionObserver
   }
 
   @Override
+  public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx, String namespace)
+      throws IOException {
+    requireGlobalPermission("getNamespaceDescriptor", Action.ADMIN, namespace);
+  }
+
+  @Override
   public void postListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> ctx,
       List<NamespaceDescriptor> descriptors) throws IOException {
     // Retains only those which passes authorization checks, as the checks weren't done as part

http://git-wip-us.apache.org/repos/asf/hbase/blob/c4aee2e2/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java
index f99e9ae..419d7f4 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestMasterObserver.java
@@ -91,6 +91,8 @@ public class TestMasterObserver {
     private boolean postDeleteNamespaceCalled;
     private boolean preModifyNamespaceCalled;
     private boolean postModifyNamespaceCalled;
+    private boolean preGetNamespaceDescriptorCalled;
+    private boolean postGetNamespaceDescriptorCalled;
     private boolean preListNamespaceDescriptorsCalled;
     private boolean postListNamespaceDescriptorsCalled;
     private boolean preAddColumnCalled;
@@ -171,6 +173,8 @@ public class TestMasterObserver {
       postDeleteNamespaceCalled = false;
       preModifyNamespaceCalled = false;
       postModifyNamespaceCalled = false;
+      preGetNamespaceDescriptorCalled = false;
+      postGetNamespaceDescriptorCalled = false;
       preListNamespaceDescriptorsCalled = false;
       postListNamespaceDescriptorsCalled = false;
       preAddColumnCalled = false;
@@ -392,6 +396,23 @@ public class TestMasterObserver {
       return preModifyNamespaceCalled && !postModifyNamespaceCalled;
     }
 
+
+    @Override
+    public void preGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+        String namespace) throws IOException {
+      preGetNamespaceDescriptorCalled = true;
+    }
+
+    @Override
+    public void postGetNamespaceDescriptor(ObserverContext<MasterCoprocessorEnvironment> ctx,
+        NamespaceDescriptor ns) throws IOException {
+      postGetNamespaceDescriptorCalled = true;
+    }
+
+    public boolean wasGetNamespaceDescriptorCalled() {
+      return preGetNamespaceDescriptorCalled && postGetNamespaceDescriptorCalled;
+    }
+
     @Override
     public void preListNamespaceDescriptors(ObserverContext<MasterCoprocessorEnvironment> env,
         List<NamespaceDescriptor> descriptors) throws IOException {
@@ -1357,6 +1378,8 @@ public class TestMasterObserver {
     assertTrue("Test namespace should be created", cp.wasCreateNamespaceCalled());
 
     assertNotNull(admin.getNamespaceDescriptor(testNamespace));
+    assertTrue("Test namespace descriptor should have been called",
+        cp.wasGetNamespaceDescriptorCalled());
 
     // turn off bypass, run the tests again
     cp.enableBypass(true);
@@ -1367,11 +1390,15 @@ public class TestMasterObserver {
         cp.preModifyNamespaceCalledOnly());
 
     assertNotNull(admin.getNamespaceDescriptor(testNamespace));
+    assertTrue("Test namespace descriptor should have been called",
+        cp.wasGetNamespaceDescriptorCalled());
 
     admin.deleteNamespace(testNamespace);
     assertTrue("Test namespace should not have been deleted", cp.preDeleteNamespaceCalledOnly());
 
     assertNotNull(admin.getNamespaceDescriptor(testNamespace));
+    assertTrue("Test namespace descriptor should have been called",
+        cp.wasGetNamespaceDescriptorCalled());
 
     cp.enableBypass(false);
     cp.resetStates();

http://git-wip-us.apache.org/repos/asf/hbase/blob/c4aee2e2/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 1c1cb6d..80f5a97 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
@@ -191,6 +191,21 @@ public class TestNamespaceCommands extends SecureTestUtil {
   }
 
   @Test
+  public void testGetNamespaceDescriptor() throws Exception {
+    AccessTestAction getNamespaceAction = new AccessTestAction() {
+      public Object run() throws Exception {
+        ACCESS_CONTROLLER.preGetNamespaceDescriptor(ObserverContext.createAndPrepare(CP_ENV, null),
+          TEST_NAMESPACE);
+        return null;
+      }
+    };
+    // verify that superuser or hbase admin can get the namespace descriptor.
+    verifyAllowed(getNamespaceAction, SUPERUSER, USER_NSP_ADMIN);
+    // all others should be denied
+    verifyDenied(getNamespaceAction, USER_NSP_WRITE, USER_CREATE, USER_RW);
+  }
+
+  @Test
   public void testListNamespaces() throws Exception {
     AccessTestAction listAction = new AccessTestAction() {
       @Override