diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java index 5a058592aa3..f80a4607854 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java @@ -53,6 +53,7 @@ import org.apache.hadoop.hbase.replication.ReplicationException; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.replication.SyncReplicationState; +import org.apache.hadoop.hbase.security.access.UserPermission; import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException; import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException; import org.apache.hadoop.hbase.snapshot.SnapshotCreationException; @@ -2833,4 +2834,23 @@ public interface Admin extends Abortable, Closeable { * no quota information on that table. */ SpaceQuotaSnapshotView getCurrentSpaceQuotaSnapshot(TableName tableName) throws IOException; + + /** + * Grants user specific permissions + * + * @param userPermission user and permissions + * @param mergeExistingPermissions If set to false, later granted permissions will override + * previous granted permissions. otherwise, it'll merge with previous granted + * permissions. + * @throws IOException if a remote or network exception occurs + */ + void grant(UserPermission userPermission, boolean mergeExistingPermissions) throws IOException; + + /** + * Revokes user specific permissions + * + * @param userPermission user and permissions + * @throws IOException if a remote or network exception occurs + */ + void revoke(UserPermission userPermission) throws IOException; } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java index 13e819573e7..3a5aef14b17 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java @@ -43,6 +43,7 @@ import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshotView; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.replication.SyncReplicationState; +import org.apache.hadoop.hbase.security.access.UserPermission; import org.apache.yetus.audience.InterfaceAudience; /** @@ -1324,4 +1325,19 @@ public interface AsyncAdmin { */ CompletableFuture getCurrentSpaceQuotaSnapshot( TableName tableName); + + /** + * Grants user specific permissions + * @param userPermission user and permissions + * @param mergeExistingPermissions If set to false, later granted permissions will override + * previous granted permissions. otherwise, it'll merge with previous granted + * permissions. + */ + CompletableFuture grant(UserPermission userPermission, boolean mergeExistingPermissions); + + /** + * Revokes user specific permissions + * @param userPermission user and permissions + */ + CompletableFuture revoke(UserPermission userPermission); } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java index edcf0dc86ec..356a42532b0 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java @@ -42,6 +42,7 @@ import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.replication.SyncReplicationState; +import org.apache.hadoop.hbase.security.access.UserPermission; import org.apache.yetus.audience.InterfaceAudience; /** @@ -796,4 +797,15 @@ class AsyncHBaseAdmin implements AsyncAdmin { public CompletableFuture getCurrentSpaceQuotaSnapshot(TableName tableName) { return wrap(rawAdmin.getCurrentSpaceQuotaSnapshot(tableName)); } + + @Override + public CompletableFuture grant(UserPermission userPermission, + boolean mergeExistingPermissions) { + return wrap(rawAdmin.grant(userPermission, mergeExistingPermissions)); + } + + @Override + public CompletableFuture revoke(UserPermission userPermission) { + return wrap(rawAdmin.revoke(userPermission)); + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java index 70f058805eb..5df3c07c033 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java @@ -92,6 +92,7 @@ import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos; import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos; import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.ClientService.BlockingInterface; @@ -1774,6 +1775,18 @@ class ConnectionImplementation implements ClusterConnection, Closeable { IsRpcThrottleEnabledRequest request) throws ServiceException { return stub.isRpcThrottleEnabled(controller, request); } + + @Override + public AccessControlProtos.GrantResponse grant(RpcController controller, + AccessControlProtos.GrantRequest request) throws ServiceException { + return stub.grant(controller, request); + } + + @Override + public AccessControlProtos.RevokeResponse revoke(RpcController controller, + AccessControlProtos.RevokeRequest request) throws ServiceException { + return stub.revoke(controller, request); + } }; } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java index d38cc2addff..769ddd79627 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java @@ -91,6 +91,8 @@ import org.apache.hadoop.hbase.replication.ReplicationException; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.replication.SyncReplicationState; +import org.apache.hadoop.hbase.security.access.ShadedAccessControlUtil; +import org.apache.hadoop.hbase.security.access.UserPermission; import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils; import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException; import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException; @@ -113,6 +115,8 @@ import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.AdminService; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearCompactionQueuesRequest; @@ -4464,4 +4468,30 @@ public class HBaseAdmin implements Admin { } }); } + + @Override + public void grant(UserPermission userPermission, boolean mergeExistingPermissions) + throws IOException { + executeCallable(new MasterCallable(getConnection(), getRpcControllerFactory()) { + @Override + protected Void rpcCall() throws Exception { + GrantRequest req = + ShadedAccessControlUtil.buildGrantRequest(userPermission, mergeExistingPermissions); + this.master.grant(getRpcController(), req); + return null; + } + }); + } + + @Override + public void revoke(UserPermission userPermission) throws IOException { + executeCallable(new MasterCallable(getConnection(), getRpcControllerFactory()) { + @Override + protected Void rpcCall() throws Exception { + RevokeRequest req = ShadedAccessControlUtil.buildRevokeRequest(userPermission); + this.master.revoke(getRpcController(), req); + return null; + } + }); + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java index 914dcc49a29..73efe32157b 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java @@ -82,6 +82,8 @@ import org.apache.hadoop.hbase.replication.ReplicationException; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.replication.SyncReplicationState; +import org.apache.hadoop.hbase.security.access.ShadedAccessControlUtil; +import org.apache.hadoop.hbase.security.access.UserPermission; import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils; import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException; import org.apache.hadoop.hbase.snapshot.SnapshotCreationException; @@ -101,6 +103,10 @@ import org.apache.hbase.thirdparty.io.netty.util.TimerTask; import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.AdminService; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearCompactionQueuesRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearCompactionQueuesResponse; @@ -3712,4 +3718,23 @@ class RawAsyncHBaseAdmin implements AsyncAdmin { .filter(s -> s.getTableName().equals(protoTableName)).findFirst() .map(s -> SpaceQuotaSnapshot.toSpaceQuotaSnapshot(s.getSnapshot())).orElse(null)); } + + @Override + public CompletableFuture grant(UserPermission userPermission, + boolean mergeExistingPermissions) { + return this. newMasterCaller() + .action((controller, stub) -> this. call(controller, + stub, ShadedAccessControlUtil.buildGrantRequest(userPermission, mergeExistingPermissions), + (s, c, req, done) -> s.grant(c, req, done), resp -> null)) + .call(); + } + + @Override + public CompletableFuture revoke(UserPermission userPermission) { + return this. newMasterCaller() + .action((controller, stub) -> this. call(controller, + stub, ShadedAccessControlUtil.buildRevokeRequest(userPermission), + (s, c, req, done) -> s.revoke(c, req, done), resp -> null)) + .call(); + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ShortCircuitMasterConnection.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ShortCircuitMasterConnection.java index 197f98ba01b..02935548156 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ShortCircuitMasterConnection.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ShortCircuitMasterConnection.java @@ -20,6 +20,11 @@ package org.apache.hadoop.hbase.client; import org.apache.yetus.audience.InterfaceAudience; import org.apache.hbase.thirdparty.com.google.protobuf.RpcController; import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; + +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.CoprocessorServiceRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.CoprocessorServiceResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AbortProcedureRequest; @@ -663,4 +668,16 @@ public class ShortCircuitMasterConnection implements MasterKeepAliveConnection { IsRpcThrottleEnabledRequest request) throws ServiceException { return stub.isRpcThrottleEnabled(controller, request); } + + @Override + public GrantResponse grant(RpcController controller, GrantRequest request) + throws ServiceException { + return stub.grant(controller, request); + } + + @Override + public RevokeResponse revoke(RpcController controller, RevokeRequest request) + throws ServiceException { + return stub.revoke(controller, request); + } } 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 981db767c87..1031cfe5b5d 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 @@ -94,10 +94,9 @@ public class AccessControlClient { final String userName, final byte[] family, final byte[] qual, boolean mergeExistingPermissions, final Permission.Action... actions) throws Throwable { // TODO: Priority is not used. - try (Table table = connection.getTable(ACL_TABLE_NAME)) { - AccessControlUtil.grant(null, getAccessControlServiceStub(table), userName, tableName, - family, qual, mergeExistingPermissions, actions); - } + UserPermission userPermission = + new UserPermission(userName, new TablePermission(tableName, family, qual, actions)); + connection.getAdmin().grant(userPermission, mergeExistingPermissions); } /** @@ -129,11 +128,9 @@ public class AccessControlClient { */ private static void grant(Connection connection, final String namespace, final String userName, boolean mergeExistingPermissions, final Permission.Action... actions) throws Throwable { - // TODO: Pass an rpcController. - try (Table table = connection.getTable(ACL_TABLE_NAME)) { - AccessControlUtil.grant(null, getAccessControlServiceStub(table), userName, namespace, - mergeExistingPermissions, actions); - } + UserPermission userPermission = + new UserPermission(userName, new NamespacePermission(namespace, actions)); + connection.getAdmin().grant(userPermission, mergeExistingPermissions); } /** @@ -152,7 +149,7 @@ public class AccessControlClient { } /** - * Grants permission on the specified namespace for the specified user. + * Grant global permissions for the specified user. * @param connection * @param userName * @param mergeExistingPermissions If set to false, later granted permissions will override @@ -163,11 +160,8 @@ public class AccessControlClient { */ private static void grant(Connection connection, final String userName, boolean mergeExistingPermissions, final Permission.Action... actions) throws Throwable { - // TODO: Pass an rpcController - try (Table table = connection.getTable(ACL_TABLE_NAME)) { - AccessControlUtil.grant(null, getAccessControlServiceStub(table), userName, - mergeExistingPermissions, actions); - } + UserPermission userPermission = new UserPermission(userName, new GlobalPermission(actions)); + connection.getAdmin().grant(userPermission, mergeExistingPermissions); } /** @@ -204,19 +198,13 @@ public class AccessControlClient { public static void revoke(Connection connection, final TableName tableName, final String username, final byte[] family, final byte[] qualifier, final Permission.Action... actions) throws Throwable { - /** TODO: Pass an rpcController - HBaseRpcController controller - = ((ClusterConnection) connection).getRpcControllerFactory().newController(); - controller.setPriority(tableName); - */ - try (Table table = connection.getTable(ACL_TABLE_NAME)) { - AccessControlUtil.revoke(null, getAccessControlServiceStub(table), username, tableName, - family, qualifier, actions); - } + UserPermission userPermission = + new UserPermission(username, new TablePermission(tableName, family, qualifier, actions)); + connection.getAdmin().revoke(userPermission); } /** - * Revokes the permission on the table for the specified user. + * Revokes the permission on the namespace for the specified user. * @param connection The Connection instance to use * @param namespace * @param userName @@ -225,14 +213,9 @@ public class AccessControlClient { */ public static void revoke(Connection connection, final String namespace, final String userName, final Permission.Action... actions) throws Throwable { - /** TODO: Pass an rpcController - HBaseRpcController controller - = ((ClusterConnection) connection).getRpcControllerFactory().newController(); - */ - try (Table table = connection.getTable(ACL_TABLE_NAME)) { - AccessControlUtil.revoke(null, getAccessControlServiceStub(table), userName, namespace, - actions); - } + UserPermission userPermission = + new UserPermission(userName, new NamespacePermission(namespace, actions)); + connection.getAdmin().revoke(userPermission); } /** @@ -241,13 +224,8 @@ public class AccessControlClient { */ public static void revoke(Connection connection, final String userName, final Permission.Action... actions) throws Throwable { - /** TODO: Pass an rpc controller. - HBaseRpcController controller - = ((ClusterConnection) connection).getRpcControllerFactory().newController(); - */ - try (Table table = connection.getTable(ACL_TABLE_NAME)) { - AccessControlUtil.revoke(null, getAccessControlServiceStub(table), userName, actions); - } + UserPermission userPermission = new UserPermission(userName, new GlobalPermission(actions)); + connection.getAdmin().revoke(userPermission); } /** diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlUtil.java index b37440ccf85..4bae9430886 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlUtil.java @@ -25,6 +25,7 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Admin; import org.apache.yetus.audience.InterfaceAudience; import org.apache.hadoop.hbase.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos; @@ -490,7 +491,9 @@ public class AccessControlUtil { * @param userShortName the short name of the user to grant permissions * @param actions the permissions to be granted * @throws ServiceException + * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead. */ + @Deprecated public static void grant(RpcController controller, AccessControlService.BlockingInterface protocol, String userShortName, boolean mergeExistingPermissions, Permission.Action... actions) throws ServiceException { @@ -517,7 +520,9 @@ public class AccessControlUtil { * @param q optional qualifier * @param actions the permissions to be granted * @throws ServiceException + * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead. */ + @Deprecated public static void grant(RpcController controller, AccessControlService.BlockingInterface protocol, String userShortName, TableName tableName, byte[] f, byte[] q, boolean mergeExistingPermissions, Permission.Action... actions) @@ -543,7 +548,9 @@ public class AccessControlUtil { * @param namespace the short name of the user to grant permissions * @param actions the permissions to be granted * @throws ServiceException + * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead. */ + @Deprecated public static void grant(RpcController controller, AccessControlService.BlockingInterface protocol, String userShortName, String namespace, boolean mergeExistingPermissions, Permission.Action... actions) throws ServiceException { @@ -567,7 +574,9 @@ public class AccessControlUtil { * @param userShortName the short name of the user to revoke permissions * @param actions the permissions to be revoked * @throws ServiceException on failure + * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead. */ + @Deprecated public static void revoke(RpcController controller, AccessControlService.BlockingInterface protocol, String userShortName, Permission.Action... actions) throws ServiceException { @@ -595,7 +604,9 @@ public class AccessControlUtil { * @param q optional qualifier * @param actions the permissions to be revoked * @throws ServiceException on failure + * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead. */ + @Deprecated public static void revoke(RpcController controller, AccessControlService.BlockingInterface protocol, String userShortName, TableName tableName, byte[] f, byte[] q, Permission.Action... actions) throws ServiceException { @@ -620,7 +631,9 @@ public class AccessControlUtil { * @param namespace optional table name * @param actions the permissions to be revoked * @throws ServiceException on failure + * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead. */ + @Deprecated public static void revoke(RpcController controller, AccessControlService.BlockingInterface protocol, String userShortName, String namespace, Permission.Action... actions) throws ServiceException { diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java index 7e36656f32d..67fdba344a7 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/ShadedAccessControlUtil.java @@ -18,20 +18,21 @@ package org.apache.hadoop.hbase.security.access; - -import org.apache.hbase.thirdparty.com.google.common.collect.ArrayListMultimap; -import org.apache.hbase.thirdparty.com.google.common.collect.ListMultimap; -import org.apache.hadoop.hbase.TableName; -import org.apache.yetus.audience.InterfaceAudience; -import org.apache.hadoop.hbase.security.access.Permission.Action; -import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos; -import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; -import org.apache.hbase.thirdparty.com.google.protobuf.ByteString; - import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.security.access.Permission.Action; +import org.apache.yetus.audience.InterfaceAudience; + +import org.apache.hbase.thirdparty.com.google.common.collect.ArrayListMultimap; +import org.apache.hbase.thirdparty.com.google.common.collect.ListMultimap; +import org.apache.hbase.thirdparty.com.google.protobuf.ByteString; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; /** * Convert protobuf objects in AccessControl.proto under hbase-protocol-shaded to user-oriented @@ -49,20 +50,18 @@ public class ShadedAccessControlUtil { /** * Convert a client user permission to a user permission shaded proto. */ - public static - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action - toPermissionAction(Permission.Action action) { + public static AccessControlProtos.Permission.Action toPermissionAction(Permission.Action action) { switch (action) { - case READ: - return org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action.READ; - case WRITE: - return org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action.WRITE; - case EXEC: - return org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action.EXEC; - case CREATE: - return org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action.CREATE; - case ADMIN: - return org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action.ADMIN; + case READ: + return AccessControlProtos.Permission.Action.READ; + case WRITE: + return AccessControlProtos.Permission.Action.WRITE; + case EXEC: + return AccessControlProtos.Permission.Action.EXEC; + case CREATE: + return AccessControlProtos.Permission.Action.CREATE; + case ADMIN: + return AccessControlProtos.Permission.Action.ADMIN; } throw new IllegalArgumentException("Unknown action value " + action.name()); } @@ -70,8 +69,7 @@ public class ShadedAccessControlUtil { /** * Convert a Permission.Action shaded proto to a client Permission.Action object. */ - public static Permission.Action toPermissionAction( - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action action) { + public static Permission.Action toPermissionAction(AccessControlProtos.Permission.Action action) { switch (action) { case READ: return Permission.Action.READ; @@ -94,9 +92,9 @@ public class ShadedAccessControlUtil { * @return the converted list of Actions */ public static List toPermissionActions( - List protoActions) { + List protoActions) { List actions = new ArrayList<>(protoActions.size()); - for (org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action a : protoActions) { + for (AccessControlProtos.Permission.Action a : protoActions) { actions.add(toPermissionAction(a)); } return actions; @@ -163,20 +161,15 @@ public class ShadedAccessControlUtil { * @param perm the client Permission * @return the protobuf Permission */ - public static org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission - toPermission(Permission perm) { - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Builder ret = - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission - .newBuilder(); + public static AccessControlProtos.Permission toPermission(Permission perm) { + AccessControlProtos.Permission.Builder ret = AccessControlProtos.Permission.newBuilder(); if (perm instanceof NamespacePermission) { NamespacePermission nsPerm = (NamespacePermission) perm; - ret.setType( - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Type.Namespace); - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.NamespacePermission.Builder builder = - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.NamespacePermission - .newBuilder(); + ret.setType(AccessControlProtos.Permission.Type.Namespace); + AccessControlProtos.NamespacePermission.Builder builder = + AccessControlProtos.NamespacePermission.newBuilder(); builder.setNamespaceName(org.apache.hbase.thirdparty.com.google.protobuf.ByteString - .copyFromUtf8(nsPerm.getNamespace())); + .copyFromUtf8(nsPerm.getNamespace())); Permission.Action[] actions = perm.getActions(); if (actions != null) { for (Permission.Action a : actions) { @@ -186,11 +179,9 @@ public class ShadedAccessControlUtil { ret.setNamespacePermission(builder); } else if (perm instanceof TablePermission) { TablePermission tablePerm = (TablePermission) perm; - ret.setType( - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Type.Table); - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.TablePermission.Builder builder = - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.TablePermission - .newBuilder(); + ret.setType(AccessControlProtos.Permission.Type.Table); + AccessControlProtos.TablePermission.Builder builder = + AccessControlProtos.TablePermission.newBuilder(); builder.setTableName(toProtoTableName(tablePerm.getTableName())); if (tablePerm.hasFamily()) { builder.setFamily(ByteString.copyFrom(tablePerm.getFamily())); @@ -207,11 +198,9 @@ public class ShadedAccessControlUtil { ret.setTablePermission(builder); } else { // perm.getAccessScope() == Permission.Scope.GLOBAL - ret.setType( - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Type.Global); - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GlobalPermission.Builder builder = - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GlobalPermission - .newBuilder(); + ret.setType(AccessControlProtos.Permission.Type.Global); + AccessControlProtos.GlobalPermission.Builder builder = + AccessControlProtos.GlobalPermission.newBuilder(); Permission.Action[] actions = perm.getActions(); if (actions != null) { for (Permission.Action a : actions) { @@ -230,9 +219,9 @@ public class ShadedAccessControlUtil { * @return the converted UserPermission */ public static ListMultimap toUserTablePermissions( - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions proto) { + AccessControlProtos.UsersAndPermissions proto) { ListMultimap perms = ArrayListMultimap.create(); - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions.UserPermissions userPerm; + AccessControlProtos.UsersAndPermissions.UserPermissions userPerm; for (int i = 0; i < proto.getUserPermissionsCount(); i++) { userPerm = proto.getUserPermissions(i); for (int j = 0; j < userPerm.getPermissionsCount(); j++) { @@ -249,16 +238,13 @@ public class ShadedAccessControlUtil { * @param perm the list of user and table permissions * @return the protobuf UserTablePermissions */ - public static - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions + public static AccessControlProtos.UsersAndPermissions toUserTablePermissions(ListMultimap perm) { - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions.Builder builder = - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions - .newBuilder(); + AccessControlProtos.UsersAndPermissions.Builder builder = + AccessControlProtos.UsersAndPermissions.newBuilder(); for (Map.Entry> entry : perm.asMap().entrySet()) { - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions.UserPermissions.Builder userPermBuilder = - org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions.UserPermissions - .newBuilder(); + AccessControlProtos.UsersAndPermissions.UserPermissions.Builder userPermBuilder = + AccessControlProtos.UsersAndPermissions.UserPermissions.newBuilder(); userPermBuilder.setUser(ByteString.copyFromUtf8(entry.getKey())); for (UserPermission userPerm : entry.getValue()) { userPermBuilder.addPermissions(toPermission(userPerm.getPermission())); @@ -267,4 +253,34 @@ public class ShadedAccessControlUtil { } return builder.build(); } + + /** + * Converts a user permission proto to a client user permission object. + * @param proto the protobuf UserPermission + * @return the converted UserPermission + */ + public static UserPermission toUserPermission(AccessControlProtos.UserPermission proto) { + return new UserPermission(proto.getUser().toStringUtf8(), toPermission(proto.getPermission())); + } + + /** + * Convert a client user permission to a user permission proto + * @param perm the client UserPermission + * @return the protobuf UserPermission + */ + public static AccessControlProtos.UserPermission toUserPermission(UserPermission perm) { + return AccessControlProtos.UserPermission.newBuilder() + .setUser(ByteString.copyFromUtf8(perm.getUser())) + .setPermission(toPermission(perm.getPermission())).build(); + } + + public static GrantRequest buildGrantRequest(UserPermission userPermission, + boolean mergeExistingPermissions) { + return GrantRequest.newBuilder().setUserPermission(toUserPermission(userPermission)) + .setMergeExistingPermissions(mergeExistingPermissions).build(); + } + + public static RevokeRequest buildRevokeRequest(UserPermission userPermission) { + return RevokeRequest.newBuilder().setUserPermission(toUserPermission(userPermission)).build(); + } } diff --git a/hbase-protocol-shaded/src/main/protobuf/Master.proto b/hbase-protocol-shaded/src/main/protobuf/Master.proto index b1ed94f55d7..ec0b5439cfa 100644 --- a/hbase-protocol-shaded/src/main/protobuf/Master.proto +++ b/hbase-protocol-shaded/src/main/protobuf/Master.proto @@ -36,6 +36,7 @@ import "Procedure.proto"; import "Quota.proto"; import "Replication.proto"; import "Snapshot.proto"; +import "AccessControl.proto"; /* Column-level protobufs */ @@ -1014,6 +1015,10 @@ service MasterService { /** Get if is rpc throttled enabled */ rpc IsRpcThrottleEnabled (IsRpcThrottleEnabledRequest) returns (IsRpcThrottleEnabledResponse); + + rpc Grant(GrantRequest) returns (GrantResponse); + + rpc Revoke(RevokeRequest) returns (RevokeResponse); } // HBCK Service definitions. diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java index 63ed125648f..68e69b95035 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java @@ -37,6 +37,7 @@ import org.apache.hadoop.hbase.net.Address; import org.apache.hadoop.hbase.quotas.GlobalQuotaSettings; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.SyncReplicationState; +import org.apache.hadoop.hbase.security.access.UserPermission; import org.apache.yetus.audience.InterfaceAudience; import org.apache.yetus.audience.InterfaceStability; @@ -1573,4 +1574,42 @@ public interface MasterObserver { default void postIsRpcThrottleEnabled(final ObserverContext ctx, final boolean rpcThrottleEnabled) throws IOException { } + + /** + * Called before granting user permissions. + * @param ctx the coprocessor instance's environment + * @param userPermission the user and permissions + * @param mergeExistingPermissions True if merge with previous granted permissions + */ + default void preGrant(ObserverContext ctx, + UserPermission userPermission, boolean mergeExistingPermissions) throws IOException { + } + + /** + * Called after granting user permissions. + * @param ctx the coprocessor instance's environment + * @param userPermission the user and permissions + * @param mergeExistingPermissions True if merge with previous granted permissions + */ + default void postGrant(ObserverContext ctx, + UserPermission userPermission, boolean mergeExistingPermissions) throws IOException { + } + + /** + * Called before revoking user permissions. + * @param ctx the coprocessor instance's environment + * @param userPermission the user and permissions + */ + default void preRevoke(ObserverContext ctx, + UserPermission userPermission) throws IOException { + } + + /** + * Called after revoking user permissions. + * @param ctx the coprocessor instance's environment + * @param userPermission the user and permissions + */ + default void postRevoke(ObserverContext ctx, + UserPermission userPermission) throws IOException { + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java index b4a4421dc60..d999dae14c1 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java @@ -58,6 +58,7 @@ import org.apache.hadoop.hbase.quotas.GlobalQuotaSettings; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.SyncReplicationState; import org.apache.hadoop.hbase.security.User; +import org.apache.hadoop.hbase.security.access.UserPermission; import org.apache.yetus.audience.InterfaceAudience; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -1834,4 +1835,42 @@ public class MasterCoprocessorHost } }); } + + public void preGrant(UserPermission userPermission, boolean mergeExistingPermissions) + throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + observer.preGrant(this, userPermission, mergeExistingPermissions); + } + }); + } + + public void postGrant(UserPermission userPermission, boolean mergeExistingPermissions) + throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + observer.postGrant(this, userPermission, mergeExistingPermissions); + } + }); + } + + public void preRevoke(UserPermission userPermission) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + observer.preRevoke(this, userPermission); + } + }); + } + + public void postRevoke(UserPermission userPermission) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + observer.postRevoke(this, userPermission); + } + }); + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java index 89fcff95cbc..1ff3f0eaa77 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java @@ -49,6 +49,7 @@ import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; import org.apache.hadoop.hbase.client.MasterSwitchType; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionInfoBuilder; +import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.client.TableDescriptor; import org.apache.hadoop.hbase.client.TableState; import org.apache.hadoop.hbase.client.VersionInfoUtil; @@ -92,8 +93,11 @@ import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.security.access.AccessChecker; +import org.apache.hadoop.hbase.security.access.AccessControlLists; import org.apache.hadoop.hbase.security.access.AccessController; import org.apache.hadoop.hbase.security.access.Permission; +import org.apache.hadoop.hbase.security.access.ShadedAccessControlUtil; +import org.apache.hadoop.hbase.security.access.UserPermission; import org.apache.hadoop.hbase.security.visibility.VisibilityController; import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils; import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils; @@ -114,6 +118,10 @@ import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.shaded.protobuf.ResponseConverter; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CompactRegionRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CompactRegionResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoRequest; @@ -2502,6 +2510,50 @@ public class MasterRpcServices extends RSRpcServices } } + @Override + public GrantResponse grant(RpcController controller, GrantRequest request) + throws ServiceException { + try { + final UserPermission perm = + ShadedAccessControlUtil.toUserPermission(request.getUserPermission()); + boolean mergeExistingPermissions = request.getMergeExistingPermissions(); + if (master.cpHost != null) { + master.cpHost.preGrant(perm, mergeExistingPermissions); + } + try (Table table = master.getConnection().getTable(AccessControlLists.ACL_TABLE_NAME)) { + AccessControlLists.addUserPermission(getConfiguration(), perm, table, + mergeExistingPermissions); + } + if (master.cpHost != null) { + master.cpHost.postGrant(perm, mergeExistingPermissions); + } + return GrantResponse.getDefaultInstance(); + } catch (IOException ioe) { + throw new ServiceException(ioe); + } + } + + @Override + public RevokeResponse revoke(RpcController controller, RevokeRequest request) + throws ServiceException { + try { + final UserPermission userPermission = + ShadedAccessControlUtil.toUserPermission(request.getUserPermission()); + if (master.cpHost != null) { + master.cpHost.preRevoke(userPermission); + } + try (Table table = master.getConnection().getTable(AccessControlLists.ACL_TABLE_NAME)) { + AccessControlLists.removeUserPermission(master.getConfiguration(), userPermission, table); + } + if (master.cpHost != null) { + master.cpHost.postRevoke(userPermission); + } + return RevokeResponse.getDefaultInstance(); + } catch (IOException ioe) { + throw new ServiceException(ioe); + } + } + private boolean containMetaWals(ServerName serverName) throws IOException { Path logDir = new Path(master.getWALRootDir(), AbstractFSWALProvider.getWALDirectoryName(serverName.toString())); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlLists.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlLists.java index 34480d3b980..7560a936a78 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlLists.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlLists.java @@ -130,7 +130,7 @@ public class AccessControlLists { * @param t acl table instance. It is closed upon method return. * @throws IOException in the case of an error accessing the metadata table */ - static void addUserPermission(Configuration conf, UserPermission userPerm, Table t, + public static void addUserPermission(Configuration conf, UserPermission userPerm, Table t, boolean mergeExistingPermissions) throws IOException { Permission permission = userPerm.getPermission(); Permission.Action[] actions = permission.getActions(); @@ -222,7 +222,7 @@ public class AccessControlLists { * @param t acl table * @throws IOException if there is an error accessing the metadata table */ - static void removeUserPermission(Configuration conf, UserPermission userPerm, Table t) + public static void removeUserPermission(Configuration conf, UserPermission userPerm, Table t) throws IOException { if (null == userPerm.getPermission().getActions() || userPerm.getPermission().getActions().length == 0) { 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 f99531c463c..d6a2463dc56 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 @@ -2052,6 +2052,10 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor, /* ---- Protobuf AccessControlService implementation ---- */ + /** + * @deprecated Use {@link Admin#grant(UserPermission, boolean)} instead. + */ + @Deprecated @Override public void grant(RpcController controller, AccessControlProtos.GrantRequest request, @@ -2069,36 +2073,10 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor, LOG.debug("Received request from {} to grant access permission {}", caller.getName(), perm.toString()); } + preGrantOrRevoke(caller, "grant", perm); - switch(request.getUserPermission().getPermission().getType()) { - case Global : - accessChecker.requireGlobalPermission(caller, "grant", Action.ADMIN, ""); - break; - case Table : - TablePermission tablePerm = (TablePermission) perm.getPermission(); - accessChecker.requirePermission(caller, "grant", tablePerm.getTableName(), - tablePerm.getFamily(), tablePerm.getQualifier(), null, Action.ADMIN); - break; - case Namespace : - NamespacePermission namespacePer = (NamespacePermission) perm.getPermission(); - accessChecker.requireNamespacePermission(caller, "grant", namespacePer.getNamespace(), - null, Action.ADMIN); - break; - } - - User.runAsLoginUser(new PrivilegedExceptionAction() { - @Override - public Void run() throws Exception { - // regionEnv is set at #start. Hopefully not null at this point. - try (Table table = regionEnv.getConnection(). - getTable(AccessControlLists.ACL_TABLE_NAME)) { - AccessControlLists.addUserPermission(regionEnv.getConfiguration(), perm, table, - request.getMergeExistingPermissions()); - } - return null; - } - }); - + // regionEnv is set at #start. Hopefully not null at this point. + regionEnv.getConnection().getAdmin().grant(perm, request.getMergeExistingPermissions()); if (AUDITLOG.isTraceEnabled()) { // audit log should store permission changes in addition to auth results AUDITLOG.trace("Granted permission " + perm.toString()); @@ -2115,9 +2093,12 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor, done.run(response); } + /** + * @deprecated Use {@link Admin#revoke(UserPermission)} instead. + */ + @Deprecated @Override - public void revoke(RpcController controller, - AccessControlProtos.RevokeRequest request, + public void revoke(RpcController controller, AccessControlProtos.RevokeRequest request, RpcCallback done) { final UserPermission perm = AccessControlUtil.toUserPermission(request.getUserPermission()); AccessControlProtos.RevokeResponse response = null; @@ -2132,35 +2113,9 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor, LOG.debug("Received request from {} to revoke access permission {}", caller.getShortName(), perm.toString()); } - - switch(request.getUserPermission().getPermission().getType()) { - case Global : - accessChecker.requireGlobalPermission(caller, "revoke", Action.ADMIN, ""); - break; - case Table : - TablePermission tablePerm = (TablePermission) perm.getPermission(); - accessChecker.requirePermission(caller, "revoke", tablePerm.getTableName(), - tablePerm.getFamily(), tablePerm.getQualifier(), null, Action.ADMIN); - break; - case Namespace : - NamespacePermission namespacePer = (NamespacePermission) perm.getPermission(); - accessChecker.requireNamespacePermission(caller, "revoke", - namespacePer.getNamespace(), null, Action.ADMIN); - break; - } - - User.runAsLoginUser(new PrivilegedExceptionAction() { - @Override - public Void run() throws Exception { - // regionEnv is set at #start. Hopefully not null here. - try (Table table = regionEnv.getConnection(). - getTable(AccessControlLists.ACL_TABLE_NAME)) { - AccessControlLists.removeUserPermission(regionEnv.getConfiguration(), perm, table); - } - return null; - } - }); - + preGrantOrRevoke(caller, "revoke", perm); + // regionEnv is set at #start. Hopefully not null here. + regionEnv.getConnection().getAdmin().revoke(perm); if (AUDITLOG.isTraceEnabled()) { // audit log should record all permission changes AUDITLOG.trace("Revoked permission " + perm.toString()); @@ -2680,4 +2635,36 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor, } done.run(response); } + + @Override + public void preGrant(ObserverContext ctx, + UserPermission userPermission, boolean mergeExistingPermissions) throws IOException { + preGrantOrRevoke(getActiveUser(ctx), "grant", userPermission); + } + + @Override + public void preRevoke(ObserverContext ctx, + UserPermission userPermission) throws IOException { + preGrantOrRevoke(getActiveUser(ctx), "revoke", userPermission); + } + + private void preGrantOrRevoke(User caller, String request, UserPermission userPermission) + throws IOException { + switch (userPermission.getPermission().scope) { + case GLOBAL: + accessChecker.requireGlobalPermission(caller, request, Action.ADMIN, ""); + break; + case NAMESPACE: + NamespacePermission namespacePerm = (NamespacePermission) userPermission.getPermission(); + accessChecker.requireNamespacePermission(caller, request, namespacePerm.getNamespace(), + null, Action.ADMIN); + break; + case TABLE: + TablePermission tablePerm = (TablePermission) userPermission.getPermission(); + accessChecker.requirePermission(caller, request, tablePerm.getTableName(), + tablePerm.getFamily(), tablePerm.getQualifier(), null, Action.ADMIN); + break; + default: + } + } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java index 3655352bf5c..e392b3b7e9a 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/SecureTestUtil.java @@ -34,7 +34,6 @@ import com.google.protobuf.ServiceException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.Coprocessor; import org.apache.hadoop.hbase.HBaseTestingUtility; -import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.MiniHBaseCluster; import org.apache.hadoop.hbase.NamespaceDescriptor; import org.apache.hadoop.hbase.TableName; @@ -375,12 +374,8 @@ public class SecureTestUtil { @Override public Void call() throws Exception { try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) { - try (Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) { - BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.grant(null, protocol, user, false, actions); - } + connection.getAdmin().grant(new UserPermission(user, new GlobalPermission(actions)), + false); } return null; } @@ -398,12 +393,7 @@ public class SecureTestUtil { @Override public Void call() throws Exception { try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) { - try (Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) { - BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.revoke(null, protocol, user, actions); - } + connection.getAdmin().revoke(new UserPermission(user, new GlobalPermission(actions))); } return null; } @@ -421,12 +411,8 @@ public class SecureTestUtil { @Override public Void call() throws Exception { try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) { - try (Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) { - BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.grant(null, protocol, user, namespace, false, actions); - } + connection.getAdmin() + .grant(new UserPermission(user, new NamespacePermission(namespace, actions)), false); } return null; } @@ -486,12 +472,8 @@ public class SecureTestUtil { @Override public Void call() throws Exception { try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) { - try (Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) { - BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.revoke(null, protocol, user, namespace, actions); - } + connection.getAdmin() + .revoke(new UserPermission(user, new NamespacePermission(namespace, actions))); } return null; } @@ -510,12 +492,9 @@ public class SecureTestUtil { @Override public Void call() throws Exception { try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) { - try (Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) { - BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.grant(null, protocol, user, table, family, qualifier, false, actions); - } + connection.getAdmin().grant( + new UserPermission(user, new TablePermission(table, family, qualifier, actions)), + false); } return null; } @@ -576,12 +555,8 @@ public class SecureTestUtil { @Override public Void call() throws Exception { try (Connection connection = ConnectionFactory.createConnection(util.getConfiguration())) { - try (Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) { - BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.revoke(null, protocol, user, table, family, qualifier, actions); - } + connection.getAdmin().revoke( + new UserPermission(user, new TablePermission(table, family, qualifier, actions))); } return null; } 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 9b8c8a6fad7..5199550dee8 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 @@ -1170,13 +1170,10 @@ public class TestAccessController extends SecureTestUtil { AccessTestAction grantAction = new AccessTestAction() { @Override public Object run() throws Exception { - try(Connection conn = ConnectionFactory.createConnection(conf); - Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) { - BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName()); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.grant(null, protocol, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, - null, false, Action.READ); + try (Connection conn = ConnectionFactory.createConnection(conf)) { + conn.getAdmin().grant(new UserPermission(USER_RO.getShortName(), + new TablePermission(TEST_TABLE, TEST_FAMILY, Action.READ)), + false); } return null; } @@ -1185,13 +1182,9 @@ public class TestAccessController extends SecureTestUtil { AccessTestAction revokeAction = new AccessTestAction() { @Override public Object run() throws Exception { - try(Connection conn = ConnectionFactory.createConnection(conf); - Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) { - BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName()); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.revoke(null, protocol, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, null, - Action.READ); + try(Connection conn = ConnectionFactory.createConnection(conf)) { + conn.getAdmin().revoke(new UserPermission(USER_RO.getShortName(), + new TablePermission(TEST_TABLE, TEST_FAMILY, Action.READ))); } return null; } @@ -1225,6 +1218,57 @@ public class TestAccessController extends SecureTestUtil { } }; + AccessTestAction preGrantAction = new AccessTestAction() { + @Override + public Object run() throws Exception { + ACCESS_CONTROLLER.preGrant(ObserverContextImpl.createAndPrepare(CP_ENV), + new UserPermission(USER_RO.getShortName(), + new TablePermission(TEST_TABLE, TEST_FAMILY, Action.READ)), + false); + return null; + } + }; + + AccessTestAction preRevokeAction = new AccessTestAction() { + @Override + public Object run() throws Exception { + ACCESS_CONTROLLER.preRevoke(ObserverContextImpl.createAndPrepare(CP_ENV), + new UserPermission(USER_RO.getShortName(), + new TablePermission(TEST_TABLE, TEST_FAMILY, Action.READ))); + return null; + } + }; + + AccessTestAction grantCPAction = new AccessTestAction() { + @Override + public Object run() throws Exception { + try (Connection conn = ConnectionFactory.createConnection(conf); + Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) { + BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName()); + AccessControlService.BlockingInterface protocol = + AccessControlService.newBlockingStub(service); + AccessControlUtil.grant(null, protocol, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, + null, false, Action.READ); + } + return null; + } + }; + + AccessTestAction revokeCPAction = new AccessTestAction() { + @Override + public Object run() throws Exception { + try (Connection conn = ConnectionFactory.createConnection(conf); + Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) { + BlockingRpcChannel service = acl.coprocessorService(TEST_TABLE.getName()); + AccessControlService.BlockingInterface protocol = + AccessControlService.newBlockingStub(service); + AccessControlUtil.revoke(null, protocol, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, + null, Action.READ); + } + return null; + } + }; + 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); @@ -1240,6 +1284,22 @@ public class TestAccessController extends SecureTestUtil { verifyAllowed(getGlobalPermissionsAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); verifyDenied(getGlobalPermissionsAction, USER_CREATE, USER_OWNER, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); + + verifyAllowed(preGrantAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); + verifyDenied(preGrantAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, + USER_GROUP_WRITE, USER_GROUP_CREATE); + + verifyAllowed(preRevokeAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); + verifyDenied(preRevokeAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, + USER_GROUP_WRITE, USER_GROUP_CREATE); + + verifyAllowed(grantCPAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); + verifyDenied(grantCPAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, + USER_GROUP_WRITE, USER_GROUP_CREATE); + + verifyAllowed(revokeCPAction, SUPERUSER, USER_ADMIN, USER_OWNER, USER_GROUP_ADMIN); + verifyDenied(revokeCPAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_GROUP_READ, + USER_GROUP_WRITE, USER_GROUP_CREATE); } finally { // Cleanup, Grant the revoked permission back to the user grantOnTable(TEST_UTIL, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, null, diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java index d37794dd3ec..fa8543e9170 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestNamespaceCommands.java @@ -356,40 +356,27 @@ public class TestNamespaceCommands extends SecureTestUtil { } @Test - public void testGrantRevoke() throws Exception{ + public void testGrantRevoke() throws Exception { final String testUser = "testUser"; - // Test if client API actions are authorized - AccessTestAction grantAction = new AccessTestAction() { @Override public Object run() throws Exception { - Connection connection = ConnectionFactory.createConnection(conf); - Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME); - try { - BlockingRpcChannel service = - acl.coprocessorService(HConstants.EMPTY_START_ROW); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.grant(null, protocol, testUser, TEST_NAMESPACE, false, Action.WRITE); - } finally { - acl.close(); - connection.close(); + try (Connection connection = ConnectionFactory.createConnection(conf)) { + connection.getAdmin().grant( + new UserPermission(testUser, new NamespacePermission(TEST_NAMESPACE, Action.WRITE)), + false); } return null; } }; - AccessTestAction grantNamespaceAction = new AccessTestAction() { @Override public Object run() throws Exception { - try(Connection conn = ConnectionFactory.createConnection(conf); - Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) { - BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.grant(null, protocol, USER_GROUP_NS_ADMIN.getShortName(), - TEST_NAMESPACE, false, Action.READ); + try (Connection conn = ConnectionFactory.createConnection(conf)) { + conn.getAdmin().grant( + new UserPermission(USER_GROUP_NS_ADMIN.getShortName(), TEST_NAMESPACE, Action.READ), + false); } return null; } @@ -398,37 +385,19 @@ public class TestNamespaceCommands extends SecureTestUtil { AccessTestAction revokeAction = new AccessTestAction() { @Override public Object run() throws Exception { - Connection connection = ConnectionFactory.createConnection(conf); - Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME); - try { - BlockingRpcChannel service = - acl.coprocessorService(HConstants.EMPTY_START_ROW); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.revoke(null, protocol, testUser, TEST_NAMESPACE, Action.WRITE); - } finally { - acl.close(); - connection.close(); + try (Connection connection = ConnectionFactory.createConnection(conf)) { + connection.getAdmin().revoke( + new UserPermission(testUser, new NamespacePermission(TEST_NAMESPACE, Action.WRITE))); } return null; } }; - AccessTestAction revokeNamespaceAction = new AccessTestAction() { @Override public Object run() throws Exception { - Connection connection = ConnectionFactory.createConnection(conf); - Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME); - try { - BlockingRpcChannel service = - acl.coprocessorService(HConstants.EMPTY_START_ROW); - AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); - AccessControlUtil.revoke(null, protocol, USER_GROUP_NS_ADMIN.getShortName(), - TEST_NAMESPACE, Action.READ); - } finally { - acl.close(); - connection.close(); + try (Connection connection = ConnectionFactory.createConnection(conf)) { + connection.getAdmin().revoke(new UserPermission(USER_GROUP_NS_ADMIN.getShortName(), + new NamespacePermission(TEST_NAMESPACE, Action.READ))); } return null; } @@ -437,16 +406,57 @@ public class TestNamespaceCommands extends SecureTestUtil { AccessTestAction getPermissionsAction = new AccessTestAction() { @Override public Object run() throws Exception { - Connection connection = ConnectionFactory.createConnection(conf); - Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME); - try { + try (Connection connection = ConnectionFactory.createConnection(conf); + Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) { BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); AccessControlService.BlockingInterface protocol = - AccessControlService.newBlockingStub(service); + AccessControlService.newBlockingStub(service); AccessControlUtil.getUserPermissions(null, protocol, Bytes.toBytes(TEST_NAMESPACE)); - } finally { - acl.close(); - connection.close(); + } + return null; + } + }; + + AccessTestAction preGrantAction = new AccessTestAction() { + @Override + public Object run() throws Exception { + ACCESS_CONTROLLER.preGrant(ObserverContextImpl.createAndPrepare(CP_ENV), + new UserPermission(testUser, new NamespacePermission(TEST_NAMESPACE, Action.WRITE)), + false); + return null; + } + }; + AccessTestAction preRevokeAction = new AccessTestAction() { + @Override + public Object run() throws Exception { + ACCESS_CONTROLLER.preRevoke(ObserverContextImpl.createAndPrepare(CP_ENV), + new UserPermission(testUser, new NamespacePermission(TEST_NAMESPACE, Action.WRITE))); + return null; + } + }; + + AccessTestAction grantCPAction = new AccessTestAction() { + @Override + public Object run() throws Exception { + try (Connection connection = ConnectionFactory.createConnection(conf); + Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) { + BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); + AccessControlService.BlockingInterface protocol = + AccessControlService.newBlockingStub(service); + AccessControlUtil.grant(null, protocol, testUser, TEST_NAMESPACE, false, Action.WRITE); + } + return null; + } + }; + AccessTestAction revokeCPAction = new AccessTestAction() { + @Override + public Object run() throws Exception { + try (Connection connection = ConnectionFactory.createConnection(conf); + Table acl = connection.getTable(AccessControlLists.ACL_TABLE_NAME)) { + BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); + AccessControlService.BlockingInterface protocol = + AccessControlService.newBlockingStub(service); + AccessControlUtil.revoke(null, protocol, testUser, TEST_NAMESPACE, Action.WRITE); } return null; } @@ -456,7 +466,6 @@ public class TestNamespaceCommands extends SecureTestUtil { verifyDenied(grantAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ, USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC, USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); - verifyAllowed(grantNamespaceAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN, USER_GROUP_NS_ADMIN); verifyDenied(grantNamespaceAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ, @@ -467,7 +476,6 @@ public class TestNamespaceCommands extends SecureTestUtil { verifyDenied(revokeAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ, USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC, USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); - verifyAllowed(revokeNamespaceAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN, USER_GROUP_NS_ADMIN); verifyDenied(revokeNamespaceAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ, @@ -479,6 +487,24 @@ public class TestNamespaceCommands extends SecureTestUtil { verifyDenied(getPermissionsAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ, USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC, USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); + + verifyAllowed(preGrantAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN); + verifyDenied(preGrantAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ, + USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC, + USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); + verifyAllowed(preRevokeAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN); + verifyDenied(preRevokeAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ, + USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC, + USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); + + verifyAllowed(grantCPAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN); + verifyDenied(grantCPAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ, + USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC, + USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); + verifyAllowed(revokeCPAction, SUPERUSER, USER_GLOBAL_ADMIN, USER_GROUP_ADMIN, USER_NS_ADMIN); + verifyDenied(revokeCPAction, USER_GLOBAL_CREATE, USER_GLOBAL_WRITE, USER_GLOBAL_READ, + USER_GLOBAL_EXEC, USER_NS_CREATE, USER_NS_WRITE, USER_NS_READ, USER_NS_EXEC, + USER_TABLE_CREATE, USER_TABLE_WRITE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); } @Test diff --git a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java index 56626b64e5f..5d550c6888a 100644 --- a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java +++ b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java @@ -60,6 +60,7 @@ import org.apache.hadoop.hbase.replication.ReplicationException; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.replication.SyncReplicationState; +import org.apache.hadoop.hbase.security.access.UserPermission; import org.apache.hadoop.hbase.thrift2.ThriftUtilities; import org.apache.hadoop.hbase.thrift2.generated.TColumnFamilyDescriptor; import org.apache.hadoop.hbase.thrift2.generated.THBaseService; @@ -1425,4 +1426,14 @@ public class ThriftAdmin implements Admin { public SpaceQuotaSnapshot getCurrentSpaceQuotaSnapshot(TableName tableName) throws IOException { throw new NotImplementedException("getCurrentSpaceQuotaSnapshot not supported in ThriftAdmin"); } + + @Override + public void grant(UserPermission userPermission, boolean mergeExistingPermissions) { + throw new NotImplementedException("grant not supported in ThriftAdmin"); + } + + @Override + public void revoke(UserPermission userPermission) { + throw new NotImplementedException("revoke not supported in ThriftAdmin"); + } }