diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java index 9a0d104..5b41716 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java @@ -155,7 +155,9 @@ public class AccessControlClient { } /** - * List all the userPermissions matching the given pattern. + * List all the userPermissions matching the given pattern. If pattern is null, the behavior is + * dependent on whether user has global admin privileges or not. If yes, the global permissions + * along with the list of superusers would be returned. Else, no rows get returned. * @param connection The Connection instance to use * @param tableRegex The regular expression string to match against * @return - returns an array of UserPermissions diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/security/Superusers.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/security/Superusers.java index adddd97..f1a3877 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/security/Superusers.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/security/Superusers.java @@ -100,4 +100,8 @@ public final class Superusers { } return false; } + + public static List getSuperUsers() { + return superUsers; + } } \ No newline at end of file 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 275d4da..dac744f 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 @@ -1105,7 +1105,7 @@ public class AccessController extends BaseMasterAndRegionObserver @Override public Void run() throws Exception { UserPermission userperm = new UserPermission(Bytes.toBytes(owner), - htd.getTableName(), null, Action.values()); + htd.getTableName(), null, Action.values()); AccessControlLists.addUserPermission(conf, userperm); return null; } @@ -1735,7 +1735,7 @@ public class AccessController extends BaseMasterAndRegionObserver Map> families = makeFamilyMap(family, qualifier); User user = getActiveUser(); AuthResult authResult = permissionGranted(OpType.CHECK_AND_DELETE, user, env, families, - Action.READ, Action.WRITE); + Action.READ, Action.WRITE); logResult(authResult); if (!authResult.isAllowed()) { if (cellFeaturesEnabled && !compatibleEarlyTermination) { @@ -1787,7 +1787,7 @@ public class AccessController extends BaseMasterAndRegionObserver Map> families = makeFamilyMap(family, qualifier); User user = getActiveUser(); AuthResult authResult = permissionGranted(OpType.INCREMENT_COLUMN_VALUE, user, env, families, - Action.WRITE); + Action.WRITE); if (!authResult.isAllowed() && cellFeaturesEnabled && !compatibleEarlyTermination) { authResult.setAllowed(checkCoveringPermission(OpType.INCREMENT_COLUMN_VALUE, env, row, families, HConstants.LATEST_TIMESTAMP, Action.WRITE)); @@ -1969,7 +1969,7 @@ public class AccessController extends BaseMasterAndRegionObserver LOG.trace("Carrying forward ACLs from " + oldCell + ": " + perms); } tags.add(new Tag(AccessControlLists.ACL_TAG_TYPE, - ProtobufUtil.toUsersAndPermissions(perms).toByteArray())); + ProtobufUtil.toUsersAndPermissions(perms).toByteArray())); } } @@ -2254,6 +2254,13 @@ public class AccessController extends BaseMasterAndRegionObserver return AccessControlLists.getUserPermissions(regionEnv.getConfiguration(), null); } }); + // Adding superusers explicitly to the result set as AccessControlLists do not store them. + // Also using acl as table name to be inline with the results of global admin and will + // help in avoiding any leakage of information about being superusers. + for (String user: Superusers.getSuperUsers()) { + perms.add(new UserPermission(user.getBytes(), AccessControlLists.ACL_TABLE_NAME, null, + Action.values())); + } } response = ResponseConverter.buildGetUserPermissionsResponse(perms); } else { 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 6d7a2ba..b474dd2 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 @@ -26,6 +26,7 @@ import static org.junit.Assert.fail; import java.io.IOException; import java.security.PrivilegedAction; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -101,6 +102,7 @@ import org.apache.hadoop.hbase.regionserver.Region; import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost; import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost; import org.apache.hadoop.hbase.regionserver.ScanType; +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.testclassification.LargeTests; @@ -344,7 +346,7 @@ public class TestAccessController extends SecureTestUtil { htd.addFamily(new HColumnDescriptor(TEST_FAMILY)); htd.addFamily(new HColumnDescriptor("fam_" + User.getCurrent().getShortName())); ACCESS_CONTROLLER.preModifyTable(ObserverContext.createAndPrepare(CP_ENV, null), - TEST_TABLE, htd); + TEST_TABLE, htd); return null; } }; @@ -434,7 +436,7 @@ public class TestAccessController extends SecureTestUtil { }; verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_CREATE, USER_OWNER, USER_ADMIN_CF, - USER_GROUP_CREATE, USER_GROUP_ADMIN); + USER_GROUP_CREATE, USER_GROUP_ADMIN); verifyDenied(action, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE); } @@ -664,7 +666,7 @@ public class TestAccessController extends SecureTestUtil { verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); verifyDenied(action, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, - USER_GROUP_WRITE, USER_GROUP_CREATE); + USER_GROUP_WRITE, USER_GROUP_CREATE); } @Test @@ -732,7 +734,7 @@ public class TestAccessController extends SecureTestUtil { private void verifyReadWrite(AccessTestAction action) throws Exception { verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW); verifyDenied(action, USER_NONE, USER_RO, USER_GROUP_ADMIN, USER_GROUP_CREATE, USER_GROUP_READ, - USER_GROUP_WRITE); + USER_GROUP_WRITE); } @Test @@ -1066,7 +1068,7 @@ public class TestAccessController extends SecureTestUtil { verifyAllowed(grantAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); verifyDenied(grantAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, - USER_GROUP_WRITE, USER_GROUP_CREATE); + USER_GROUP_WRITE, USER_GROUP_CREATE); try { verifyAllowed(revokeAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); verifyDenied(revokeAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, @@ -1331,6 +1333,11 @@ public class TestAccessController extends SecureTestUtil { } } + private boolean hasFoundUserPermission(List userPermissions, + List perms) { + return perms.containsAll(userPermissions); + } + private boolean hasFoundUserPermission(UserPermission userPermission, List perms) { return perms.contains(userPermission); } @@ -1582,10 +1589,17 @@ public class TestAccessController extends SecureTestUtil { } finally { acl.close(); } - UserPermission adminPerm = new UserPermission(Bytes.toBytes(USER_ADMIN.getShortName()), - AccessControlLists.ACL_TABLE_NAME, null, null, Bytes.toBytes("ACRW")); - assertTrue("Only global users and user admin has permission on table _acl_ per setup", - perms.size() == 5 && hasFoundUserPermission(adminPerm, perms)); + List adminPerms = new ArrayList(); + adminPerms.add(new UserPermission(Bytes.toBytes(USER_ADMIN.getShortName()), + AccessControlLists.ACL_TABLE_NAME, null, null, Bytes.toBytes("ACRW"))); + List superUsers = Superusers.getSuperUsers(); + for(String user: superUsers) { + adminPerms.add(new UserPermission(Bytes.toBytes(user), AccessControlLists.ACL_TABLE_NAME, + null, null, Action.values())); + } + assertTrue("Only super users, global users and user admin has permission on table hbase:acl " + + "per setup", perms.size() == 5 + superUsers.size() && + hasFoundUserPermission(adminPerms, perms)); } /** global operations */