You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by el...@apache.org on 2017/01/23 23:01:54 UTC

[21/50] [abbrv] hbase git commit: HBASE-16867 Procedure V2 - Check ACLs for MasterRpcServices' queueLock() and lockHeartbeat().

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/HBASE-16961
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