HBASE-12674 Add permission check to getNamespaceDescriptor()
This commit is contained in:
parent
75cf81aae5
commit
c4aee2e283
|
@ -157,6 +157,16 @@ public abstract class BaseMasterAndRegionObserver extends BaseRegionObserver
|
|||
NamespaceDescriptor ns) throws IOException {
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
|
|
@ -150,6 +150,16 @@ public class BaseMasterObserver implements MasterObserver {
|
|||
public void postModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx, NamespaceDescriptor ns) throws IOException {
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
|
|
@ -788,6 +788,24 @@ public interface MasterObserver extends Coprocessor {
|
|||
void postModifyNamespace(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
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
|
||||
|
|
|
@ -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 {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamespaceDescriptor getNamespaceDescriptor(String name) throws IOException {
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -1184,6 +1184,12 @@ public class AccessController extends BaseMasterAndRegionObserver
|
|||
requireGlobalPermission("modifyNamespace", Action.ADMIN, ns.getName());
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -190,6 +190,21 @@ public class TestNamespaceCommands extends SecureTestUtil {
|
|||
verifyDenied(deleteNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW);
|
||||
}
|
||||
|
||||
@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() {
|
||||
|
|
Loading…
Reference in New Issue