HBASE-21911 Move getUserPermissions from regionserver to master
Signed-off-by: Guanghao Zhang <zghao@apache.org>
This commit is contained in:
parent
f5b20451db
commit
89dbab7c9f
|
@ -56,6 +56,7 @@ import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
|
|||
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.security.access.GetUserPermissionsRequest;
|
||||
import org.apache.hadoop.hbase.security.access.UserPermission;
|
||||
import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
|
||||
import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
|
||||
|
@ -2921,4 +2922,14 @@ public interface Admin extends Abortable, Closeable {
|
|||
* @throws IOException if a remote or network exception occurs
|
||||
*/
|
||||
void revoke(UserPermission userPermission) throws IOException;
|
||||
|
||||
/**
|
||||
* Get the global/namespace/table permissions for user
|
||||
* @param getUserPermissionsRequest A request contains which user, global, namespace or table
|
||||
* permissions needed
|
||||
* @return The user and permission list
|
||||
* @throws IOException if a remote or network exception occurs
|
||||
*/
|
||||
List<UserPermission> getUserPermissions(GetUserPermissionsRequest getUserPermissionsRequest)
|
||||
throws IOException;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.apache.hadoop.hbase.quotas.QuotaSettings;
|
|||
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.security.access.GetUserPermissionsRequest;
|
||||
import org.apache.hadoop.hbase.security.access.UserPermission;
|
||||
import org.apache.yetus.audience.InterfaceAudience;
|
||||
|
||||
|
@ -1414,4 +1415,13 @@ public interface AsyncAdmin {
|
|||
* @param userPermission user name and the specific permission
|
||||
*/
|
||||
CompletableFuture<Void> revoke(UserPermission userPermission);
|
||||
|
||||
/**
|
||||
* Get the global/namespace/table permissions for user
|
||||
* @param getUserPermissionsRequest A request contains which user, global, namespace or table
|
||||
* permissions needed
|
||||
* @return The user and permission list
|
||||
*/
|
||||
CompletableFuture<List<UserPermission>>
|
||||
getUserPermissions(GetUserPermissionsRequest getUserPermissionsRequest);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.apache.hadoop.hbase.quotas.QuotaSettings;
|
|||
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.security.access.GetUserPermissionsRequest;
|
||||
import org.apache.hadoop.hbase.security.access.UserPermission;
|
||||
import org.apache.hadoop.hbase.util.FutureUtils;
|
||||
import org.apache.yetus.audience.InterfaceAudience;
|
||||
|
@ -805,4 +806,10 @@ class AsyncHBaseAdmin implements AsyncAdmin {
|
|||
public CompletableFuture<Void> revoke(UserPermission userPermission) {
|
||||
return wrap(rawAdmin.revoke(userPermission));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<UserPermission>>
|
||||
getUserPermissions(GetUserPermissionsRequest getUserPermissionsRequest) {
|
||||
return wrap(rawAdmin.getUserPermissions(getUserPermissionsRequest));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,6 +93,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;
|
||||
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.AdminProtos;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.ClientService.BlockingInterface;
|
||||
|
@ -1786,6 +1788,12 @@ class ConnectionImplementation implements ClusterConnection, Closeable {
|
|||
AccessControlProtos.RevokeRequest request) throws ServiceException {
|
||||
return stub.revoke(controller, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetUserPermissionsResponse getUserPermissions(RpcController controller,
|
||||
GetUserPermissionsRequest request) throws ServiceException {
|
||||
return stub.getUserPermissions(controller, request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
|
|||
import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
|
||||
import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
|
||||
import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
|
||||
import org.apache.hadoop.hbase.security.access.GetUserPermissionsRequest;
|
||||
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,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.AccessControlProtos.GrantRequest;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.RevokeRequest;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;
|
||||
|
@ -4256,4 +4258,22 @@ public class HBaseAdmin implements Admin {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserPermission>
|
||||
getUserPermissions(GetUserPermissionsRequest getUserPermissionsRequest) throws IOException {
|
||||
return executeCallable(
|
||||
new MasterCallable<List<UserPermission>>(getConnection(), getRpcControllerFactory()) {
|
||||
@Override
|
||||
protected List<UserPermission> rpcCall() throws Exception {
|
||||
AccessControlProtos.GetUserPermissionsRequest req =
|
||||
ShadedAccessControlUtil.buildGetUserPermissionsRequest(getUserPermissionsRequest);
|
||||
AccessControlProtos.GetUserPermissionsResponse response =
|
||||
this.master.getUserPermissions(getRpcController(), req);
|
||||
return response.getUserPermissionList().stream()
|
||||
.map(userPermission -> ShadedAccessControlUtil.toUserPermission(userPermission))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
|
|||
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.security.access.GetUserPermissionsRequest;
|
||||
import org.apache.hadoop.hbase.security.access.ShadedAccessControlUtil;
|
||||
import org.apache.hadoop.hbase.security.access.UserPermission;
|
||||
import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
|
||||
|
@ -105,6 +106,8 @@ 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;
|
||||
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.RevokeRequest;
|
||||
|
@ -3769,4 +3772,18 @@ class RawAsyncHBaseAdmin implements AsyncAdmin {
|
|||
(s, c, req, done) -> s.revoke(c, req, done), resp -> null))
|
||||
.call();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<UserPermission>>
|
||||
getUserPermissions(GetUserPermissionsRequest getUserPermissionsRequest) {
|
||||
return this.<List<UserPermission>> newMasterCaller().action((controller,
|
||||
stub) -> this.<AccessControlProtos.GetUserPermissionsRequest, GetUserPermissionsResponse,
|
||||
List<UserPermission>> call(controller, stub,
|
||||
ShadedAccessControlUtil.buildGetUserPermissionsRequest(getUserPermissionsRequest),
|
||||
(s, c, req, done) -> s.getUserPermissions(c, req, done),
|
||||
resp -> resp.getUserPermissionList().stream()
|
||||
.map(uPerm -> ShadedAccessControlUtil.toUserPermission(uPerm))
|
||||
.collect(Collectors.toList())))
|
||||
.call();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ 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.GetUserPermissionsRequest;
|
||||
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.RevokeRequest;
|
||||
|
@ -679,4 +681,10 @@ public class ShortCircuitMasterConnection implements MasterKeepAliveConnection {
|
|||
throws ServiceException {
|
||||
return stub.revoke(controller, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetUserPermissionsResponse getUserPermissions(RpcController controller,
|
||||
GetUserPermissionsRequest request) throws ServiceException {
|
||||
return stub.getUserPermissions(controller, request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,11 +24,11 @@ import java.util.regex.Pattern;
|
|||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hadoop.hbase.HConstants;
|
||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||
import org.apache.hadoop.hbase.MasterNotRunningException;
|
||||
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
|
||||
import org.apache.hadoop.hbase.client.TableDescriptor;
|
||||
import org.apache.yetus.audience.InterfaceAudience;
|
||||
import org.apache.hadoop.hbase.client.Admin;
|
||||
import org.apache.hadoop.hbase.client.Connection;
|
||||
|
@ -250,36 +250,27 @@ public class AccessControlClient {
|
|||
*/
|
||||
public static List<UserPermission> getUserPermissions(Connection connection, String tableRegex,
|
||||
String userName) throws Throwable {
|
||||
/**
|
||||
* TODO: Pass an rpcController HBaseRpcController controller = ((ClusterConnection)
|
||||
* connection).getRpcControllerFactory().newController();
|
||||
*/
|
||||
List<UserPermission> permList = new ArrayList<>();
|
||||
try (Table table = connection.getTable(ACL_TABLE_NAME)) {
|
||||
try (Admin admin = connection.getAdmin()) {
|
||||
CoprocessorRpcChannel service = table.coprocessorService(HConstants.EMPTY_START_ROW);
|
||||
BlockingInterface protocol =
|
||||
AccessControlProtos.AccessControlService.newBlockingStub(service);
|
||||
HTableDescriptor[] htds = null;
|
||||
if (tableRegex == null || tableRegex.isEmpty()) {
|
||||
permList = AccessControlUtil.getUserPermissions(null, protocol, userName);
|
||||
} else if (tableRegex.charAt(0) == '@') { // Namespaces
|
||||
String namespaceRegex = tableRegex.substring(1);
|
||||
for (NamespaceDescriptor nsds : admin.listNamespaceDescriptors()) { // Read out all
|
||||
// namespaces
|
||||
String namespace = nsds.getName();
|
||||
if (namespace.matches(namespaceRegex)) { // Match the given namespace regex?
|
||||
permList.addAll(AccessControlUtil.getUserPermissions(null, protocol,
|
||||
Bytes.toBytes(namespace), userName));
|
||||
}
|
||||
}
|
||||
} else { // Tables
|
||||
htds = admin.listTables(Pattern.compile(tableRegex), true);
|
||||
for (HTableDescriptor htd : htds) {
|
||||
permList.addAll(AccessControlUtil.getUserPermissions(null, protocol, htd.getTableName(),
|
||||
null, null, userName));
|
||||
try (Admin admin = connection.getAdmin()) {
|
||||
if (tableRegex == null || tableRegex.isEmpty()) {
|
||||
permList = admin.getUserPermissions(
|
||||
GetUserPermissionsRequest.newBuilder().withUserName(userName).build());
|
||||
} else if (tableRegex.charAt(0) == '@') { // Namespaces
|
||||
String namespaceRegex = tableRegex.substring(1);
|
||||
for (NamespaceDescriptor nsds : admin.listNamespaceDescriptors()) { // Read out all
|
||||
// namespaces
|
||||
String namespace = nsds.getName();
|
||||
if (namespace.matches(namespaceRegex)) { // Match the given namespace regex?
|
||||
permList.addAll(admin.getUserPermissions(
|
||||
GetUserPermissionsRequest.newBuilder(namespace).withUserName(userName).build()));
|
||||
}
|
||||
}
|
||||
} else { // Tables
|
||||
List<TableDescriptor> htds = admin.listTableDescriptors(Pattern.compile(tableRegex), true);
|
||||
for (TableDescriptor htd : htds) {
|
||||
permList.addAll(admin.getUserPermissions(GetUserPermissionsRequest
|
||||
.newBuilder(htd.getTableName()).withUserName(userName).build()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return permList;
|
||||
|
@ -348,22 +339,14 @@ public class AccessControlClient {
|
|||
if (tableRegex == null || tableRegex.isEmpty() || tableRegex.charAt(0) == '@') {
|
||||
throw new IllegalArgumentException("Table name can't be null or empty or a namespace.");
|
||||
}
|
||||
/**
|
||||
* TODO: Pass an rpcController HBaseRpcController controller = ((ClusterConnection)
|
||||
* connection).getRpcControllerFactory().newController();
|
||||
*/
|
||||
List<UserPermission> permList = new ArrayList<UserPermission>();
|
||||
try (Table table = connection.getTable(ACL_TABLE_NAME)) {
|
||||
try (Admin admin = connection.getAdmin()) {
|
||||
CoprocessorRpcChannel service = table.coprocessorService(HConstants.EMPTY_START_ROW);
|
||||
BlockingInterface protocol =
|
||||
AccessControlProtos.AccessControlService.newBlockingStub(service);
|
||||
HTableDescriptor[] htds = admin.listTables(Pattern.compile(tableRegex), true);
|
||||
// Retrieve table permissions
|
||||
for (HTableDescriptor htd : htds) {
|
||||
permList.addAll(AccessControlUtil.getUserPermissions(null, protocol, htd.getTableName(),
|
||||
columnFamily, columnQualifier, userName));
|
||||
}
|
||||
try (Admin admin = connection.getAdmin()) {
|
||||
List<TableDescriptor> htds = admin.listTableDescriptors(Pattern.compile(tableRegex), true);
|
||||
// Retrieve table permissions
|
||||
for (TableDescriptor htd : htds) {
|
||||
permList.addAll(admin.getUserPermissions(
|
||||
GetUserPermissionsRequest.newBuilder(htd.getTableName()).withFamily(columnFamily)
|
||||
.withQualifier(columnQualifier).withUserName(userName).build()));
|
||||
}
|
||||
}
|
||||
return permList;
|
||||
|
|
|
@ -654,7 +654,9 @@ public class AccessControlUtil {
|
|||
* @param controller RpcController
|
||||
* @param protocol the AccessControlService protocol proxy
|
||||
* @throws ServiceException on failure
|
||||
* @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static List<UserPermission> getUserPermissions(RpcController controller,
|
||||
AccessControlService.BlockingInterface protocol) throws ServiceException {
|
||||
return getUserPermissions(controller, protocol, HConstants.EMPTY_STRING);
|
||||
|
@ -666,7 +668,9 @@ public class AccessControlUtil {
|
|||
* @param protocol the AccessControlService protocol proxy
|
||||
* @param userName User name, if empty then all user permissions will be retrieved.
|
||||
* @throws ServiceException
|
||||
* @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static List<UserPermission> getUserPermissions(RpcController controller,
|
||||
AccessControlService.BlockingInterface protocol, String userName) throws ServiceException {
|
||||
AccessControlProtos.GetUserPermissionsRequest.Builder builder =
|
||||
|
@ -695,7 +699,9 @@ public class AccessControlUtil {
|
|||
* @param protocol the AccessControlService protocol proxy
|
||||
* @param t optional table name
|
||||
* @throws ServiceException
|
||||
* @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static List<UserPermission> getUserPermissions(RpcController controller,
|
||||
AccessControlService.BlockingInterface protocol,
|
||||
TableName t) throws ServiceException {
|
||||
|
@ -712,7 +718,9 @@ public class AccessControlUtil {
|
|||
* @param columnQualifier Column qualifier
|
||||
* @param userName User name, if empty then all user permissions will be retrieved.
|
||||
* @throws ServiceException
|
||||
* @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static List<UserPermission> getUserPermissions(RpcController controller,
|
||||
AccessControlService.BlockingInterface protocol, TableName t, byte[] columnFamily,
|
||||
byte[] columnQualifier, String userName) throws ServiceException {
|
||||
|
@ -751,7 +759,9 @@ public class AccessControlUtil {
|
|||
* @param protocol the AccessControlService protocol proxy
|
||||
* @param namespace name of the namespace
|
||||
* @throws ServiceException
|
||||
* @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static List<UserPermission> getUserPermissions(RpcController controller,
|
||||
AccessControlService.BlockingInterface protocol,
|
||||
byte[] namespace) throws ServiceException {
|
||||
|
@ -765,7 +775,9 @@ public class AccessControlUtil {
|
|||
* @param namespace name of the namespace
|
||||
* @param userName User name, if empty then all user permissions will be retrieved.
|
||||
* @throws ServiceException
|
||||
* @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static List<UserPermission> getUserPermissions(RpcController controller,
|
||||
AccessControlService.BlockingInterface protocol, byte[] namespace, String userName)
|
||||
throws ServiceException {
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hadoop.hbase.security.access;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.yetus.audience.InterfaceAudience;
|
||||
|
||||
/**
|
||||
* Used by
|
||||
* {@link org.apache.hadoop.hbase.client.Admin#getUserPermissions(GetUserPermissionsRequest)}.
|
||||
* Represents the params of user permissions needed to get from HBase.
|
||||
*/
|
||||
@InterfaceAudience.Public
|
||||
public final class GetUserPermissionsRequest {
|
||||
private String userName;
|
||||
private String namespace;
|
||||
private TableName tableName;
|
||||
private byte[] family;
|
||||
private byte[] qualifier;
|
||||
|
||||
private GetUserPermissionsRequest(String userName, String namespace, TableName tableName,
|
||||
byte[] family, byte[] qualifier) {
|
||||
this.userName = userName;
|
||||
this.namespace = namespace;
|
||||
this.tableName = tableName;
|
||||
this.family = family;
|
||||
this.qualifier = qualifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a get global permission request
|
||||
* @return a get global permission request builder
|
||||
*/
|
||||
public static Builder newBuilder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a get namespace permission request
|
||||
* @param namespace the specific namespace
|
||||
* @return a get namespace permission request builder
|
||||
*/
|
||||
public static Builder newBuilder(String namespace) {
|
||||
return new Builder(namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a get table permission request
|
||||
* @param tableName the specific table name
|
||||
* @return a get table permission request builder
|
||||
*/
|
||||
public static Builder newBuilder(TableName tableName) {
|
||||
return new Builder(tableName);
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public TableName getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public byte[] getFamily() {
|
||||
return family;
|
||||
}
|
||||
|
||||
public byte[] getQualifier() {
|
||||
return qualifier;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String userName;
|
||||
private String namespace;
|
||||
private TableName tableName;
|
||||
private byte[] family;
|
||||
private byte[] qualifier;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
private Builder(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
private Builder(TableName tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* user name could be null if need all global/namespace/table permissions
|
||||
*/
|
||||
public Builder withUserName(String userName) {
|
||||
this.userName = userName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withFamily(byte[] family) {
|
||||
Objects.requireNonNull(tableName, "The tableName can't be NULL");
|
||||
this.family = family;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withQualifier(byte[] qualifier) {
|
||||
Objects.requireNonNull(tableName, "The tableName can't be NULL");
|
||||
// Objects.requireNonNull(family, "The family can't be NULL");
|
||||
this.qualifier = qualifier;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GetUserPermissionsRequest build() {
|
||||
return new GetUserPermissionsRequest(userName, namespace, tableName, family, qualifier);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,9 @@ 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.GetUserPermissionsResponse;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantRequest;
|
||||
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;
|
||||
|
||||
|
@ -280,4 +282,40 @@ public class ShadedAccessControlUtil {
|
|||
public static RevokeRequest buildRevokeRequest(UserPermission userPermission) {
|
||||
return RevokeRequest.newBuilder().setUserPermission(toUserPermission(userPermission)).build();
|
||||
}
|
||||
|
||||
public static AccessControlProtos.GetUserPermissionsRequest
|
||||
buildGetUserPermissionsRequest(GetUserPermissionsRequest request) {
|
||||
AccessControlProtos.GetUserPermissionsRequest.Builder builder =
|
||||
AccessControlProtos.GetUserPermissionsRequest.newBuilder();
|
||||
if (request.getUserName() != null && !request.getUserName().isEmpty()) {
|
||||
builder.setUserName(ByteString.copyFromUtf8(request.getUserName()));
|
||||
}
|
||||
if (request.getNamespace() != null && !request.getNamespace().isEmpty()) {
|
||||
builder.setNamespaceName(ByteString.copyFromUtf8(request.getNamespace()));
|
||||
builder.setType(Type.Namespace);
|
||||
}
|
||||
if (request.getTableName() != null) {
|
||||
builder.setTableName(toProtoTableName(request.getTableName()));
|
||||
builder.setType(Type.Table);
|
||||
}
|
||||
if (!builder.hasType()) {
|
||||
builder.setType(Type.Global);
|
||||
}
|
||||
if (request.getFamily() != null && request.getFamily().length > 0) {
|
||||
builder.setColumnFamily(ByteString.copyFrom(request.getFamily()));
|
||||
}
|
||||
if (request.getQualifier() != null && request.getQualifier().length > 0) {
|
||||
builder.setColumnQualifier(ByteString.copyFrom(request.getQualifier()));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static GetUserPermissionsResponse
|
||||
buildGetUserPermissionsResponse(final List<UserPermission> permissions) {
|
||||
GetUserPermissionsResponse.Builder builder = GetUserPermissionsResponse.newBuilder();
|
||||
for (UserPermission perm : permissions) {
|
||||
builder.addUserPermission(toUserPermission(perm));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,6 +103,9 @@ message GetUserPermissionsRequest {
|
|||
optional Permission.Type type = 1;
|
||||
optional TableName table_name = 2;
|
||||
optional bytes namespace_name = 3;
|
||||
optional bytes column_family = 4;
|
||||
optional bytes column_qualifier = 5;
|
||||
optional bytes user_name = 6;
|
||||
}
|
||||
|
||||
message GetUserPermissionsResponse {
|
||||
|
|
|
@ -1027,6 +1027,8 @@ service MasterService {
|
|||
rpc Grant(GrantRequest) returns (GrantResponse);
|
||||
|
||||
rpc Revoke(RevokeRequest) returns (RevokeResponse);
|
||||
|
||||
rpc GetUserPermissions (GetUserPermissionsRequest) returns (GetUserPermissionsResponse);
|
||||
}
|
||||
|
||||
// HBCK Service definitions.
|
||||
|
|
|
@ -1545,4 +1545,34 @@ public interface MasterObserver {
|
|||
default void postRevoke(ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
UserPermission userPermission) throws IOException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before getting user permissions.
|
||||
* @param ctx the coprocessor instance's environment
|
||||
* @param userName the user name, null if get all user permissions
|
||||
* @param namespace the namespace, null if don't get namespace permission
|
||||
* @param tableName the table name, null if don't get table permission
|
||||
* @param family the table column family, null if don't get table family permission
|
||||
* @param qualifier the table column qualifier, null if don't get table qualifier permission
|
||||
* @throws IOException if something went wrong
|
||||
*/
|
||||
default void preGetUserPermissions(ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
String userName, String namespace, TableName tableName, byte[] family, byte[] qualifier)
|
||||
throws IOException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after getting user permissions.
|
||||
* @param ctx the coprocessor instance's environment
|
||||
* @param userName the user name, null if get all user permissions
|
||||
* @param namespace the namespace, null if don't get namespace permission
|
||||
* @param tableName the table name, null if don't get table permission
|
||||
* @param family the table column family, null if don't get table family permission
|
||||
* @param qualifier the table column qualifier, null if don't get table qualifier permission
|
||||
* @throws IOException if something went wrong
|
||||
*/
|
||||
default void postGetUserPermissions(ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
String userName, String namespace, TableName tableName, byte[] family, byte[] qualifier)
|
||||
throws IOException {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1798,4 +1798,24 @@ public class MasterCoprocessorHost
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void preGetUserPermissions(String userName, String namespace, TableName tableName,
|
||||
byte[] family, byte[] qualifier) throws IOException {
|
||||
execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() {
|
||||
@Override
|
||||
public void call(MasterObserver observer) throws IOException {
|
||||
observer.preGetUserPermissions(this, userName, namespace, tableName, family, qualifier);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void postGetUserPermissions(String userName, String namespace, TableName tableName,
|
||||
byte[] family, byte[] qualifier) throws IOException {
|
||||
execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() {
|
||||
@Override
|
||||
public void call(MasterObserver observer) throws IOException {
|
||||
observer.postGetUserPermissions(this, userName, namespace, tableName, family, qualifier);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,11 +91,13 @@ import org.apache.hadoop.hbase.regionserver.RpcSchedulerFactory;
|
|||
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.security.Superusers;
|
||||
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.Permission.Action;
|
||||
import org.apache.hadoop.hbase.security.access.ShadedAccessControlUtil;
|
||||
import org.apache.hadoop.hbase.security.access.UserPermission;
|
||||
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
||||
|
@ -118,8 +120,12 @@ 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;
|
||||
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.GrantRequest;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AccessControlProtos.GrantResponse;
|
||||
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;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CompactRegionRequest;
|
||||
|
@ -2537,6 +2543,57 @@ public class MasterRpcServices extends RSRpcServices
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetUserPermissionsResponse getUserPermissions(RpcController controller,
|
||||
GetUserPermissionsRequest request) throws ServiceException {
|
||||
try {
|
||||
final String userName = request.hasUserName() ? request.getUserName().toStringUtf8() : null;
|
||||
String namespace =
|
||||
request.hasNamespaceName() ? request.getNamespaceName().toStringUtf8() : null;
|
||||
TableName table =
|
||||
request.hasTableName() ? ProtobufUtil.toTableName(request.getTableName()) : null;
|
||||
byte[] cf = request.hasColumnFamily() ? request.getColumnFamily().toByteArray() : null;
|
||||
byte[] cq = request.hasColumnQualifier() ? request.getColumnQualifier().toByteArray() : null;
|
||||
Type permissionType = request.hasType() ? request.getType() : null;
|
||||
if (master.cpHost != null) {
|
||||
master.getMasterCoprocessorHost().preGetUserPermissions(userName, namespace, table, cf, cq);
|
||||
}
|
||||
|
||||
List<UserPermission> perms = null;
|
||||
if (permissionType == Type.Table) {
|
||||
boolean filter = (cf != null || userName != null) ? true : false;
|
||||
perms = AccessControlLists.getUserTablePermissions(master.getConfiguration(), table, cf, cq,
|
||||
userName, filter);
|
||||
} else if (permissionType == Type.Namespace) {
|
||||
perms = AccessControlLists.getUserNamespacePermissions(master.getConfiguration(), namespace,
|
||||
userName, userName != null ? true : false);
|
||||
} else {
|
||||
perms = AccessControlLists.getUserPermissions(master.getConfiguration(), null, null, null,
|
||||
userName, userName != null ? true : false);
|
||||
// Skip super users when filter user is specified
|
||||
if (userName == null) {
|
||||
// Adding superusers explicitly to the result set as AccessControlLists do not store
|
||||
// them. Also using acl as table name to be inline with the results of global admin and
|
||||
// will help in avoiding any leakage of information about being superusers.
|
||||
for (String user : Superusers.getSuperUsers()) {
|
||||
perms.add(new UserPermission(user,
|
||||
Permission.newBuilder().withActions(Action.values()).build()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (master.cpHost != null) {
|
||||
master.getMasterCoprocessorHost().postGetUserPermissions(userName, namespace, table, cf,
|
||||
cq);
|
||||
}
|
||||
AccessControlProtos.GetUserPermissionsResponse response =
|
||||
ShadedAccessControlUtil.buildGetUserPermissionsResponse(perms);
|
||||
return response;
|
||||
} catch (IOException ioe) {
|
||||
throw new ServiceException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean containMetaWals(ServerName serverName) throws IOException {
|
||||
Path logDir = new Path(master.getWALRootDir(),
|
||||
AbstractFSWALProvider.getWALDirectoryName(serverName.toString()));
|
||||
|
|
|
@ -538,8 +538,9 @@ public class AccessControlLists {
|
|||
* Returns the currently granted permissions for a given table as the specified user plus
|
||||
* associated permissions.
|
||||
*/
|
||||
static List<UserPermission> getUserTablePermissions(Configuration conf, TableName tableName,
|
||||
byte[] cf, byte[] cq, String userName, boolean hasFilterUser) throws IOException {
|
||||
public static List<UserPermission> getUserTablePermissions(Configuration conf,
|
||||
TableName tableName, byte[] cf, byte[] cq, String userName, boolean hasFilterUser)
|
||||
throws IOException {
|
||||
return getUserPermissions(conf, tableName == null ? null : tableName.getName(), cf, cq,
|
||||
userName, hasFilterUser);
|
||||
}
|
||||
|
@ -548,8 +549,8 @@ public class AccessControlLists {
|
|||
* Returns the currently granted permissions for a given namespace as the specified user plus
|
||||
* associated permissions.
|
||||
*/
|
||||
static List<UserPermission> getUserNamespacePermissions(Configuration conf, String namespace,
|
||||
String user, boolean hasFilterUser) throws IOException {
|
||||
public static List<UserPermission> getUserNamespacePermissions(Configuration conf,
|
||||
String namespace, String user, boolean hasFilterUser) throws IOException {
|
||||
return getUserPermissions(conf, Bytes.toBytes(toNamespaceEntry(namespace)), null, null, user,
|
||||
hasFilterUser);
|
||||
}
|
||||
|
@ -566,8 +567,8 @@ public class AccessControlLists {
|
|||
* @return List of UserPermissions
|
||||
* @throws IOException on failure
|
||||
*/
|
||||
static List<UserPermission> getUserPermissions(Configuration conf, byte[] entryName, byte[] cf,
|
||||
byte[] cq, String user, boolean hasFilterUser) throws IOException {
|
||||
public static List<UserPermission> getUserPermissions(Configuration conf, byte[] entryName,
|
||||
byte[] cf, byte[] cq, String user, boolean hasFilterUser) throws IOException {
|
||||
ListMultimap<String, UserPermission> allPerms =
|
||||
getPermissions(conf, entryName, null, cf, cq, user, hasFilterUser);
|
||||
List<UserPermission> perms = new ArrayList<>();
|
||||
|
|
|
@ -2136,6 +2136,10 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
|
|||
done.run(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link Admin#getUserPermissions(GetUserPermissionsRequest)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void getUserPermissions(RpcController controller,
|
||||
AccessControlProtos.GetUserPermissionsRequest request,
|
||||
|
@ -2148,77 +2152,29 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
|
|||
throw new CoprocessorException("AccessController not yet initialized");
|
||||
}
|
||||
User caller = RpcServer.getRequestUser().orElse(null);
|
||||
|
||||
List<UserPermission> perms = null;
|
||||
// Initialize username, cf and cq. Set to null if request doesn't have.
|
||||
final String userName = request.hasUserName() ? request.getUserName().toStringUtf8() : null;
|
||||
final String namespace =
|
||||
request.hasNamespaceName() ? request.getNamespaceName().toStringUtf8() : null;
|
||||
final TableName table =
|
||||
request.hasTableName() ? ProtobufUtil.toTableName(request.getTableName()) : null;
|
||||
final byte[] cf =
|
||||
request.hasColumnFamily() ? request.getColumnFamily().toByteArray() : null;
|
||||
final byte[] cq =
|
||||
request.hasColumnQualifier() ? request.getColumnQualifier().toByteArray() : null;
|
||||
|
||||
preGetUserPermissions(caller, userName, namespace, table, cf, cq);
|
||||
GetUserPermissionsRequest getUserPermissionsRequest = null;
|
||||
if (request.getType() == AccessControlProtos.Permission.Type.Table) {
|
||||
final TableName table = request.hasTableName() ?
|
||||
ProtobufUtil.toTableName(request.getTableName()) : null;
|
||||
accessChecker.requirePermission(caller, "userPermissions", table, cf, cq, userName,
|
||||
Action.ADMIN);
|
||||
perms = User.runAsLoginUser(new PrivilegedExceptionAction<List<UserPermission>>() {
|
||||
@Override
|
||||
public List<UserPermission> run() throws Exception {
|
||||
if (cf != null || userName != null) {
|
||||
// retrieve permission based on the requested parameters
|
||||
return AccessControlLists.getUserTablePermissions(regionEnv.getConfiguration(),
|
||||
table, cf, cq, userName, true);
|
||||
} else {
|
||||
return AccessControlLists.getUserTablePermissions(regionEnv.getConfiguration(),
|
||||
table, null, null, null, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
getUserPermissionsRequest = GetUserPermissionsRequest.newBuilder(table).withFamily(cf)
|
||||
.withQualifier(cq).withUserName(userName).build();
|
||||
} else if (request.getType() == AccessControlProtos.Permission.Type.Namespace) {
|
||||
final String namespace = request.getNamespaceName().toStringUtf8();
|
||||
accessChecker.requireNamespacePermission(caller, "userPermissions",
|
||||
namespace, userName, Action.ADMIN);
|
||||
perms = User.runAsLoginUser(new PrivilegedExceptionAction<List<UserPermission>>() {
|
||||
@Override
|
||||
public List<UserPermission> run() throws Exception {
|
||||
if (userName != null) {
|
||||
// retrieve permission based on the requested parameters
|
||||
return AccessControlLists.getUserNamespacePermissions(regionEnv.getConfiguration(),
|
||||
namespace, userName, true);
|
||||
} else {
|
||||
return AccessControlLists.getUserNamespacePermissions(regionEnv.getConfiguration(),
|
||||
namespace, null, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
getUserPermissionsRequest =
|
||||
GetUserPermissionsRequest.newBuilder(namespace).withUserName(userName).build();
|
||||
} else {
|
||||
accessChecker.requirePermission(caller, "userPermissions", userName, Action.ADMIN);
|
||||
perms = User.runAsLoginUser(new PrivilegedExceptionAction<List<UserPermission>>() {
|
||||
@Override
|
||||
public List<UserPermission> run() throws Exception {
|
||||
if (userName != null) {
|
||||
// retrieve permission based on the requested parameters
|
||||
return AccessControlLists.getUserPermissions(regionEnv.getConfiguration(), null,
|
||||
null, null, userName, true);
|
||||
} else {
|
||||
return AccessControlLists.getUserPermissions(regionEnv.getConfiguration(), null,
|
||||
null, null, null, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Skip super users when filter user is specified
|
||||
if (userName == null) {
|
||||
// Adding superusers explicitly to the result set as AccessControlLists do not store
|
||||
// them. Also using acl as table name to be inline with the results of global admin and
|
||||
// will help in avoiding any leakage of information about being superusers.
|
||||
for (String user : Superusers.getSuperUsers()) {
|
||||
perms.add(new UserPermission(user,
|
||||
Permission.newBuilder().withActions(Action.values()).build()));
|
||||
}
|
||||
}
|
||||
getUserPermissionsRequest =
|
||||
GetUserPermissionsRequest.newBuilder().withUserName(userName).build();
|
||||
}
|
||||
List<UserPermission> perms =
|
||||
regionEnv.getConnection().getAdmin().getUserPermissions(getUserPermissionsRequest);
|
||||
response = AccessControlUtil.buildGetUserPermissionsResponse(perms);
|
||||
} else {
|
||||
throw new CoprocessorException(AccessController.class, "This method "
|
||||
|
@ -2674,4 +2630,24 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor,
|
|||
accessChecker.performOnSuperuser(request, caller, userPermission.getUser());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preGetUserPermissions(ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
String userName, String namespace, TableName tableName, byte[] family, byte[] qualifier)
|
||||
throws IOException {
|
||||
preGetUserPermissions(getActiveUser(ctx), userName, namespace, tableName, family, qualifier);
|
||||
}
|
||||
|
||||
private void preGetUserPermissions(User caller, String userName, String namespace,
|
||||
TableName tableName, byte[] family, byte[] qualifier) throws IOException {
|
||||
if (tableName != null) {
|
||||
accessChecker.requirePermission(caller, "getUserPermissions", tableName, family, qualifier,
|
||||
userName, Action.ADMIN);
|
||||
} else if (namespace != null) {
|
||||
accessChecker.requireNamespacePermission(caller, "getUserPermissions", namespace, userName,
|
||||
Action.ADMIN);
|
||||
} else {
|
||||
accessChecker.requirePermission(caller, "getUserPermissions", userName, Action.ADMIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work for additional information regarding
|
||||
* copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License. You may obtain a
|
||||
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable
|
||||
* law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
|
||||
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hadoop.hbase.client;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
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.UserPermission;
|
||||
import org.apache.hadoop.hbase.testclassification.ClientTests;
|
||||
import org.apache.hadoop.hbase.testclassification.SmallTests;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
@Category({ ClientTests.class, SmallTests.class })
|
||||
public class TestAsyncAccessControlAdminApi extends TestAsyncAdminBase {
|
||||
|
||||
@ClassRule
|
||||
public static final HBaseClassTestRule CLASS_RULE =
|
||||
HBaseClassTestRule.forClass(TestAsyncAccessControlAdminApi.class);
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
SecureTestUtil.enableSecurity(TEST_UTIL.getConfiguration());
|
||||
TEST_UTIL.startMiniCluster(1);
|
||||
TEST_UTIL.waitTableAvailable(AccessControlLists.ACL_TABLE_NAME);
|
||||
ASYNC_CONN = ConnectionFactory.createAsyncConnection(TEST_UTIL.getConfiguration()).get();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGrant() 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
|
||||
admin.grant(userPermission, false).get();
|
||||
|
||||
// get table permissions
|
||||
List<UserPermission> userPermissions =
|
||||
admin.getUserPermissions(GetUserPermissionsRequest.newBuilder(tableName).build()).get();
|
||||
assertEquals(1, userPermissions.size());
|
||||
assertEquals(userPermission, userPermissions.get(0));
|
||||
|
||||
// get user table permissions
|
||||
userPermissions = admin.getUserPermissions(
|
||||
GetUserPermissionsRequest.newBuilder(tableName).withUserName(user).build()).get();
|
||||
assertEquals(1, userPermissions.size());
|
||||
assertEquals(userPermission, userPermissions.get(0));
|
||||
|
||||
userPermissions = admin.getUserPermissions(
|
||||
GetUserPermissionsRequest.newBuilder(tableName).withUserName("u").build()).get();
|
||||
assertEquals(0, userPermissions.size());
|
||||
}
|
||||
}
|
|
@ -144,7 +144,8 @@ public class SecureTestUtil {
|
|||
Permission.Action... actions) throws IOException {
|
||||
Permission[] perms = new Permission[actions.length];
|
||||
for (int i = 0; i < actions.length; i++) {
|
||||
perms[i] = new TablePermission(table, family, column, actions[i]);
|
||||
perms[i] = Permission.newBuilder(table).withFamily(family).withQualifier(column)
|
||||
.withActions(actions[i]).build();
|
||||
}
|
||||
|
||||
checkTablePerms(conf, table, perms);
|
||||
|
@ -878,7 +879,8 @@ public class SecureTestUtil {
|
|||
byte[] column, Permission.Action... actions) throws IOException {
|
||||
Permission[] perms = new Permission[actions.length];
|
||||
for (int i = 0; i < actions.length; i++) {
|
||||
perms[i] = new TablePermission(table, family, column, actions[i]);
|
||||
perms[i] = Permission.newBuilder(table).withFamily(family).withQualifier(column)
|
||||
.withActions(actions[i]).build();
|
||||
}
|
||||
checkTablePerms(testUtil, table, perms);
|
||||
}
|
||||
|
|
|
@ -1190,12 +1190,9 @@ public class TestAccessController extends SecureTestUtil {
|
|||
AccessTestAction getTablePermissionsAction = 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.getUserPermissions(null, protocol, TEST_TABLE);
|
||||
try (Connection conn = ConnectionFactory.createConnection(conf)) {
|
||||
conn.getAdmin()
|
||||
.getUserPermissions(GetUserPermissionsRequest.newBuilder(TEST_TABLE).build());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -1204,12 +1201,9 @@ public class TestAccessController extends SecureTestUtil {
|
|||
AccessTestAction getGlobalPermissionsAction = 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.getUserPermissions(null, protocol);
|
||||
try (Connection conn = ConnectionFactory.createConnection(conf);
|
||||
Table acl = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) {
|
||||
conn.getAdmin().getUserPermissions(GetUserPermissionsRequest.newBuilder().build());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -1679,17 +1673,8 @@ public class TestAccessController extends SecureTestUtil {
|
|||
htd.setOwner(USER_OWNER);
|
||||
createTable(TEST_UTIL, htd);
|
||||
try {
|
||||
List<UserPermission> perms;
|
||||
Table acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
|
||||
try {
|
||||
BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
|
||||
AccessControlService.BlockingInterface protocol =
|
||||
AccessControlService.newBlockingStub(service);
|
||||
perms = AccessControlUtil.getUserPermissions(null, protocol, tableName);
|
||||
} finally {
|
||||
acl.close();
|
||||
}
|
||||
|
||||
List<UserPermission> perms =
|
||||
admin.getUserPermissions(GetUserPermissionsRequest.newBuilder(tableName).build());
|
||||
UserPermission ownerperm = new UserPermission(USER_OWNER.getName(),
|
||||
Permission.newBuilder(tableName).withActions(Action.values()).build());
|
||||
assertTrue("Owner should have all permissions on table",
|
||||
|
@ -1708,16 +1693,7 @@ public class TestAccessController extends SecureTestUtil {
|
|||
grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier,
|
||||
Permission.Action.READ);
|
||||
|
||||
acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
|
||||
try {
|
||||
BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
|
||||
AccessControlService.BlockingInterface protocol =
|
||||
AccessControlService.newBlockingStub(service);
|
||||
perms = AccessControlUtil.getUserPermissions(null, protocol, tableName);
|
||||
} finally {
|
||||
acl.close();
|
||||
}
|
||||
|
||||
perms = admin.getUserPermissions(GetUserPermissionsRequest.newBuilder(tableName).build());
|
||||
UserPermission upToVerify =
|
||||
new UserPermission(userName, Permission.newBuilder(tableName).withFamily(family1)
|
||||
.withQualifier(qualifier).withActions(Permission.Action.READ).build());
|
||||
|
@ -1733,16 +1709,7 @@ public class TestAccessController extends SecureTestUtil {
|
|||
grantOnTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier,
|
||||
Permission.Action.WRITE, Permission.Action.READ);
|
||||
|
||||
acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
|
||||
try {
|
||||
BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
|
||||
AccessControlService.BlockingInterface protocol =
|
||||
AccessControlService.newBlockingStub(service);
|
||||
perms = AccessControlUtil.getUserPermissions(null, protocol, tableName);
|
||||
} finally {
|
||||
acl.close();
|
||||
}
|
||||
|
||||
perms = admin.getUserPermissions(GetUserPermissionsRequest.newBuilder(tableName).build());
|
||||
upToVerify = new UserPermission(userName,
|
||||
Permission.newBuilder(tableName).withFamily(family1).withQualifier(qualifier)
|
||||
.withActions(Permission.Action.WRITE, Permission.Action.READ).build());
|
||||
|
@ -1753,16 +1720,7 @@ public class TestAccessController extends SecureTestUtil {
|
|||
revokeFromTable(TEST_UTIL, user.getShortName(), tableName, family1, qualifier,
|
||||
Permission.Action.WRITE, Permission.Action.READ);
|
||||
|
||||
acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
|
||||
try {
|
||||
BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
|
||||
AccessControlService.BlockingInterface protocol =
|
||||
AccessControlService.newBlockingStub(service);
|
||||
perms = AccessControlUtil.getUserPermissions(null, protocol, tableName);
|
||||
} finally {
|
||||
acl.close();
|
||||
}
|
||||
|
||||
perms = admin.getUserPermissions(GetUserPermissionsRequest.newBuilder(tableName).build());
|
||||
assertFalse("User should not be granted permission: " + upToVerify.toString(),
|
||||
hasFoundUserPermission(upToVerify, perms));
|
||||
|
||||
|
@ -1773,16 +1731,7 @@ public class TestAccessController extends SecureTestUtil {
|
|||
htd.setOwner(newOwner);
|
||||
admin.modifyTable(tableName, htd);
|
||||
|
||||
acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
|
||||
try {
|
||||
BlockingRpcChannel service = acl.coprocessorService(tableName.getName());
|
||||
AccessControlService.BlockingInterface protocol =
|
||||
AccessControlService.newBlockingStub(service);
|
||||
perms = AccessControlUtil.getUserPermissions(null, protocol, tableName);
|
||||
} finally {
|
||||
acl.close();
|
||||
}
|
||||
|
||||
perms = admin.getUserPermissions(GetUserPermissionsRequest.newBuilder(tableName).build());
|
||||
UserPermission newOwnerperm = new UserPermission(newOwner.getName(),
|
||||
Permission.newBuilder(tableName).withActions(Action.values()).build());
|
||||
assertTrue("New owner should have all permissions on table",
|
||||
|
@ -1795,16 +1744,8 @@ public class TestAccessController extends SecureTestUtil {
|
|||
|
||||
@Test
|
||||
public void testGlobalPermissionList() throws Exception {
|
||||
List<UserPermission> perms;
|
||||
Table acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME);
|
||||
try {
|
||||
BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
|
||||
AccessControlService.BlockingInterface protocol =
|
||||
AccessControlService.newBlockingStub(service);
|
||||
perms = AccessControlUtil.getUserPermissions(null, protocol);
|
||||
} finally {
|
||||
acl.close();
|
||||
}
|
||||
List<UserPermission> perms = systemUserConnection.getAdmin()
|
||||
.getUserPermissions(GetUserPermissionsRequest.newBuilder().build());
|
||||
|
||||
Collection<String> superUsers = Superusers.getSuperUsers();
|
||||
List<UserPermission> adminPerms = new ArrayList<>(superUsers.size() + 1);
|
||||
|
@ -1900,9 +1841,12 @@ public class TestAccessController extends SecureTestUtil {
|
|||
AccessTestAction multiQualifierRead = new AccessTestAction() {
|
||||
@Override
|
||||
public Void run() throws Exception {
|
||||
checkTablePerms(TEST_UTIL, TEST_TABLE, new Permission[] {
|
||||
new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_Q1, Permission.Action.READ),
|
||||
new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_Q2, Permission.Action.READ), });
|
||||
checkTablePerms(TEST_UTIL, TEST_TABLE,
|
||||
new Permission[] {
|
||||
Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY).withQualifier(TEST_Q1)
|
||||
.withActions(Permission.Action.READ).build(),
|
||||
Permission.newBuilder(TEST_TABLE).withFamily(TEST_FAMILY).withQualifier(TEST_Q2)
|
||||
.withActions(Permission.Action.READ).build(), });
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
@ -1912,7 +1856,7 @@ public class TestAccessController extends SecureTestUtil {
|
|||
public Void run() throws Exception {
|
||||
checkTablePerms(TEST_UTIL, TEST_TABLE, new Permission[] {
|
||||
new Permission(Permission.Action.READ),
|
||||
new TablePermission(TEST_TABLE, null, (byte[]) null, Permission.Action.READ), });
|
||||
Permission.newBuilder(TEST_TABLE).withActions(Permission.Action.READ).build() });
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
@ -3527,12 +3471,9 @@ public class TestAccessController extends SecureTestUtil {
|
|||
AccessTestAction globalUserPermissionAction = 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.getUserPermissions(null, protocol, "dummy");
|
||||
try (Connection conn = ConnectionFactory.createConnection(conf)) {
|
||||
conn.getAdmin().getUserPermissions(
|
||||
GetUserPermissionsRequest.newBuilder().withUserName("dummy").build());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -3566,12 +3507,9 @@ public class TestAccessController extends SecureTestUtil {
|
|||
AccessTestAction namespaceUserPermissionAction = 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.getUserPermissions(null, protocol, Bytes.toBytes(namespace1), "dummy");
|
||||
try (Connection conn = ConnectionFactory.createConnection(conf)) {
|
||||
conn.getAdmin().getUserPermissions(
|
||||
GetUserPermissionsRequest.newBuilder(namespace1).withUserName("dummy").build());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -3610,13 +3548,9 @@ public class TestAccessController extends SecureTestUtil {
|
|||
AccessTestAction tableUserPermissionAction = 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.getUserPermissions(null, protocol, TEST_TABLE, TEST_FAMILY,
|
||||
TEST_QUALIFIER, "dummy");
|
||||
try (Connection conn = ConnectionFactory.createConnection(conf)) {
|
||||
conn.getAdmin().getUserPermissions(GetUserPermissionsRequest.newBuilder(TEST_TABLE)
|
||||
.withFamily(TEST_FAMILY).withQualifier(TEST_QUALIFIER).withUserName("dummy").build());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -405,12 +405,9 @@ public class TestNamespaceCommands extends SecureTestUtil {
|
|||
AccessTestAction getPermissionsAction = 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.getUserPermissions(null, protocol, Bytes.toBytes(TEST_NAMESPACE));
|
||||
try (Connection connection = ConnectionFactory.createConnection(conf)) {
|
||||
connection.getAdmin()
|
||||
.getUserPermissions(GetUserPermissionsRequest.newBuilder(TEST_NAMESPACE).build());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -420,7 +417,8 @@ public class TestNamespaceCommands extends SecureTestUtil {
|
|||
@Override
|
||||
public Object run() throws Exception {
|
||||
ACCESS_CONTROLLER.preGrant(ObserverContextImpl.createAndPrepare(CP_ENV),
|
||||
new UserPermission(testUser, new NamespacePermission(TEST_NAMESPACE, Action.WRITE)),
|
||||
new UserPermission(testUser,
|
||||
Permission.newBuilder(TEST_NAMESPACE).withActions(Action.WRITE).build()),
|
||||
false);
|
||||
return null;
|
||||
}
|
||||
|
@ -429,7 +427,8 @@ public class TestNamespaceCommands extends SecureTestUtil {
|
|||
@Override
|
||||
public Object run() throws Exception {
|
||||
ACCESS_CONTROLLER.preRevoke(ObserverContextImpl.createAndPrepare(CP_ENV),
|
||||
new UserPermission(testUser, new NamespacePermission(TEST_NAMESPACE, Action.WRITE)));
|
||||
new UserPermission(testUser,
|
||||
Permission.newBuilder(TEST_NAMESPACE).withActions(Action.WRITE).build()));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -58,6 +58,7 @@ import org.apache.hadoop.hbase.quotas.QuotaSettings;
|
|||
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.security.access.GetUserPermissionsRequest;
|
||||
import org.apache.hadoop.hbase.security.access.UserPermission;
|
||||
import org.apache.hadoop.hbase.snapshot.RestoreSnapshotException;
|
||||
import org.apache.hadoop.hbase.thrift2.ThriftUtilities;
|
||||
|
@ -1349,4 +1350,10 @@ public class ThriftAdmin implements Admin {
|
|||
public void revoke(UserPermission userPermission) {
|
||||
throw new NotImplementedException("revoke not supported in ThriftAdmin");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserPermission>
|
||||
getUserPermissions(GetUserPermissionsRequest getUserPermissionsRequest) {
|
||||
throw new NotImplementedException("getUserPermissions not supported in ThriftAdmin");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue