You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2017/01/20 00:43:04 UTC
hbase git commit: HBASE-16867 Procedure V2 - Check ACLs for
MasterRpcServices' queueLock() and lockHeartbeat().
Repository: hbase
Updated Branches:
refs/heads/master 76dc957f6 -> 558a6bb9d
HBASE-16867 Procedure V2 - Check ACLs for MasterRpcServices' queueLock() and lockHeartbeat().
Change-Id: I03773059c169022318cf7953110bb022b6ad216d
Signed-off-by: Michael Stack <st...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/558a6bb9
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/558a6bb9
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/558a6bb9
Branch: refs/heads/master
Commit: 558a6bb9d71cde7fba240a8a454c32367f0ef4c0
Parents: 76dc957
Author: Apekshit Sharma <ap...@apache.org>
Authored: Mon Oct 17 21:03:49 2016 -0700
Committer: Michael Stack <st...@apache.org>
Committed: Thu Jan 19 16:42:57 2017 -0800
----------------------------------------------------------------------
.../hbase/security/access/AccessController.java | 46 +++++++++--
.../security/access/TestAccessController.java | 80 +++++++++++++++++++-
2 files changed, 116 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/558a6bb9/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 5011819..f68ae94 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
@@ -86,16 +86,13 @@ import org.apache.hadoop.hbase.io.hfile.HFile;
import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
import org.apache.hadoop.hbase.ipc.RpcServer;
import org.apache.hadoop.hbase.master.MasterServices;
+import org.apache.hadoop.hbase.master.locking.LockProcedure;
+import org.apache.hadoop.hbase.master.locking.LockProcedure.LockType;
import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
+import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
-import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.WALEntry;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.CleanupBulkLoadRequest;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.PrepareBulkLoadRequest;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.SnapshotDescription;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas;
import org.apache.hadoop.hbase.regionserver.InternalScanner;
import org.apache.hadoop.hbase.regionserver.MiniBatchOperationInProgress;
import org.apache.hadoop.hbase.regionserver.Region;
@@ -111,6 +108,11 @@ import org.apache.hadoop.hbase.security.Superusers;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.security.UserProvider;
import org.apache.hadoop.hbase.security.access.Permission.Action;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.WALEntry;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.CleanupBulkLoadRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.PrepareBulkLoadRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.SnapshotDescription;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.Quotas;
import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
import org.apache.hadoop.hbase.util.ByteRange;
import org.apache.hadoop.hbase.util.Bytes;
@@ -2739,4 +2741,36 @@ public class AccessController extends BaseMasterAndRegionObserver
String regex) throws IOException {
requirePermission(getActiveUser(ctx), "listReplicationPeers", Action.ADMIN);
}
+
+ @Override
+ public void preRequestLock(ObserverContext<MasterCoprocessorEnvironment> ctx, String namespace,
+ TableName tableName, HRegionInfo[] regionInfos, LockType type, String description)
+ throws IOException {
+ // There are operations in the CREATE and ADMIN domain which may require lock, READ
+ // or WRITE. So for any lock request, we check for these two perms irrespective of lock type.
+ String reason = String.format("Lock %s, description=%s", type, description);
+ checkLockPermissions(getActiveUser(ctx), namespace, tableName, regionInfos, reason);
+ }
+
+ @Override
+ public void preLockHeartbeat(ObserverContext<MasterCoprocessorEnvironment> ctx,
+ LockProcedure proc, boolean keepAlive) throws IOException {
+ String reason = "Heartbeat for lock " + proc.getProcId();
+ checkLockPermissions(getActiveUser(ctx), null, proc.getTableName(), null, reason);
+ }
+
+ private void checkLockPermissions(User user, String namespace,
+ TableName tableName, HRegionInfo[] regionInfos, String reason)
+ throws IOException {
+ if (namespace != null && !namespace.isEmpty()) {
+ requireNamespacePermission(user, reason, namespace, Action.ADMIN, Action.CREATE);
+ } else if (tableName != null || (regionInfos != null && regionInfos.length > 0)) {
+ // So, either a table or regions op. If latter, check perms ons table.
+ TableName tn = tableName != null? tableName: regionInfos[0].getTable();
+ requireTablePermission(user, reason, tn, null, null,
+ Action.ADMIN, Action.CREATE);
+ } else {
+ throw new DoNotRetryIOException("Invalid lock level when requesting permissions.");
+ }
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/hbase/blob/558a6bb9/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
index 5dcea53..8685b44 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java
@@ -92,10 +92,11 @@ import org.apache.hadoop.hbase.io.hfile.CacheConfig;
import org.apache.hadoop.hbase.io.hfile.HFile;
import org.apache.hadoop.hbase.io.hfile.HFileContext;
import org.apache.hadoop.hbase.io.hfile.HFileContextBuilder;
-import org.apache.hadoop.hbase.shaded.ipc.protobuf.generated.TestProcedureProtos;
import org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles;
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
+import org.apache.hadoop.hbase.master.locking.LockProcedure;
+import org.apache.hadoop.hbase.master.locking.LockProcedure.LockType;
import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
import org.apache.hadoop.hbase.master.procedure.TableProcedureInterface;
import org.apache.hadoop.hbase.procedure2.Procedure;
@@ -105,8 +106,6 @@ import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsRequest;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.SnapshotDescription;
-import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos.ProcedureState;
import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
import org.apache.hadoop.hbase.regionserver.Region;
@@ -117,6 +116,9 @@ import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
import org.apache.hadoop.hbase.security.Superusers;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.security.access.Permission.Action;
+import org.apache.hadoop.hbase.shaded.ipc.protobuf.generated.TestProcedureProtos;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.SnapshotDescription;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos.ProcedureState;
import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.apache.hadoop.hbase.testclassification.SecurityTests;
import org.apache.hadoop.hbase.util.Bytes;
@@ -127,6 +129,7 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
+import org.mockito.Mockito;
import com.google.protobuf.BlockingRpcChannel;
import com.google.protobuf.RpcCallback;
@@ -2976,4 +2979,73 @@ public class TestAccessController extends SecureTestUtil {
verifyAllowed(action, SUPERUSER, USER_ADMIN);
verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
}
-}
+
+ @Test
+ public void testRemoteLocks() throws Exception {
+ String namespace = "preQueueNs";
+ final TableName tableName = TableName.valueOf(namespace, "testTable");
+ HRegionInfo[] regionInfos = new HRegionInfo[] {new HRegionInfo(tableName)};
+
+ // Setup Users
+ // User will be granted ADMIN and CREATE on namespace. Should be denied before grant.
+ User namespaceUser = User.createUserForTesting(conf, "qLNSUser", new String[0]);
+ // User will be granted ADMIN and CREATE on table. Should be denied before grant.
+ User tableACUser = User.createUserForTesting(conf, "qLTableACUser", new String[0]);
+ // User will be granted READ, WRITE, EXECUTE on table. Should be denied.
+ User tableRWXUser = User.createUserForTesting(conf, "qLTableRWXUser", new String[0]);
+ grantOnTable(TEST_UTIL, tableRWXUser.getShortName(), tableName, null, null,
+ Action.READ, Action.WRITE, Action.EXEC);
+ // User with global READ, WRITE, EXECUTE should be denied lock access.
+ User globalRWXUser = User.createUserForTesting(conf, "qLGlobalRWXUser", new String[0]);
+ grantGlobal(TEST_UTIL, globalRWXUser.getShortName(), Action.READ, Action.WRITE, Action.EXEC);
+
+ AccessTestAction namespaceLockAction = new AccessTestAction() {
+ @Override public Object run() throws Exception {
+ ACCESS_CONTROLLER.preRequestLock(ObserverContext.createAndPrepare(CP_ENV, null), namespace,
+ null, null, LockType.EXCLUSIVE, null);
+ return null;
+ }
+ };
+ verifyAllowed(namespaceLockAction, SUPERUSER, USER_ADMIN);
+ verifyDenied(namespaceLockAction, globalRWXUser, tableACUser, namespaceUser, tableRWXUser);
+ grantOnNamespace(TEST_UTIL, namespaceUser.getShortName(), namespace, Action.ADMIN);
+ verifyAllowed(namespaceLockAction, namespaceUser);
+
+ AccessTestAction tableLockAction = new AccessTestAction() {
+ @Override public Object run() throws Exception {
+ ACCESS_CONTROLLER.preRequestLock(ObserverContext.createAndPrepare(CP_ENV, null),
+ null, tableName, null, LockType.EXCLUSIVE, null);
+ return null;
+ }
+ };
+ verifyAllowed(tableLockAction, SUPERUSER, USER_ADMIN, namespaceUser);
+ verifyDenied(tableLockAction, globalRWXUser, tableACUser, tableRWXUser);
+ grantOnTable(TEST_UTIL, tableACUser.getShortName(), tableName, null, null,
+ Action.ADMIN, Action.CREATE);
+ verifyAllowed(tableLockAction, tableACUser);
+
+ AccessTestAction regionsLockAction = new AccessTestAction() {
+ @Override public Object run() throws Exception {
+ ACCESS_CONTROLLER.preRequestLock(ObserverContext.createAndPrepare(CP_ENV, null),
+ null, null, regionInfos, LockType.EXCLUSIVE, null);
+ return null;
+ }
+ };
+ verifyAllowed(regionsLockAction, SUPERUSER, USER_ADMIN, namespaceUser, tableACUser);
+ verifyDenied(regionsLockAction, globalRWXUser, tableRWXUser);
+
+ // Test heartbeats
+ // Create a lock procedure and try sending heartbeat to it. It doesn't matter how the lock
+ // was created, we just need namespace from the lock's tablename.
+ LockProcedure proc = new LockProcedure(conf, tableName, LockType.EXCLUSIVE, "test", null);
+ AccessTestAction regionLockHeartbeatAction = new AccessTestAction() {
+ @Override public Object run() throws Exception {
+ ACCESS_CONTROLLER.preLockHeartbeat(ObserverContext.createAndPrepare(CP_ENV, null),
+ proc, false);
+ return null;
+ }
+ };
+ verifyAllowed(regionLockHeartbeatAction, SUPERUSER, USER_ADMIN, namespaceUser, tableACUser);
+ verifyDenied(regionLockHeartbeatAction, globalRWXUser, tableRWXUser);
+ }
+}
\ No newline at end of file