You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zg...@apache.org on 2019/04/09 09:05:21 UTC
[hbase] branch master updated: HBASE-22117 Move
hasPermission/checkPermissions from region server to master
This is an automated email from the ASF dual-hosted git repository.
zghao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/master by this push:
new d32f924 HBASE-22117 Move hasPermission/checkPermissions from region server to master
d32f924 is described below
commit d32f924ef4a6ffe10bddef5b3daf69bc0f85405c
Author: meiyi <my...@gamil.com>
AuthorDate: Thu Mar 28 18:50:08 2019 +0800
HBASE-22117 Move hasPermission/checkPermissions from region server to master
Signed-off-by: Guanghao Zhang <zg...@apache.org>
---
.../java/org/apache/hadoop/hbase/client/Admin.java | 21 ++
.../org/apache/hadoop/hbase/client/AsyncAdmin.java | 19 ++
.../hadoop/hbase/client/AsyncHBaseAdmin.java | 7 +
.../hbase/client/ConnectionImplementation.java | 8 +
.../org/apache/hadoop/hbase/client/HBaseAdmin.java | 17 ++
.../hadoop/hbase/client/RawAsyncHBaseAdmin.java | 15 ++
.../hbase/client/ShortCircuitMasterConnection.java | 8 +
.../hbase/security/access/AccessControlClient.java | 18 +-
.../hbase/security/access/AccessControlUtil.java | 2 +
.../security/access/ShadedAccessControlUtil.java | 13 ++
.../src/main/protobuf/AccessControl.proto | 9 +
.../src/main/protobuf/Master.proto | 2 +
.../hadoop/hbase/coprocessor/MasterObserver.java | 21 ++
.../hadoop/hbase/master/MasterCoprocessorHost.java | 21 ++
.../hadoop/hbase/master/MasterRpcServices.java | 44 ++++
.../hbase/security/access/AccessChecker.java | 164 ++++++++++++++
.../hbase/security/access/AccessController.java | 251 +++++++--------------
.../client/TestAsyncAccessControlAdminApi.java | 73 +++++-
.../hbase/security/access/SecureTestUtil.java | 88 ++------
.../security/access/TestAccessController.java | 24 +-
.../access/TestWithDisabledAuthorization.java | 67 +++---
.../hadoop/hbase/thrift2/client/ThriftAdmin.java | 6 +
22 files changed, 583 insertions(+), 315 deletions(-)
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 bf52af9..675942a 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
@@ -54,6 +54,7 @@ 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.GetUserPermissionsRequest;
+import org.apache.hadoop.hbase.security.access.Permission;
import org.apache.hadoop.hbase.security.access.UserPermission;
import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
@@ -2107,4 +2108,24 @@ public interface Admin extends Abortable, Closeable {
*/
List<UserPermission> getUserPermissions(GetUserPermissionsRequest getUserPermissionsRequest)
throws IOException;
+
+ /**
+ * Check if the user has specific permissions
+ * @param userName the user name
+ * @param permissions the specific permission list
+ * @return True if user has the specific permissions
+ * @throws IOException if a remote or network exception occurs
+ */
+ List<Boolean> hasUserPermissions(String userName, List<Permission> permissions)
+ throws IOException;
+
+ /**
+ * Check if call user has specific permissions
+ * @param permissions the specific permission list
+ * @return True if user has the specific permissions
+ * @throws IOException if a remote or network exception occurs
+ */
+ default List<Boolean> hasUserPermissions(List<Permission> permissions) throws IOException {
+ return hasUserPermissions(null, permissions);
+ }
}
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 2f1f494..96ea677 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
@@ -47,6 +47,7 @@ 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.GetUserPermissionsRequest;
+import org.apache.hadoop.hbase.security.access.Permission;
import org.apache.hadoop.hbase.security.access.UserPermission;
import org.apache.yetus.audience.InterfaceAudience;
@@ -1457,4 +1458,22 @@ public interface AsyncAdmin {
*/
CompletableFuture<List<UserPermission>>
getUserPermissions(GetUserPermissionsRequest getUserPermissionsRequest);
+
+ /**
+ * Check if the user has specific permissions
+ * @param userName the user name
+ * @param permissions the specific permission list
+ * @return True if user has the specific permissions
+ */
+ CompletableFuture<List<Boolean>> hasUserPermissions(String userName,
+ List<Permission> permissions);
+
+ /**
+ * Check if call user has specific permissions
+ * @param permissions the specific permission list
+ * @return True if user has the specific permissions
+ */
+ default CompletableFuture<List<Boolean>> hasUserPermissions(List<Permission> permissions) {
+ return hasUserPermissions(null, permissions);
+ }
}
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 668e729..1566110 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
@@ -43,6 +43,7 @@ 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.GetUserPermissionsRequest;
+import org.apache.hadoop.hbase.security.access.Permission;
import org.apache.hadoop.hbase.security.access.UserPermission;
import org.apache.hadoop.hbase.util.FutureUtils;
import org.apache.yetus.audience.InterfaceAudience;
@@ -814,4 +815,10 @@ class AsyncHBaseAdmin implements AsyncAdmin {
getUserPermissions(GetUserPermissionsRequest getUserPermissionsRequest) {
return wrap(rawAdmin.getUserPermissions(getUserPermissionsRequest));
}
+
+ @Override
+ public CompletableFuture<List<Boolean>> hasUserPermissions(String userName,
+ List<Permission> permissions) {
+ return wrap(rawAdmin.hasUserPermissions(userName, permissions));
+ }
}
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 6bcb499..f5b0b03 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
@@ -95,6 +95,8 @@ 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.AccessControlProtos.GetUserPermissionsRequest;
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GetUserPermissionsResponse;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.HasUserPermissionsRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.HasUserPermissionsResponse;
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;
@@ -1803,6 +1805,12 @@ class ConnectionImplementation implements ClusterConnection, Closeable {
GetUserPermissionsRequest request) throws ServiceException {
return stub.getUserPermissions(controller, request);
}
+
+ @Override
+ public HasUserPermissionsResponse hasUserPermissions(RpcController controller,
+ HasUserPermissionsRequest request) throws ServiceException {
+ return stub.hasUserPermissions(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 fd1cbc7..23237af 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
@@ -86,6 +86,7 @@ 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.GetUserPermissionsRequest;
+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.snapshot.ClientSnapshotDescriptionUtils;
@@ -113,6 +114,7 @@ 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.AccessControlProtos.GrantRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.HasUserPermissionsRequest;
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;
@@ -3854,6 +3856,21 @@ public class HBaseAdmin implements Admin {
}
@Override
+ public List<Boolean> hasUserPermissions(String userName, List<Permission> permissions)
+ throws IOException {
+ return executeCallable(
+ new MasterCallable<List<Boolean>>(getConnection(), getRpcControllerFactory()) {
+ @Override
+ protected List<Boolean> rpcCall() throws Exception {
+ HasUserPermissionsRequest request =
+ ShadedAccessControlUtil.buildHasUserPermissionsRequest(userName, permissions);
+ return this.master.hasUserPermissions(getRpcController(), request)
+ .getHasUserPermissionList();
+ }
+ });
+ }
+
+ @Override
public void close() {
}
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 8537ffe..c6637b0 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
@@ -87,6 +87,7 @@ 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.GetUserPermissionsRequest;
+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.snapshot.ClientSnapshotDescriptionUtils;
@@ -112,6 +113,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos;
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GetUserPermissionsResponse;
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.HasUserPermissionsRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.HasUserPermissionsResponse;
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;
@@ -3824,4 +3827,16 @@ class RawAsyncHBaseAdmin implements AsyncAdmin {
.collect(Collectors.toList())))
.call();
}
+
+ @Override
+ public CompletableFuture<List<Boolean>> hasUserPermissions(String userName,
+ List<Permission> permissions) {
+ return this.<List<Boolean>> newMasterCaller()
+ .action((controller, stub) -> this
+ .<HasUserPermissionsRequest, HasUserPermissionsResponse, List<Boolean>> call(controller,
+ stub, ShadedAccessControlUtil.buildHasUserPermissionsRequest(userName, permissions),
+ (s, c, req, done) -> s.hasUserPermissions(c, req, done),
+ resp -> resp.getHasUserPermissionList()))
+ .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 6e80a54..8927615 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
@@ -25,6 +25,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Get
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GetUserPermissionsResponse;
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.HasUserPermissionsRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.HasUserPermissionsResponse;
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;
@@ -696,4 +698,10 @@ public class ShortCircuitMasterConnection implements MasterKeepAliveConnection {
GetUserPermissionsRequest request) throws ServiceException {
return stub.getUserPermissions(controller, request);
}
+
+ @Override
+ public HasUserPermissionsResponse hasUserPermissions(RpcController controller,
+ HasUserPermissionsRequest request) throws ServiceException {
+ return stub.hasUserPermissions(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 046761e..01f3e49 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
@@ -392,19 +392,9 @@ public class AccessControlClient {
if (StringUtils.isEmpty(tableName) || StringUtils.isEmpty(userName)) {
throw new IllegalArgumentException("Table and user name can't be null or empty.");
}
- boolean hasPermission = false;
- /**
- * todo: pass an rpccontroller hbaserpccontroller controller = ((clusterconnection)
- * connection).getrpccontrollerfactory().newcontroller();
- */
- try (Table table = connection.getTable(ACL_TABLE_NAME)) {
- CoprocessorRpcChannel service = table.coprocessorService(HConstants.EMPTY_START_ROW);
- BlockingInterface protocol =
- AccessControlProtos.AccessControlService.newBlockingStub(service);
- // Check whether user has permission
- hasPermission = AccessControlUtil.hasPermission(null, protocol, TableName.valueOf(tableName),
- columnFamily, columnQualifier, userName, actions);
- }
- return hasPermission;
+ List<Permission> permissions = new ArrayList<>(1);
+ permissions.add(Permission.newBuilder(TableName.valueOf(tableName)).withFamily(columnFamily)
+ .withQualifier(columnQualifier).withActions(actions).build());
+ return connection.getAdmin().hasUserPermissions(userName, permissions).get(0);
}
}
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 0220d89..484cee3 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
@@ -815,7 +815,9 @@ public class AccessControlUtil {
* @param actions Actions
* @return true if access allowed, otherwise false
* @throws ServiceException
+ * @deprecated Use {@link Admin#hasUserPermissions(String, List)} instead.
*/
+ @Deprecated
public static boolean hasPermission(RpcController controller,
AccessControlService.BlockingInterface protocol, TableName tableName, byte[] columnFamily,
byte[] columnQualifier, String userName, Permission.Action[] actions)
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 be3b75e..661bcc8 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
@@ -31,6 +31,7 @@ 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.GetUserPermissionsResponse;
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.HasUserPermissionsRequest;
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Type;
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeRequest;
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
@@ -318,4 +319,16 @@ public class ShadedAccessControlUtil {
}
return builder.build();
}
+
+ public static HasUserPermissionsRequest buildHasUserPermissionsRequest(String userName,
+ List<Permission> permissions) {
+ HasUserPermissionsRequest.Builder builder = HasUserPermissionsRequest.newBuilder();
+ if (userName != null && !userName.isEmpty()) {
+ builder.setUserName(ByteString.copyFromUtf8(userName));
+ }
+ for (Permission permission : permissions) {
+ builder.addPermission(toPermission(permission));
+ }
+ return builder.build();
+ }
}
diff --git a/hbase-protocol-shaded/src/main/protobuf/AccessControl.proto b/hbase-protocol-shaded/src/main/protobuf/AccessControl.proto
index af60fe2..3142a12 100644
--- a/hbase-protocol-shaded/src/main/protobuf/AccessControl.proto
+++ b/hbase-protocol-shaded/src/main/protobuf/AccessControl.proto
@@ -119,6 +119,15 @@ message CheckPermissionsRequest {
message CheckPermissionsResponse {
}
+message HasUserPermissionsRequest {
+ optional bytes user_name = 1;
+ repeated Permission permission = 2;
+}
+
+message HasUserPermissionsResponse {
+ repeated bool has_user_permission = 1;
+}
+
service AccessControlService {
rpc Grant(GrantRequest)
returns (GrantResponse);
diff --git a/hbase-protocol-shaded/src/main/protobuf/Master.proto b/hbase-protocol-shaded/src/main/protobuf/Master.proto
index d883b4c..257defe 100644
--- a/hbase-protocol-shaded/src/main/protobuf/Master.proto
+++ b/hbase-protocol-shaded/src/main/protobuf/Master.proto
@@ -1033,6 +1033,8 @@ service MasterService {
rpc Revoke(RevokeRequest) returns (RevokeResponse);
rpc GetUserPermissions (GetUserPermissionsRequest) returns (GetUserPermissionsResponse);
+
+ rpc HasUserPermissions (HasUserPermissionsRequest) returns (HasUserPermissionsResponse);
}
// 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 bfb1ada..88b01a2 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.Permission;
import org.apache.hadoop.hbase.security.access.UserPermission;
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.yetus.audience.InterfaceStability;
@@ -1662,4 +1663,24 @@ public interface MasterObserver {
String userName, String namespace, TableName tableName, byte[] family, byte[] qualifier)
throws IOException {
}
+
+ /*
+ * Called before checking if user has permissions.
+ * @param ctx the coprocessor instance's environment
+ * @param userName the user name
+ * @param permissions the permission list
+ */
+ default void preHasUserPermissions(ObserverContext<MasterCoprocessorEnvironment> ctx,
+ String userName, List<Permission> permissions) throws IOException {
+ }
+
+ /**
+ * Called after checking if user has permissions.
+ * @param ctx the coprocessor instance's environment
+ * @param userName the user name
+ * @param permissions the permission list
+ */
+ default void postHasUserPermissions(ObserverContext<MasterCoprocessorEnvironment> ctx,
+ String userName, List<Permission> permissions) 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 bb9fc3f..720f496 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.Permission;
import org.apache.hadoop.hbase.security.access.UserPermission;
import org.apache.yetus.audience.InterfaceAudience;
import org.slf4j.Logger;
@@ -1912,4 +1913,24 @@ public class MasterCoprocessorHost
}
});
}
+
+ public void preHasUserPermissions(String userName, List<Permission> permissions)
+ throws IOException {
+ execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() {
+ @Override
+ public void call(MasterObserver observer) throws IOException {
+ observer.preHasUserPermissions(this, userName, permissions);
+ }
+ });
+ }
+
+ public void postHasUserPermissions(String userName, List<Permission> permissions)
+ throws IOException {
+ execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() {
+ @Override
+ public void call(MasterObserver observer) throws IOException {
+ observer.postHasUserPermissions(this, userName, permissions);
+ }
+ });
+ }
}
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 08f89db..221ba37 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
@@ -94,6 +94,7 @@ import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
import org.apache.hadoop.hbase.security.Superusers;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.security.access.AccessChecker;
+import org.apache.hadoop.hbase.security.access.AccessChecker.InputUser;
import org.apache.hadoop.hbase.security.access.AccessControlLists;
import org.apache.hadoop.hbase.security.access.AccessController;
import org.apache.hadoop.hbase.security.access.Permission;
@@ -125,6 +126,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Get
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GetUserPermissionsResponse;
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.HasUserPermissionsRequest;
+import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.HasUserPermissionsResponse;
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.Permission.Type;
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeRequest;
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeResponse;
@@ -2628,6 +2631,47 @@ public class MasterRpcServices extends RSRpcServices
}
}
+ @Override
+ public HasUserPermissionsResponse hasUserPermissions(RpcController controller,
+ HasUserPermissionsRequest request) throws ServiceException {
+ try {
+ User caller = RpcServer.getRequestUser().orElse(null);
+ String userName =
+ request.hasUserName() ? request.getUserName().toStringUtf8() : caller.getShortName();
+ List<Permission> permissions = new ArrayList<>();
+ for (int i = 0; i < request.getPermissionCount(); i++) {
+ permissions.add(ShadedAccessControlUtil.toPermission(request.getPermission(i)));
+ }
+ if (master.cpHost != null) {
+ master.getMasterCoprocessorHost().preHasUserPermissions(userName, permissions);
+ }
+ if (!caller.getShortName().equals(userName)) {
+ List<String> groups = AccessChecker.getUserGroups(userName);
+ caller = new InputUser(userName, groups.toArray(new String[groups.size()]));
+ }
+ List<Boolean> hasUserPermissions = new ArrayList<>();
+ if (accessChecker != null) {
+ for (Permission permission : permissions) {
+ boolean hasUserPermission =
+ accessChecker.hasUserPermission(caller, "hasUserPermissions", permission);
+ hasUserPermissions.add(hasUserPermission);
+ }
+ } else {
+ for (int i = 0; i < permissions.size(); i++) {
+ hasUserPermissions.add(true);
+ }
+ }
+ if (master.cpHost != null) {
+ master.getMasterCoprocessorHost().postHasUserPermissions(userName, permissions);
+ }
+ HasUserPermissionsResponse.Builder builder =
+ HasUserPermissionsResponse.newBuilder().addAllHasUserPermission(hasUserPermissions);
+ return builder.build();
+ } 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/AccessChecker.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessChecker.java
index c4957f9..a035eb2 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessChecker.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessChecker.java
@@ -26,9 +26,13 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.AuthUtil;
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.DoNotRetryIOException;
import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.TableName;
@@ -39,12 +43,14 @@ import org.apache.hadoop.hbase.security.Superusers;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.security.UserProvider;
import org.apache.hadoop.hbase.security.access.Permission.Action;
+import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
import org.apache.hadoop.security.Groups;
import org.apache.hadoop.security.HadoopKerberosName;
import org.apache.yetus.audience.InterfaceAudience;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableSet;
@InterfaceAudience.Private
public final class AccessChecker {
@@ -526,4 +532,162 @@ public final class AccessChecker {
return new ArrayList<>();
}
}
+
+ /**
+ * Authorizes that if the current user has the given permissions.
+ * @param user Active user to which authorization checks should be applied
+ * @param request Request type
+ * @param permission Actions being requested
+ * @return True if the user has the specific permission
+ */
+ public boolean hasUserPermission(User user, String request, Permission permission) {
+ if (!authorizationEnabled) {
+ return true;
+ }
+ if (permission instanceof TablePermission) {
+ TablePermission tPerm = (TablePermission) permission;
+ for (Permission.Action action : permission.getActions()) {
+ AuthResult authResult = permissionGranted(request, user, action, tPerm.getTableName(),
+ tPerm.getFamily(), tPerm.getQualifier());
+ AccessChecker.logResult(authResult);
+ if (!authResult.isAllowed()) {
+ return false;
+ }
+ }
+ } else if (permission instanceof NamespacePermission) {
+ NamespacePermission nsPerm = (NamespacePermission) permission;
+ AuthResult authResult;
+ for (Action action : nsPerm.getActions()) {
+ if (getAuthManager().authorizeUserNamespace(user, nsPerm.getNamespace(), action)) {
+ authResult =
+ AuthResult.allow(request, "Namespace action allowed", user, action, null, null);
+ } else {
+ authResult =
+ AuthResult.deny(request, "Namespace action denied", user, action, null, null);
+ }
+ AccessChecker.logResult(authResult);
+ if (!authResult.isAllowed()) {
+ return false;
+ }
+ }
+ } else {
+ AuthResult authResult;
+ for (Permission.Action action : permission.getActions()) {
+ if (getAuthManager().authorizeUserGlobal(user, action)) {
+ authResult = AuthResult.allow(request, "Global action allowed", user, action, null, null);
+ } else {
+ authResult = AuthResult.deny(request, "Global action denied", user, action, null, null);
+ }
+ AccessChecker.logResult(authResult);
+ if (!authResult.isAllowed()) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private AuthResult permissionGranted(String request, User user, Action permRequest,
+ TableName tableName, byte[] family, byte[] qualifier) {
+ Map<byte[], ? extends Collection<byte[]>> map = makeFamilyMap(family, qualifier);
+ return permissionGranted(request, user, permRequest, tableName, map);
+ }
+
+ /**
+ * Check the current user for authorization to perform a specific action against the given set of
+ * row data.
+ * <p>
+ * Note: Ordering of the authorization checks has been carefully optimized to short-circuit the
+ * most common requests and minimize the amount of processing required.
+ * </p>
+ * @param request User request
+ * @param user User name
+ * @param permRequest the action being requested
+ * @param tableName Table name
+ * @param families the map of column families to qualifiers present in the request
+ * @return an authorization result
+ */
+ public AuthResult permissionGranted(String request, User user, Action permRequest,
+ TableName tableName, Map<byte[], ? extends Collection<?>> families) {
+ if (!authorizationEnabled) {
+ return AuthResult.allow(request, "All users allowed because authorization is disabled", user,
+ permRequest, tableName, families);
+ }
+ // 1. All users need read access to hbase:meta table.
+ // this is a very common operation, so deal with it quickly.
+ if (TableName.META_TABLE_NAME.equals(tableName)) {
+ if (permRequest == Action.READ) {
+ return AuthResult.allow(request, "All users allowed", user, permRequest, tableName,
+ families);
+ }
+ }
+
+ if (user == null) {
+ return AuthResult.deny(request, "No user associated with request!", null, permRequest,
+ tableName, families);
+ }
+
+ // 2. check for the table-level, if successful we can short-circuit
+ if (getAuthManager().authorizeUserTable(user, tableName, permRequest)) {
+ return AuthResult.allow(request, "Table permission granted", user, permRequest, tableName,
+ families);
+ }
+
+ // 3. check permissions against the requested families
+ if (families != null && families.size() > 0) {
+ // all families must pass
+ for (Map.Entry<byte[], ? extends Collection<?>> family : families.entrySet()) {
+ // a) check for family level access
+ if (getAuthManager().authorizeUserTable(user, tableName, family.getKey(), permRequest)) {
+ continue; // family-level permission overrides per-qualifier
+ }
+
+ // b) qualifier level access can still succeed
+ if ((family.getValue() != null) && (family.getValue().size() > 0)) {
+ if (family.getValue() instanceof Set) {
+ // for each qualifier of the family
+ Set<byte[]> familySet = (Set<byte[]>) family.getValue();
+ for (byte[] qualifier : familySet) {
+ if (!getAuthManager().authorizeUserTable(user, tableName, family.getKey(), qualifier,
+ permRequest)) {
+ return AuthResult.deny(request, "Failed qualifier check", user, permRequest,
+ tableName, makeFamilyMap(family.getKey(), qualifier));
+ }
+ }
+ } else if (family.getValue() instanceof List) { // List<Cell>
+ List<Cell> cellList = (List<Cell>) family.getValue();
+ for (Cell cell : cellList) {
+ if (!getAuthManager().authorizeUserTable(user, tableName, family.getKey(),
+ CellUtil.cloneQualifier(cell), permRequest)) {
+ return AuthResult.deny(request, "Failed qualifier check", user, permRequest,
+ tableName, makeFamilyMap(family.getKey(), CellUtil.cloneQualifier(cell)));
+ }
+ }
+ }
+ } else {
+ // no qualifiers and family-level check already failed
+ return AuthResult.deny(request, "Failed family check", user, permRequest, tableName,
+ makeFamilyMap(family.getKey(), null));
+ }
+ }
+
+ // all family checks passed
+ return AuthResult.allow(request, "All family checks passed", user, permRequest, tableName,
+ families);
+ }
+
+ // 4. no families to check and table level access failed
+ return AuthResult.deny(request, "No families to check and table permission failed", user,
+ permRequest, tableName, families);
+ }
+
+ private Map<byte[], ? extends Collection<byte[]>> makeFamilyMap(byte[] family, byte[] qualifier) {
+ if (family == null) {
+ return null;
+ }
+
+ Map<byte[], Collection<byte[]>> familyMap = new TreeMap<>(Bytes.BYTES_COMPARATOR);
+ familyMap.put(family, qualifier != null ? ImmutableSet.of(qualifier) : null);
+ return familyMap;
+ }
}
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 aaa2da5..a5ee794 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
@@ -141,7 +141,6 @@ import org.apache.hbase.thirdparty.com.google.common.collect.ListMultimap;
import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
import org.apache.hbase.thirdparty.com.google.common.collect.MapMaker;
import org.apache.hbase.thirdparty.com.google.common.collect.Maps;
-import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
/**
* Provides basic authorization checks for data access and administrative
@@ -299,93 +298,6 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
}
/**
- * Check the current user for authorization to perform a specific action against the given set of
- * row data.
- * <p>
- * Note: Ordering of the authorization checks has been carefully optimized to short-circuit the
- * most common requests and minimize the amount of processing required.
- * </p>
- * @param request User request
- * @param user User name
- * @param permRequest the action being requested
- * @param e the coprocessor environment
- * @param tableName Table name
- * @param families the map of column families to qualifiers present in the request
- * @return an authorization result
- */
- private AuthResult permissionGranted(String request, User user, Action permRequest,
- RegionCoprocessorEnvironment e, TableName tableName,
- Map<byte[], ? extends Collection<?>> families) {
- // 1. All users need read access to hbase:meta table.
- // this is a very common operation, so deal with it quickly.
- if (TableName.META_TABLE_NAME.equals(tableName)) {
- if (permRequest == Action.READ) {
- return AuthResult.allow(request, "All users allowed", user, permRequest, tableName,
- families);
- }
- }
-
- if (user == null) {
- return AuthResult.deny(request, "No user associated with request!", null,
- permRequest, tableName, families);
- }
-
- // 2. check for the table-level, if successful we can short-circuit
- if (getAuthManager().authorizeUserTable(user, tableName, permRequest)) {
- return AuthResult.allow(request, "Table permission granted", user,
- permRequest, tableName, families);
- }
-
- // 3. check permissions against the requested families
- if (families != null && families.size() > 0) {
- // all families must pass
- for (Map.Entry<byte [], ? extends Collection<?>> family : families.entrySet()) {
- // a) check for family level access
- if (getAuthManager().authorizeUserTable(user, tableName, family.getKey(),
- permRequest)) {
- continue; // family-level permission overrides per-qualifier
- }
-
- // b) qualifier level access can still succeed
- if ((family.getValue() != null) && (family.getValue().size() > 0)) {
- if (family.getValue() instanceof Set) {
- // for each qualifier of the family
- Set<byte[]> familySet = (Set<byte[]>)family.getValue();
- for (byte[] qualifier : familySet) {
- if (!getAuthManager().authorizeUserTable(user, tableName,
- family.getKey(), qualifier, permRequest)) {
- return AuthResult.deny(request, "Failed qualifier check", user,
- permRequest, tableName, makeFamilyMap(family.getKey(), qualifier));
- }
- }
- } else if (family.getValue() instanceof List) { // List<Cell>
- List<Cell> cellList = (List<Cell>)family.getValue();
- for (Cell cell : cellList) {
- if (!getAuthManager().authorizeUserTable(user, tableName, family.getKey(),
- CellUtil.cloneQualifier(cell), permRequest)) {
- return AuthResult.deny(request, "Failed qualifier check", user, permRequest,
- tableName, makeFamilyMap(family.getKey(), CellUtil.cloneQualifier(cell)));
- }
- }
- }
- } else {
- // no qualifiers and family-level check already failed
- return AuthResult.deny(request, "Failed family check", user, permRequest,
- tableName, makeFamilyMap(family.getKey(), null));
- }
- }
-
- // all family checks passed
- return AuthResult.allow(request, "All family checks passed", user, permRequest,
- tableName, families);
- }
-
- // 4. no families to check and table level access failed
- return AuthResult.deny(request, "No families to check and table permission failed",
- user, permRequest, tableName, families);
- }
-
- /**
* Check the current user for authorization to perform a specific action
* against the given set of row data.
* @param opType the operation type
@@ -400,7 +312,7 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
Map<byte [], ? extends Collection<?>> families, Action... actions) {
AuthResult result = null;
for (Action action: actions) {
- result = permissionGranted(opType.toString(), user, action, e,
+ result = accessChecker.permissionGranted(opType.toString(), user, action,
e.getRegion().getRegionInfo().getTable(), families);
if (!result.isAllowed()) {
return result;
@@ -2186,76 +2098,40 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
done.run(response);
}
+ /**
+ * @deprecated Use {@link Admin#hasUserPermissions(List)} instead.
+ */
+ @Deprecated
@Override
public void checkPermissions(RpcController controller,
- AccessControlProtos.CheckPermissionsRequest request,
- RpcCallback<AccessControlProtos.CheckPermissionsResponse> done) {
- Permission[] permissions = new Permission[request.getPermissionCount()];
- for (int i=0; i < request.getPermissionCount(); i++) {
- permissions[i] = AccessControlUtil.toPermission(request.getPermission(i));
- }
+ AccessControlProtos.CheckPermissionsRequest request,
+ RpcCallback<AccessControlProtos.CheckPermissionsResponse> done) {
AccessControlProtos.CheckPermissionsResponse response = null;
try {
User user = RpcServer.getRequestUser().orElse(null);
TableName tableName = regionEnv.getRegion().getTableDescriptor().getTableName();
- for (Permission permission : permissions) {
+ List<Permission> permissions = new ArrayList<>();
+ for (int i = 0; i < request.getPermissionCount(); i++) {
+ Permission permission = AccessControlUtil.toPermission(request.getPermission(i));
+ permissions.add(permission);
if (permission instanceof TablePermission) {
- // Check table permissions
-
TablePermission tperm = (TablePermission) permission;
- for (Action action : permission.getActions()) {
- if (!tperm.getTableName().equals(tableName)) {
- throw new CoprocessorException(AccessController.class, String.format("This method "
- + "can only execute at the table specified in TablePermission. " +
- "Table of the region:%s , requested table:%s", tableName,
- tperm.getTableName()));
- }
-
- Map<byte[], Set<byte[]>> familyMap = new TreeMap<>(Bytes.BYTES_COMPARATOR);
- if (tperm.getFamily() != null) {
- if (tperm.getQualifier() != null) {
- Set<byte[]> qualifiers = Sets.newTreeSet(Bytes.BYTES_COMPARATOR);
- qualifiers.add(tperm.getQualifier());
- familyMap.put(tperm.getFamily(), qualifiers);
- } else {
- familyMap.put(tperm.getFamily(), null);
- }
- }
-
- AuthResult result = permissionGranted("checkPermissions", user, action, regionEnv,
- regionEnv.getRegion().getRegionInfo().getTable(), familyMap);
- AccessChecker.logResult(result);
- if (!result.isAllowed()) {
- // Even if passive we need to throw an exception here, we support checking
- // effective permissions, so throw unconditionally
- throw new AccessDeniedException("Insufficient permissions (table=" + tableName +
- (familyMap.size() > 0 ? ", family: " + result.toFamilyString() : "") +
- ", action=" + action.toString() + ")");
- }
- }
-
- } else {
- // Check global permissions
-
- for (Action action : permission.getActions()) {
- AuthResult result;
- if (getAuthManager().authorizeUserGlobal(user, action)) {
- result = AuthResult.allow("checkPermissions", "Global action allowed", user,
- action, null, null);
- } else {
- result = AuthResult.deny("checkPermissions", "Global action denied", user, action,
- null, null);
- }
- AccessChecker.logResult(result);
- if (!result.isAllowed()) {
- // Even if passive we need to throw an exception here, we support checking
- // effective permissions, so throw unconditionally
- throw new AccessDeniedException("Insufficient permissions (action=" +
- action.toString() + ")");
- }
+ if (!tperm.getTableName().equals(tableName)) {
+ throw new CoprocessorException(AccessController.class,
+ String.format(
+ "This method can only execute at the table specified in "
+ + "TablePermission. Table of the region:%s , requested table:%s",
+ tableName, tperm.getTableName()));
}
}
}
+ for (Permission permission : permissions) {
+ boolean hasPermission =
+ accessChecker.hasUserPermission(user, "checkPermissions", permission);
+ if (!hasPermission) {
+ throw new AccessDeniedException("Insufficient permissions " + permission.toString());
+ }
+ }
response = AccessControlProtos.CheckPermissionsResponse.getDefaultInstance();
} catch (IOException ioe) {
CoprocessorRpcUtils.setControllerException(controller, ioe);
@@ -2555,6 +2431,10 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
return userProvider.getCurrent();
}
+ /**
+ * @deprecated Use {@link Admin#hasUserPermissions(String, List)} instead.
+ */
+ @Deprecated
@Override
public void hasPermission(RpcController controller, HasPermissionRequest request,
RpcCallback<HasPermissionResponse> done) {
@@ -2568,33 +2448,10 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
AccessControlProtos.HasPermissionResponse response = null;
try {
User caller = RpcServer.getRequestUser().orElse(null);
- // User instance for the input user name
- User filterUser = accessChecker.validateCallerWithFilterUser(caller, tPerm, inputUserName);
-
- // Initialize family and qualifier map
- Map<byte[], Set<byte[]>> familyMap = new TreeMap<byte[], Set<byte[]>>(Bytes.BYTES_COMPARATOR);
- if (tPerm.getFamily() != null) {
- if (tPerm.getQualifier() != null) {
- Set<byte[]> qualifiers = Sets.newTreeSet(Bytes.BYTES_COMPARATOR);
- qualifiers.add(tPerm.getQualifier());
- familyMap.put(tPerm.getFamily(), qualifiers);
- } else {
- familyMap.put(tPerm.getFamily(), null);
- }
- }
-
- // Iterate each action and check whether permission granted
- boolean hasPermission = false;
- for (Action action : tPerm.getActions()) {
- AuthResult result = permissionGranted("hasPermission", filterUser, action, regionEnv,
- tPerm.getTableName(), familyMap);
- if (!result.isAllowed()) {
- hasPermission = false;
- // Break the loop is any action is not allowed
- break;
- }
- hasPermission = true;
- }
+ List<Permission> permissions = Lists.newArrayList(tPerm);
+ preHasUserPermissions(caller, inputUserName, permissions);
+ boolean hasPermission = regionEnv.getConnection().getAdmin()
+ .hasUserPermissions(inputUserName, permissions).get(0);
response = ResponseConverter.buildHasPermissionResponse(hasPermission);
} catch (IOException ioe) {
ResponseConverter.setControllerException(controller, ioe);
@@ -2656,4 +2513,48 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
accessChecker.requirePermission(caller, "getUserPermissions", userName, Action.ADMIN);
}
}
+
+ @Override
+ public void preHasUserPermissions(ObserverContext<MasterCoprocessorEnvironment> ctx,
+ String userName, List<Permission> permissions) throws IOException {
+ preHasUserPermissions(getActiveUser(ctx), userName, permissions);
+ }
+
+ private void preHasUserPermissions(User caller, String userName, List<Permission> permissions)
+ throws IOException {
+ String request = "hasUserPermissions";
+ for (Permission permission : permissions) {
+ if (!caller.getShortName().equals(userName)) {
+ // User should have admin privilege if checking permission for other users
+ if (permission instanceof TablePermission) {
+ TablePermission tPerm = (TablePermission) permission;
+ accessChecker.requirePermission(caller, request, tPerm.getTableName(), tPerm.getFamily(),
+ tPerm.getQualifier(), userName, Action.ADMIN);
+ } else if (permission instanceof NamespacePermission) {
+ NamespacePermission nsPerm = (NamespacePermission) permission;
+ accessChecker.requireNamespacePermission(caller, request, nsPerm.getNamespace(), userName,
+ Action.ADMIN);
+ } else {
+ accessChecker.requirePermission(caller, request, userName, Action.ADMIN);
+ }
+ } else {
+ // User don't need ADMIN privilege for self check.
+ // Setting action as null in AuthResult to display empty action in audit log
+ AuthResult result;
+ if (permission instanceof TablePermission) {
+ TablePermission tPerm = (TablePermission) permission;
+ result = AuthResult.allow(request, "Self user validation allowed", caller, null,
+ tPerm.getTableName(), tPerm.getFamily(), tPerm.getQualifier());
+ } else if (permission instanceof NamespacePermission) {
+ NamespacePermission nsPerm = (NamespacePermission) permission;
+ result = AuthResult.allow(request, "Self user validation allowed", caller, null,
+ nsPerm.getNamespace());
+ } else {
+ result = AuthResult.allow(request, "Self user validation allowed", caller, null, null,
+ null, null);
+ }
+ accessChecker.logResult(result);
+ }
+ }
+ }
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAccessControlAdminApi.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAccessControlAdminApi.java
index 8075ae0..fbb08c6 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAccessControlAdminApi.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAccessControlAdminApi.java
@@ -12,14 +12,19 @@
package org.apache.hadoop.hbase.client;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.util.List;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.security.access.AccessControlLists;
import org.apache.hadoop.hbase.security.access.GetUserPermissionsRequest;
import org.apache.hadoop.hbase.security.access.Permission;
import org.apache.hadoop.hbase.security.access.SecureTestUtil;
+import org.apache.hadoop.hbase.security.access.SecureTestUtil.AccessTestAction;
import org.apache.hadoop.hbase.security.access.UserPermission;
import org.apache.hadoop.hbase.testclassification.ClientTests;
import org.apache.hadoop.hbase.testclassification.SmallTests;
@@ -29,6 +34,7 @@ import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
@RunWith(Parameterized.class)
@Category({ ClientTests.class, SmallTests.class })
@@ -47,12 +53,16 @@ public class TestAsyncAccessControlAdminApi extends TestAsyncAdminBase {
}
@Test
- public void testGrant() throws Exception {
+ public void test() throws Exception {
TableName tableName = TableName.valueOf("test-table");
- String user = "test-user";
- UserPermission userPermission = new UserPermission(user,
- Permission.newBuilder(tableName).withActions(Permission.Action.READ).build());
- // grant user table permission
+ String userName1 = "user1";
+ String userName2 = "user2";
+ User user2 = User.createUserForTesting(TEST_UTIL.getConfiguration(), userName2, new String[0]);
+ Permission permission =
+ Permission.newBuilder(tableName).withActions(Permission.Action.READ).build();
+ UserPermission userPermission = new UserPermission(userName1, permission);
+
+ // grant user1 table permission
admin.grant(userPermission, false).get();
// get table permissions
@@ -61,14 +71,57 @@ public class TestAsyncAccessControlAdminApi extends TestAsyncAdminBase {
assertEquals(1, userPermissions.size());
assertEquals(userPermission, userPermissions.get(0));
- // get user table permissions
- userPermissions = admin.getUserPermissions(
- GetUserPermissionsRequest.newBuilder(tableName).withUserName(user).build()).get();
+ // get table permissions
+ userPermissions =
+ admin
+ .getUserPermissions(
+ GetUserPermissionsRequest.newBuilder(tableName).withUserName(userName1).build())
+ .get();
assertEquals(1, userPermissions.size());
assertEquals(userPermission, userPermissions.get(0));
- userPermissions = admin.getUserPermissions(
- GetUserPermissionsRequest.newBuilder(tableName).withUserName("u").build()).get();
+ userPermissions =
+ admin
+ .getUserPermissions(
+ GetUserPermissionsRequest.newBuilder(tableName).withUserName(userName2).build())
+ .get();
assertEquals(0, userPermissions.size());
+
+ // has user permission
+ List<Permission> permissions = Lists.newArrayList(permission);
+ boolean hasPermission =
+ admin.hasUserPermissions(userName1, permissions).get().get(0).booleanValue();
+ assertTrue(hasPermission);
+ hasPermission = admin.hasUserPermissions(userName2, permissions).get().get(0).booleanValue();
+ assertFalse(hasPermission);
+
+ AccessTestAction hasPermissionAction = new AccessTestAction() {
+ @Override
+ public Object run() throws Exception {
+ try (AsyncConnection conn =
+ ConnectionFactory.createAsyncConnection(TEST_UTIL.getConfiguration()).get()) {
+ return conn.getAdmin().hasUserPermissions(userName1, permissions).get().get(0);
+ }
+ }
+ };
+ try {
+ user2.runAs(hasPermissionAction);
+ fail("Should not come here");
+ } catch (Exception e) {
+ LOG.error("Call has permission error", e);
+ }
+
+ // check permission
+ admin.hasUserPermissions(permissions);
+ AccessTestAction checkPermissionsAction = new AccessTestAction() {
+ @Override
+ public Object run() throws Exception {
+ try (AsyncConnection conn =
+ ConnectionFactory.createAsyncConnection(TEST_UTIL.getConfiguration()).get()) {
+ return conn.getAdmin().hasUserPermissions(permissions).get().get(0);
+ }
+ }
+ };
+ assertFalse((Boolean) user2.runAs(checkPermissionsAction));
}
}
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 eecd773..341e7df 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
@@ -18,6 +18,7 @@
package org.apache.hadoop.hbase.security.access;
+import com.google.protobuf.ServiceException;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.security.PrivilegedActionException;
@@ -28,9 +29,6 @@ import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
-import com.google.protobuf.BlockingRpcChannel;
-import com.google.protobuf.ServiceException;
-
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Coprocessor;
import org.apache.hadoop.hbase.HBaseTestingUtility;
@@ -54,14 +52,9 @@ import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
import org.apache.hadoop.hbase.coprocessor.MasterObserver;
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
import org.apache.hadoop.hbase.io.hfile.HFile;
-import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
-import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
-import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
-import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.CheckPermissionsRequest;
import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.security.AccessDeniedException;
import org.apache.hadoop.hbase.security.User;
-import org.apache.hadoop.hbase.security.access.Permission.Action;
import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
import org.apache.hbase.thirdparty.com.google.common.collect.Maps;
import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
@@ -140,36 +133,6 @@ public class SecureTestUtil {
}
}
- public static void checkTablePerms(Configuration conf, TableName table, byte[] family, byte[] column,
- Permission.Action... actions) throws IOException {
- Permission[] perms = new Permission[actions.length];
- for (int i = 0; i < actions.length; i++) {
- perms[i] = Permission.newBuilder(table).withFamily(family).withQualifier(column)
- .withActions(actions[i]).build();
- }
-
- checkTablePerms(conf, table, perms);
- }
-
- public static void checkTablePerms(Configuration conf, TableName table, Permission... perms)
- throws IOException {
- CheckPermissionsRequest.Builder request = CheckPermissionsRequest.newBuilder();
- for (Permission p : perms) {
- request.addPermission(AccessControlUtil.toPermission(p));
- }
- try (Connection connection = ConnectionFactory.createConnection(conf)) {
- try (Table acl = connection.getTable(table)) {
- AccessControlService.BlockingInterface protocol =
- AccessControlService.newBlockingStub(acl.coprocessorService(new byte[0]));
- try {
- protocol.checkPermissions(null, request.build());
- } catch (ServiceException se) {
- ProtobufUtil.toIOException(se);
- }
- }
- }
- }
-
/**
* An AccessTestAction performs an action that will be examined to confirm
* the results conform to expected access rights.
@@ -854,25 +817,7 @@ public class SecureTestUtil {
for (int i = 0; i < actions.length; i++) {
perms[i] = new Permission(actions[i]);
}
- CheckPermissionsRequest.Builder request = CheckPermissionsRequest.newBuilder();
- for (Action a : actions) {
- request.addPermission(AccessControlProtos.Permission.newBuilder()
- .setType(AccessControlProtos.Permission.Type.Global)
- .setGlobalPermission(
- AccessControlProtos.GlobalPermission.newBuilder()
- .addAction(AccessControlUtil.toPermissionAction(a)).build()));
- }
- try(Connection conn = ConnectionFactory.createConnection(testUtil.getConfiguration());
- Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) {
- BlockingRpcChannel channel = acl.coprocessorService(new byte[0]);
- AccessControlService.BlockingInterface protocol =
- AccessControlService.newBlockingStub(channel);
- try {
- protocol.checkPermissions(null, request.build());
- } catch (ServiceException se) {
- ProtobufUtil.toIOException(se);
- }
- }
+ checkPermissions(testUtil.getConfiguration(), perms);
}
public static void checkTablePerms(HBaseTestingUtility testUtil, TableName table, byte[] family,
@@ -882,26 +827,23 @@ public class SecureTestUtil {
perms[i] = Permission.newBuilder(table).withFamily(family).withQualifier(column)
.withActions(actions[i]).build();
}
- checkTablePerms(testUtil, table, perms);
+ checkTablePerms(testUtil, perms);
}
- public static void checkTablePerms(HBaseTestingUtility testUtil, TableName table,
- Permission... perms) throws IOException {
- CheckPermissionsRequest.Builder request = CheckPermissionsRequest.newBuilder();
- for (Permission p : perms) {
- request.addPermission(AccessControlUtil.toPermission(p));
- }
+ public static void checkTablePerms(HBaseTestingUtility testUtil, Permission... perms)
+ throws IOException {
+ checkPermissions(testUtil.getConfiguration(), perms);
+ }
- try(Connection conn = ConnectionFactory.createConnection(testUtil.getConfiguration());
- Table acl = conn.getTable(table)) {
- AccessControlService.BlockingInterface protocol =
- AccessControlService.newBlockingStub(acl.coprocessorService(new byte[0]));
- try {
- protocol.checkPermissions(null, request.build());
- } catch (ServiceException se) {
- ProtobufUtil.toIOException(se);
+ private static void checkPermissions(Configuration conf, Permission... perms) throws IOException {
+ try (Connection conn = ConnectionFactory.createConnection(conf)) {
+ List<Boolean> hasUserPermissions =
+ conn.getAdmin().hasUserPermissions(Lists.newArrayList(perms));
+ for (int i = 0; i < hasUserPermissions.size(); i++) {
+ if (!hasUserPermissions.get(i).booleanValue()) {
+ throw new AccessDeniedException("Insufficient permissions " + perms[i]);
+ }
}
}
}
-
}
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 fae2e2f..a5a8a04 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
@@ -1844,7 +1844,7 @@ public class TestAccessController extends SecureTestUtil {
AccessTestAction multiQualifierRead = new AccessTestAction() {
@Override
public Void run() throws Exception {
- checkTablePerms(TEST_UTIL, TEST_TABLE,
+ checkTablePerms(TEST_UTIL,
new Permission[] {
Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY).withQualifier(TEST_Q1)
.withActions(Permission.Action.READ).build(),
@@ -1857,8 +1857,7 @@ public class TestAccessController extends SecureTestUtil {
AccessTestAction globalAndTableRead = new AccessTestAction() {
@Override
public Void run() throws Exception {
- checkTablePerms(TEST_UTIL, TEST_TABLE, new Permission[] {
- new Permission(Permission.Action.READ),
+ checkTablePerms(TEST_UTIL, new Permission[] { new Permission(Permission.Action.READ),
Permission.newBuilder(TEST_TABLE).withActions(Permission.Action.READ).build() });
return null;
}
@@ -1867,7 +1866,7 @@ public class TestAccessController extends SecureTestUtil {
AccessTestAction noCheck = new AccessTestAction() {
@Override
public Void run() throws Exception {
- checkTablePerms(TEST_UTIL, TEST_TABLE, new Permission[0]);
+ checkTablePerms(TEST_UTIL, new Permission[0]);
return null;
}
};
@@ -3333,7 +3332,7 @@ public class TestAccessController extends SecureTestUtil {
TEST_FAMILY, TEST_QUALIFIER, Permission.Action.READ, Permission.Action.WRITE);
// Verify action privilege
- AccessTestAction hasPermissionAction = new AccessTestAction() {
+ AccessTestAction hasPermissionActionCP = new AccessTestAction() {
@Override
public Object run() throws Exception {
try (Connection conn = ConnectionFactory.createConnection(conf);
@@ -3348,6 +3347,21 @@ public class TestAccessController extends SecureTestUtil {
return null;
}
};
+ AccessTestAction hasPermissionAction = new AccessTestAction() {
+ @Override
+ public Object run() throws Exception {
+ try (Connection conn = ConnectionFactory.createConnection(conf)) {
+ Permission.Action[] actions = { Permission.Action.READ, Permission.Action.WRITE };
+ conn.getAdmin().hasUserPermissions("dummy",
+ Arrays.asList(Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY)
+ .withQualifier(HConstants.EMPTY_BYTE_ARRAY).withActions(actions).build()));
+ }
+ return null;
+ }
+ };
+ verifyAllowed(hasPermissionActionCP, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN, USER_OWNER,
+ USER_ADMIN_CF, user1);
+ verifyDenied(hasPermissionActionCP, USER_CREATE, USER_RW, USER_RO, USER_NONE, user2);
verifyAllowed(hasPermissionAction, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN, USER_OWNER,
USER_ADMIN_CF, user1);
verifyDenied(hasPermissionAction, USER_CREATE, USER_RW, USER_RO, USER_NONE, user2);
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestWithDisabledAuthorization.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestWithDisabledAuthorization.java
index bc59f70..8bc5718 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestWithDisabledAuthorization.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestWithDisabledAuthorization.java
@@ -250,9 +250,8 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyAllowed(checkGlobalAdmin, SUPERUSER, USER_ADMIN);
- verifyDenied(checkGlobalAdmin, USER_OWNER, USER_CREATE, USER_RW, USER_RO, USER_QUAL,
- USER_NONE);
+ verifyAllowed(checkGlobalAdmin, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
+ USER_RO, USER_QUAL, USER_NONE);
AccessTestAction checkGlobalRead = new AccessTestAction() {
@Override
@@ -262,9 +261,8 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyAllowed(checkGlobalRead, SUPERUSER, USER_ADMIN);
- verifyDenied(checkGlobalRead, USER_OWNER, USER_CREATE, USER_RW, USER_RO, USER_QUAL,
- USER_NONE);
+ verifyAllowed(checkGlobalRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO,
+ USER_QUAL, USER_NONE);
AccessTestAction checkGlobalReadWrite = new AccessTestAction() {
@Override
@@ -274,9 +272,8 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyAllowed(checkGlobalReadWrite, SUPERUSER, USER_ADMIN);
- verifyDenied(checkGlobalReadWrite, USER_OWNER, USER_CREATE, USER_RW, USER_RO, USER_QUAL,
- USER_NONE);
+ verifyAllowed(checkGlobalReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
+ USER_RO, USER_QUAL, USER_NONE);
AccessTestAction checkTableAdmin = new AccessTestAction() {
@Override
@@ -287,8 +284,8 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyAllowed(checkTableAdmin, SUPERUSER, USER_ADMIN, USER_OWNER);
- verifyDenied(checkTableAdmin, USER_CREATE, USER_RW, USER_RO, USER_QUAL, USER_NONE);
+ verifyAllowed(checkTableAdmin, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO,
+ USER_QUAL, USER_NONE);
AccessTestAction checkTableCreate = new AccessTestAction() {
@Override
@@ -299,8 +296,8 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyAllowed(checkTableCreate, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE);
- verifyDenied(checkTableCreate, USER_RW, USER_RO, USER_QUAL, USER_NONE);
+ verifyAllowed(checkTableCreate, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
+ USER_RO, USER_QUAL, USER_NONE);
AccessTestAction checkTableRead = new AccessTestAction() {
@Override
@@ -311,8 +308,8 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyAllowed(checkTableRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE);
- verifyDenied(checkTableRead, USER_RW, USER_RO, USER_QUAL, USER_NONE);
+ verifyAllowed(checkTableRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO,
+ USER_QUAL, USER_NONE);
AccessTestAction checkTableReadWrite = new AccessTestAction() {
@Override
@@ -323,8 +320,8 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyAllowed(checkTableReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE);
- verifyDenied(checkTableReadWrite, USER_RW, USER_RO, USER_QUAL, USER_NONE);
+ verifyAllowed(checkTableReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
+ USER_RO, USER_QUAL, USER_NONE);
AccessTestAction checkColumnRead = new AccessTestAction() {
@Override
@@ -335,9 +332,8 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyAllowed(checkColumnRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
- USER_RO);
- verifyDenied(checkColumnRead, USER_QUAL, USER_NONE);
+ verifyAllowed(checkColumnRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW, USER_RO,
+ USER_QUAL, USER_NONE);
AccessTestAction checkColumnReadWrite = new AccessTestAction() {
@Override
@@ -348,9 +344,8 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyAllowed(checkColumnReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
- USER_RW);
- verifyDenied(checkColumnReadWrite, USER_RO, USER_QUAL, USER_NONE);
+ verifyAllowed(checkColumnReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
+ USER_RO, USER_QUAL, USER_NONE);
AccessTestAction checkQualifierRead = new AccessTestAction() {
@Override
@@ -362,8 +357,7 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
};
verifyAllowed(checkQualifierRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
- USER_RO, USER_QUAL);
- verifyDenied(checkQualifierRead, USER_NONE);
+ USER_RO, USER_QUAL, USER_NONE);
AccessTestAction checkQualifierReadWrite = new AccessTestAction() {
@Override
@@ -374,14 +368,13 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyAllowed(checkQualifierReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
- USER_RW, USER_QUAL);
- verifyDenied(checkQualifierReadWrite, USER_RO, USER_NONE);
+ verifyAllowed(checkQualifierReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
+ USER_QUAL, USER_RO, USER_NONE);
AccessTestAction checkMultiQualifierRead = new AccessTestAction() {
@Override
public Void run() throws Exception {
- checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(),
+ checkTablePerms(TEST_UTIL,
new Permission[] {
Permission.newBuilder(TEST_TABLE.getTableName()).withFamily(TEST_FAMILY)
.withQualifier(TEST_Q1).withActions(Action.READ).build(),
@@ -391,14 +384,13 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyAllowed(checkMultiQualifierRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
- USER_RW, USER_RO);
- verifyDenied(checkMultiQualifierRead, USER_QUAL, USER_NONE);
+ verifyAllowed(checkMultiQualifierRead, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE, USER_RW,
+ USER_RO, USER_QUAL, USER_NONE);
AccessTestAction checkMultiQualifierReadWrite = new AccessTestAction() {
@Override
public Void run() throws Exception {
- checkTablePerms(TEST_UTIL, TEST_TABLE.getTableName(),
+ checkTablePerms(TEST_UTIL,
new Permission[] {
Permission.newBuilder(TEST_TABLE.getTableName()).withFamily(TEST_FAMILY)
.withQualifier(TEST_Q1)
@@ -411,8 +403,7 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
};
verifyAllowed(checkMultiQualifierReadWrite, SUPERUSER, USER_ADMIN, USER_OWNER, USER_CREATE,
- USER_RW);
- verifyDenied(checkMultiQualifierReadWrite, USER_RO, USER_QUAL, USER_NONE);
+ USER_RW, USER_RO, USER_QUAL, USER_NONE);
}
/** Test grants and revocations with authorization disabled */
@@ -424,7 +415,7 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
User tblUser = User.createUserForTesting(TEST_UTIL.getConfiguration(), "tbluser",
new String[0]);
- // If we check now, the test user won't have permissions
+ // If we check now, the test user have permissions because authorization is disabled
AccessTestAction checkTableRead = new AccessTestAction() {
@Override
@@ -435,7 +426,7 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
}
};
- verifyDenied(tblUser, checkTableRead);
+ verifyAllowed(tblUser, checkTableRead);
// An actual read won't be denied
@@ -469,7 +460,7 @@ public class TestWithDisabledAuthorization extends SecureTestUtil {
// Now the permission check will indicate revocation but the actual op will still succeed
- verifyDenied(tblUser, checkTableRead);
+ verifyAllowed(tblUser, checkTableRead);
verifyAllowed(tblUser, tableRead);
}
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 7ff1979..fbb6722 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
@@ -57,6 +57,7 @@ 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.GetUserPermissionsRequest;
+import org.apache.hadoop.hbase.security.access.Permission;
import org.apache.hadoop.hbase.security.access.UserPermission;
import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
import org.apache.hadoop.hbase.thrift2.ThriftUtilities;
@@ -1122,6 +1123,11 @@ public class ThriftAdmin implements Admin {
}
@Override
+ public List<Boolean> hasUserPermissions(String userName, List<Permission> permissions) {
+ throw new NotImplementedException("hasUserPermissions not supported in ThriftAdmin");
+ }
+
+ @Override
public Future<Void> splitRegionAsync(byte[] regionName) throws IOException {
return splitRegionAsync(regionName, null);
}