diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlConstants.java hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlConstants.java index 2705765..9b84df7 100644 --- hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlConstants.java +++ hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlConstants.java @@ -52,4 +52,7 @@ public interface AccessControlConstants { /** Alternate cell ACL evaluation strategy: Cell ACL first, then table and CF */ public static final byte[] OP_ATTRIBUTE_ACL_STRATEGY_CELL_FIRST = new byte[] { 1 }; + /** Whether to preserve ACLS on truncate command. */ + public static final String PRESERVE_ACLS_ON_TRUNCATE = "hbase.preserve.acls.on.truncate"; + } diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java index 49aa7d7..08a5997 100644 --- hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java +++ hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java @@ -173,6 +173,8 @@ public class AccessController extends BaseMasterAndRegionObserver private Map scannerOwners = new MapMaker().weakKeys().makeMap(); + private Map> tableAcls; + // Provider for mapping principal names to Users private UserProvider userProvider; @@ -194,6 +196,8 @@ public class AccessController extends BaseMasterAndRegionObserver // This boolean having relevance only in the Master. private volatile boolean aclTabAvailable = false; + boolean shouldPreserveAcls; + public HRegion getRegion() { return regionEnv != null ? regionEnv.getRegion() : null; } @@ -818,6 +822,8 @@ public class AccessController extends BaseMasterAndRegionObserver shouldCheckExecPermission = conf.getBoolean(AccessControlConstants.EXEC_PERMISSION_CHECKS_KEY, AccessControlConstants.DEFAULT_EXEC_PERMISSION_CHECKS); + shouldPreserveAcls = conf.getBoolean(AccessControlConstants.PRESERVE_ACLS_ON_TRUNCATE, true); + cellFeaturesEnabled = HFile.getFormatVersion(conf) >= HFile.MIN_FORMAT_VERSION_WITH_TAGS; if (!cellFeaturesEnabled) { LOG.info("A minimum HFile version of " + HFile.MIN_FORMAT_VERSION_WITH_TAGS @@ -861,6 +867,8 @@ public class AccessController extends BaseMasterAndRegionObserver } else { throw new RuntimeException("Error obtaining TableAuthManager, zk found null."); } + + tableAcls = new MapMaker().weakValues().makeMap(); } public void stop(CoprocessorEnvironment env) { @@ -938,7 +946,24 @@ public class AccessController extends BaseMasterAndRegionObserver @Override public void preTruncateTable(ObserverContext c, TableName tableName) throws IOException { - requirePermission("truncateTable", tableName, null, null, Action.ADMIN, Action.CREATE); + requirePermission("truncateTable", tableName, null, null, Action.ADMIN); + List acls = AccessControlLists.getUserTablePermissions(c.getEnvironment() + .getConfiguration(), tableName); + if (acls != null) { + tableAcls.put(tableName, acls); + } + } + + @Override + public void postTruncateTable(ObserverContext ctx, + TableName tableName) throws IOException { + List perms = tableAcls.get(tableName); + if (perms != null) { + for (UserPermission perm : perms) { + AccessControlLists.addUserPermission(ctx.getEnvironment().getConfiguration(), perm); + } + } + tableAcls.remove(tableName); } @Override diff --git hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java index 3ed58cc..ea4b3ba 100644 --- hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java +++ hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java @@ -36,6 +36,7 @@ import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.hbase.Coprocessor; import org.apache.hadoop.hbase.CoprocessorEnvironment; +import org.apache.hadoop.hbase.HBaseIOException; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HConstants; @@ -334,8 +335,8 @@ public class TestAccessController extends SecureTestUtil { } }; - verifyAllowed(truncateTable, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER); - verifyDenied(truncateTable, USER_RW, USER_RO, USER_NONE); + verifyAllowed(truncateTable, SUPERUSER, USER_ADMIN); + verifyDenied(truncateTable, USER_RW, USER_RO, USER_NONE,USER_CREATE, USER_OWNER); } @Test @@ -2304,4 +2305,23 @@ public class TestAccessController extends SecureTestUtil { verifyAllowed(setNamespaceQuotaAction, SUPERUSER, USER_ADMIN); verifyDenied(setNamespaceQuotaAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER); } + + @Test + public void testTruncatePerms() throws Exception { + try { + List existingPerms = AccessControlClient.getUserPermissions(conf, + TEST_TABLE.getTableName().getNameAsString()); + assertTrue(existingPerms != null); + assertTrue(existingPerms.size() > 1); + TEST_UTIL.getHBaseAdmin().disableTable(TEST_TABLE.getTableName()); + TEST_UTIL.truncateTable(TEST_TABLE.getTableName()); + List perms = AccessControlClient.getUserPermissions(conf, + TEST_TABLE.getTableName().getNameAsString()); + assertTrue(perms != null); + assertEquals(existingPerms.size(), perms.size()); + } catch (Throwable e) { + throw new HBaseIOException(e); + } + } + }