HBASE-21739 Move grant/revoke from regionserver to master

Signed-off-by: Guanghao Zhang <zghao@apache.org>
This commit is contained in:
meiyi 2019-01-29 19:52:50 +08:00 committed by Guanghao Zhang
parent d82c1a6c2b
commit f997252344
20 changed files with 600 additions and 266 deletions

View File

@ -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;
}

View File

@ -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<? extends SpaceQuotaSnapshotView> 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<Void> grant(UserPermission userPermission, boolean mergeExistingPermissions);
/**
* Revokes user specific permissions
* @param userPermission user and permissions
*/
CompletableFuture<Void> revoke(UserPermission userPermission);
}

View File

@ -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<SpaceQuotaSnapshot> getCurrentSpaceQuotaSnapshot(TableName tableName) {
return wrap(rawAdmin.getCurrentSpaceQuotaSnapshot(tableName));
}
@Override
public CompletableFuture<Void> grant(UserPermission userPermission,
boolean mergeExistingPermissions) {
return wrap(rawAdmin.grant(userPermission, mergeExistingPermissions));
}
@Override
public CompletableFuture<Void> revoke(UserPermission userPermission) {
return wrap(rawAdmin.revoke(userPermission));
}
}

View File

@ -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);
}
};
}

View File

@ -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<Void>(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<Void>(getConnection(), getRpcControllerFactory()) {
@Override
protected Void rpcCall() throws Exception {
RevokeRequest req = ShadedAccessControlUtil.buildRevokeRequest(userPermission);
this.master.revoke(getRpcController(), req);
return null;
}
});
}
}

View File

@ -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<Void> grant(UserPermission userPermission,
boolean mergeExistingPermissions) {
return this.<Void> newMasterCaller()
.action((controller, stub) -> this.<GrantRequest, GrantResponse, Void> call(controller,
stub, ShadedAccessControlUtil.buildGrantRequest(userPermission, mergeExistingPermissions),
(s, c, req, done) -> s.grant(c, req, done), resp -> null))
.call();
}
@Override
public CompletableFuture<Void> revoke(UserPermission userPermission) {
return this.<Void> newMasterCaller()
.action((controller, stub) -> this.<RevokeRequest, RevokeResponse, Void> call(controller,
stub, ShadedAccessControlUtil.buildRevokeRequest(userPermission),
(s, c, req, done) -> s.revoke(c, req, done), resp -> null))
.call();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
/**

View File

@ -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 {

View File

@ -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<Permission.Action> toPermissionActions(
List<org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Action> protoActions) {
List<AccessControlProtos.Permission.Action> protoActions) {
List<Permission.Action> 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<String, Permission> toUserTablePermissions(
org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.UsersAndPermissions proto) {
AccessControlProtos.UsersAndPermissions proto) {
ListMultimap<String, Permission> 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<String, UserPermission> 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<String, Collection<UserPermission>> 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();
}
}

View File

@ -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.

View File

@ -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<MasterCoprocessorEnvironment> 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<MasterCoprocessorEnvironment> 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<MasterCoprocessorEnvironment> 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<MasterCoprocessorEnvironment> 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<MasterCoprocessorEnvironment> ctx,
UserPermission userPermission) throws IOException {
}
}

View File

@ -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);
}
});
}
}

View File

@ -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()));

View File

@ -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) {

View File

@ -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<Void>() {
@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<AccessControlProtos.RevokeResponse> 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<Void>() {
@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<MasterCoprocessorEnvironment> ctx,
UserPermission userPermission, boolean mergeExistingPermissions) throws IOException {
preGrantOrRevoke(getActiveUser(ctx), "grant", userPermission);
}
@Override
public void preRevoke(ObserverContext<MasterCoprocessorEnvironment> 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:
}
}
}

View File

@ -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;
}

View File

@ -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,

View File

@ -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

View File

@ -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");
}
}