HBASE-12161 Add support for grant/revoke on namespaces in AccessControlClient (Srikanth Srungarapu)
This commit is contained in:
parent
5c92bded9d
commit
49056295ef
|
@ -20,40 +20,26 @@ package org.apache.hadoop.hbase.security.access;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
|
||||||
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.hbase.HBaseIOException;
|
|
||||||
import org.apache.hadoop.hbase.HConstants;
|
import org.apache.hadoop.hbase.HConstants;
|
||||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||||
import org.apache.hadoop.hbase.MasterNotRunningException;
|
import org.apache.hadoop.hbase.MasterNotRunningException;
|
||||||
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
||||||
import org.apache.hadoop.hbase.TableName;
|
import org.apache.hadoop.hbase.TableName;
|
||||||
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
|
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
|
||||||
|
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
||||||
|
import org.apache.hadoop.hbase.classification.InterfaceStability;
|
||||||
import org.apache.hadoop.hbase.client.Admin;
|
import org.apache.hadoop.hbase.client.Admin;
|
||||||
import org.apache.hadoop.hbase.client.HBaseAdmin;
|
import org.apache.hadoop.hbase.client.HBaseAdmin;
|
||||||
import org.apache.hadoop.hbase.client.HTable;
|
import org.apache.hadoop.hbase.client.HTable;
|
||||||
import org.apache.hadoop.hbase.client.Table;
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
import org.apache.hadoop.hbase.client.coprocessor.Batch;
|
|
||||||
import org.apache.hadoop.hbase.ipc.BlockingRpcCallback;
|
|
||||||
import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
|
import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
|
||||||
import org.apache.hadoop.hbase.ipc.ServerRpcController;
|
|
||||||
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
|
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
|
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.AccessControlService.BlockingInterface;
|
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService.BlockingInterface;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GrantRequest;
|
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GrantResponse;
|
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeRequest;
|
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeResponse;
|
|
||||||
import org.apache.hadoop.hbase.util.ByteStringer;
|
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.security.authorize.AccessControlList;
|
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility client for doing access control admin operations.
|
* Utility client for doing access control admin operations.
|
||||||
|
@ -61,6 +47,22 @@ import com.google.protobuf.ByteString;
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Public
|
||||||
@InterfaceStability.Evolving
|
@InterfaceStability.Evolving
|
||||||
public class AccessControlClient {
|
public class AccessControlClient {
|
||||||
|
|
||||||
|
private static HTable getAclTable(Configuration conf) throws IOException {
|
||||||
|
TableName aclTableName =
|
||||||
|
TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR,
|
||||||
|
AccessControlConstants.OP_ATTRIBUTE_ACL);
|
||||||
|
return new HTable(conf, aclTableName.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BlockingInterface getAccessControlServiceStub(HTable ht)
|
||||||
|
throws IOException {
|
||||||
|
CoprocessorRpcChannel service = ht.coprocessorService(HConstants.EMPTY_START_ROW);
|
||||||
|
BlockingInterface protocol =
|
||||||
|
AccessControlProtos.AccessControlService.newBlockingStub(service);
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grants permission on the specified table for the specified user
|
* Grants permission on the specified table for the specified user
|
||||||
* @param conf
|
* @param conf
|
||||||
|
@ -69,56 +71,37 @@ public class AccessControlClient {
|
||||||
* @param family
|
* @param family
|
||||||
* @param qual
|
* @param qual
|
||||||
* @param actions
|
* @param actions
|
||||||
* @return GrantResponse
|
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public static GrantResponse grant(Configuration conf, final TableName tableName,
|
public static void grant(Configuration conf, final TableName tableName,
|
||||||
final String userName, final byte[] family, final byte[] qual,
|
final String userName, final byte[] family, final byte[] qual,
|
||||||
final AccessControlProtos.Permission.Action... actions) throws Throwable {
|
final Permission.Action... actions) throws Throwable {
|
||||||
Table ht = null;
|
HTable ht = null;
|
||||||
try {
|
try {
|
||||||
TableName aclTableName =
|
ht = getAclTable(conf);
|
||||||
TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR, "acl");
|
ProtobufUtil.grant(getAccessControlServiceStub(ht), userName, tableName, family, qual,
|
||||||
ht = new HTable(conf, aclTableName);
|
actions);
|
||||||
Batch.Call<AccessControlService, GrantResponse> callable =
|
} finally {
|
||||||
new Batch.Call<AccessControlService, GrantResponse>() {
|
if (ht != null) {
|
||||||
ServerRpcController controller = new ServerRpcController();
|
ht.close();
|
||||||
BlockingRpcCallback<GrantResponse> rpcCallback =
|
}
|
||||||
new BlockingRpcCallback<GrantResponse>();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public GrantResponse call(AccessControlService service) throws IOException {
|
* Grants permission on the specified namespace for the specified user.
|
||||||
GrantRequest.Builder builder = GrantRequest.newBuilder();
|
* @param conf
|
||||||
AccessControlProtos.Permission.Builder ret =
|
* @param namespace
|
||||||
AccessControlProtos.Permission.newBuilder();
|
* @param userName
|
||||||
AccessControlProtos.TablePermission.Builder permissionBuilder =
|
* @param actions
|
||||||
AccessControlProtos.TablePermission
|
* @throws Throwable
|
||||||
.newBuilder();
|
*/
|
||||||
for (AccessControlProtos.Permission.Action a : actions) {
|
public static void grant(Configuration conf, final String namespace,
|
||||||
permissionBuilder.addAction(a);
|
final String userName, final Permission.Action... actions) throws Throwable {
|
||||||
}
|
HTable ht = null;
|
||||||
permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName));
|
try {
|
||||||
|
ht = getAclTable(conf);
|
||||||
if (family != null) {
|
ProtobufUtil.grant(getAccessControlServiceStub(ht), userName, namespace, actions);
|
||||||
permissionBuilder.setFamily(ByteStringer.wrap(family));
|
|
||||||
}
|
|
||||||
if (qual != null) {
|
|
||||||
permissionBuilder.setQualifier(ByteStringer.wrap(qual));
|
|
||||||
}
|
|
||||||
ret.setType(AccessControlProtos.Permission.Type.Table).setTablePermission(
|
|
||||||
permissionBuilder);
|
|
||||||
builder.setUserPermission(AccessControlProtos.UserPermission.newBuilder()
|
|
||||||
.setUser(ByteString.copyFromUtf8(userName)).setPermission(ret));
|
|
||||||
service.grant(controller, builder.build(), rpcCallback);
|
|
||||||
return rpcCallback.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Map<byte[], GrantResponse> result = ht.coprocessorService(AccessControlService.class,
|
|
||||||
HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, callable);
|
|
||||||
return result.values().iterator().next(); // There will be exactly one
|
|
||||||
// region for labels
|
|
||||||
// table and so one entry in
|
|
||||||
// result Map.
|
|
||||||
} finally {
|
} finally {
|
||||||
if (ht != null) {
|
if (ht != null) {
|
||||||
ht.close();
|
ht.close();
|
||||||
|
@ -144,61 +127,42 @@ public class AccessControlClient {
|
||||||
/**
|
/**
|
||||||
* Revokes the permission on the table
|
* Revokes the permission on the table
|
||||||
* @param conf
|
* @param conf
|
||||||
* @param username
|
|
||||||
* @param tableName
|
* @param tableName
|
||||||
|
* @param username
|
||||||
* @param family
|
* @param family
|
||||||
* @param qualifier
|
* @param qualifier
|
||||||
* @param actions
|
* @param actions
|
||||||
* @return RevokeResponse
|
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public static RevokeResponse revoke(Configuration conf, final String username,
|
public static void revoke(Configuration conf, final TableName tableName,
|
||||||
final TableName tableName, final byte[] family, final byte[] qualifier,
|
final String username, final byte[] family, final byte[] qualifier,
|
||||||
final AccessControlProtos.Permission.Action... actions) throws Throwable {
|
final Permission.Action... actions) throws Throwable {
|
||||||
Table ht = null;
|
HTable ht = null;
|
||||||
try {
|
try {
|
||||||
TableName aclTableName = TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR,
|
ht = getAclTable(conf);
|
||||||
"acl");
|
ProtobufUtil.revoke(getAccessControlServiceStub(ht), username, tableName, family, qualifier,
|
||||||
ht = new HTable(conf, aclTableName);
|
actions);
|
||||||
Batch.Call<AccessControlService, AccessControlProtos.RevokeResponse> callable =
|
} finally {
|
||||||
new Batch.Call<AccessControlService, AccessControlProtos.RevokeResponse>() {
|
if (ht != null) {
|
||||||
ServerRpcController controller = new ServerRpcController();
|
ht.close();
|
||||||
BlockingRpcCallback<AccessControlProtos.RevokeResponse> rpcCallback =
|
}
|
||||||
new BlockingRpcCallback<AccessControlProtos.RevokeResponse>();
|
}
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public RevokeResponse call(AccessControlService service) throws IOException {
|
|
||||||
AccessControlProtos.Permission.Builder ret =
|
|
||||||
AccessControlProtos.Permission.newBuilder();
|
|
||||||
AccessControlProtos.TablePermission.Builder permissionBuilder =
|
|
||||||
AccessControlProtos.TablePermission.newBuilder();
|
|
||||||
for (AccessControlProtos.Permission.Action a : actions) {
|
|
||||||
permissionBuilder.addAction(a);
|
|
||||||
}
|
|
||||||
if (tableName != null) {
|
|
||||||
permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName));
|
|
||||||
}
|
|
||||||
if (family != null) {
|
|
||||||
permissionBuilder.setFamily(ByteStringer.wrap(family));
|
|
||||||
}
|
|
||||||
if (qualifier != null) {
|
|
||||||
permissionBuilder.setQualifier(ByteStringer.wrap(qualifier));
|
|
||||||
}
|
|
||||||
ret.setType(AccessControlProtos.Permission.Type.Table).setTablePermission(
|
|
||||||
permissionBuilder);
|
|
||||||
RevokeRequest builder = AccessControlProtos.RevokeRequest
|
|
||||||
.newBuilder()
|
|
||||||
.setUserPermission(
|
|
||||||
AccessControlProtos.UserPermission.newBuilder()
|
|
||||||
.setUser(ByteString.copyFromUtf8(username)).setPermission(ret)).build();
|
|
||||||
service.revoke(controller, builder, rpcCallback);
|
|
||||||
return rpcCallback.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Map<byte[], RevokeResponse> result = ht.coprocessorService(AccessControlService.class,
|
|
||||||
HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, callable);
|
|
||||||
return result.values().iterator().next();
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revokes the permission on the table for the specified user.
|
||||||
|
* @param conf
|
||||||
|
* @param namespace
|
||||||
|
* @param userName
|
||||||
|
* @param actions
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public static void revoke(Configuration conf, final String namespace,
|
||||||
|
final String userName, final Permission.Action... actions) throws Throwable {
|
||||||
|
HTable ht = null;
|
||||||
|
try {
|
||||||
|
ht = getAclTable(conf);
|
||||||
|
ProtobufUtil.revoke(getAccessControlServiceStub(ht), userName, namespace, actions);
|
||||||
} finally {
|
} finally {
|
||||||
if (ht != null) {
|
if (ht != null) {
|
||||||
ht.close();
|
ht.close();
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.apache.hadoop.hbase.HColumnDescriptor;
|
||||||
import org.apache.hadoop.hbase.HRegionLocation;
|
import org.apache.hadoop.hbase.HRegionLocation;
|
||||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||||
import org.apache.hadoop.hbase.IntegrationTestingUtility;
|
import org.apache.hadoop.hbase.IntegrationTestingUtility;
|
||||||
import org.apache.hadoop.hbase.testclassification.IntegrationTests;
|
|
||||||
import org.apache.hadoop.hbase.TableName;
|
import org.apache.hadoop.hbase.TableName;
|
||||||
import org.apache.hadoop.hbase.chaos.factories.MonkeyFactory;
|
import org.apache.hadoop.hbase.chaos.factories.MonkeyFactory;
|
||||||
import org.apache.hadoop.hbase.client.Admin;
|
import org.apache.hadoop.hbase.client.Admin;
|
||||||
|
@ -52,13 +51,14 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
|
||||||
import org.apache.hadoop.hbase.io.hfile.HFile;
|
import org.apache.hadoop.hbase.io.hfile.HFile;
|
||||||
import org.apache.hadoop.hbase.mapreduce.Import;
|
import org.apache.hadoop.hbase.mapreduce.Import;
|
||||||
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
|
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
|
|
||||||
import org.apache.hadoop.hbase.security.User;
|
import org.apache.hadoop.hbase.security.User;
|
||||||
import org.apache.hadoop.hbase.security.access.AccessControlClient;
|
import org.apache.hadoop.hbase.security.access.AccessControlClient;
|
||||||
|
import org.apache.hadoop.hbase.security.access.Permission;
|
||||||
import org.apache.hadoop.hbase.security.visibility.Authorizations;
|
import org.apache.hadoop.hbase.security.visibility.Authorizations;
|
||||||
import org.apache.hadoop.hbase.security.visibility.CellVisibility;
|
import org.apache.hadoop.hbase.security.visibility.CellVisibility;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
||||||
|
import org.apache.hadoop.hbase.testclassification.IntegrationTests;
|
||||||
import org.apache.hadoop.hbase.util.AbstractHBaseTool;
|
import org.apache.hadoop.hbase.util.AbstractHBaseTool;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.apache.hadoop.io.BytesWritable;
|
import org.apache.hadoop.io.BytesWritable;
|
||||||
|
@ -154,7 +154,7 @@ public class IntegrationTestBigLinkedListWithVisibility extends IntegrationTestB
|
||||||
admin.createTable(htd);
|
admin.createTable(htd);
|
||||||
if (acl) {
|
if (acl) {
|
||||||
LOG.info("Granting permissions for user " + USER.getShortName());
|
LOG.info("Granting permissions for user " + USER.getShortName());
|
||||||
AccessControlProtos.Permission.Action[] actions = { AccessControlProtos.Permission.Action.READ };
|
Permission.Action[] actions = { Permission.Action.READ };
|
||||||
try {
|
try {
|
||||||
AccessControlClient.grant(getConf(), tableName, USER.getShortName(), null, null,
|
AccessControlClient.grant(getConf(), tableName, USER.getShortName(), null, null,
|
||||||
actions);
|
actions);
|
||||||
|
|
|
@ -390,6 +390,48 @@ public class SecureTestUtil {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grant permissions on a namespace to the given user using AccessControl Client.
|
||||||
|
* Will wait until all active AccessController instances have updated their permissions caches
|
||||||
|
* or will throw an exception upon timeout (10 seconds).
|
||||||
|
*/
|
||||||
|
public static void grantOnNamespaceUsingAccessControlClient(final HBaseTestingUtility util,
|
||||||
|
final Configuration conf, final String user, final String namespace,
|
||||||
|
final Permission.Action... actions) throws Exception {
|
||||||
|
SecureTestUtil.updateACLs(util, new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
try {
|
||||||
|
AccessControlClient.grant(conf, namespace, user, actions);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revoke permissions on a namespace from the given user using AccessControl Client.
|
||||||
|
* Will wait until all active AccessController instances have updated their permissions caches
|
||||||
|
* or will throw an exception upon timeout (10 seconds).
|
||||||
|
*/
|
||||||
|
public static void revokeFromNamespaceUsingAccessControlClient(final HBaseTestingUtility util,
|
||||||
|
final Configuration conf, final String user, final String namespace,
|
||||||
|
final Permission.Action... actions) throws Exception {
|
||||||
|
SecureTestUtil.updateACLs(util, new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
try {
|
||||||
|
AccessControlClient.revoke(conf, namespace, user, actions);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revoke permissions on a namespace from the given user. Will wait until all active
|
* Revoke permissions on a namespace from the given user. Will wait until all active
|
||||||
* AccessController instances have updated their permissions caches or will
|
* AccessController instances have updated their permissions caches or will
|
||||||
|
@ -439,6 +481,27 @@ public class SecureTestUtil {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grant permissions on a table to the given user using AccessControlClient. Will wait until all
|
||||||
|
* active AccessController instances have updated their permissions caches or will
|
||||||
|
* throw an exception upon timeout (10 seconds).
|
||||||
|
*/
|
||||||
|
public static void grantOnTableUsingAccessControlClient(final HBaseTestingUtility util,
|
||||||
|
final Configuration conf, final String user, final TableName table, final byte[] family,
|
||||||
|
final byte[] qualifier, final Permission.Action... actions) throws Exception {
|
||||||
|
SecureTestUtil.updateACLs(util, new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
try {
|
||||||
|
AccessControlClient.grant(conf, table, user, family, qualifier, actions);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revoke permissions on a table from the given user. Will wait until all active
|
* Revoke permissions on a table from the given user. Will wait until all active
|
||||||
* AccessController instances have updated their permissions caches or will
|
* AccessController instances have updated their permissions caches or will
|
||||||
|
@ -463,4 +526,25 @@ public class SecureTestUtil {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revoke permissions on a table from the given user using AccessControlClient. Will wait until
|
||||||
|
* all active AccessController instances have updated their permissions caches or will
|
||||||
|
* throw an exception upon timeout (10 seconds).
|
||||||
|
*/
|
||||||
|
public static void revokeFromTableUsingAccessControlClient(final HBaseTestingUtility util,
|
||||||
|
final Configuration conf, final String user, final TableName table, final byte[] family,
|
||||||
|
final byte[] qualifier, final Permission.Action... actions) throws Exception {
|
||||||
|
SecureTestUtil.updateACLs(util, new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
try {
|
||||||
|
AccessControlClient.revoke(conf, table, user, family, qualifier, actions);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,6 @@ import org.apache.hadoop.hbase.HTableDescriptor;
|
||||||
import org.apache.hadoop.hbase.KeyValue;
|
import org.apache.hadoop.hbase.KeyValue;
|
||||||
import org.apache.hadoop.hbase.MiniHBaseCluster;
|
import org.apache.hadoop.hbase.MiniHBaseCluster;
|
||||||
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
||||||
import org.apache.hadoop.hbase.NamespaceDescriptor.Builder;
|
|
||||||
import org.apache.hadoop.hbase.ServerName;
|
import org.apache.hadoop.hbase.ServerName;
|
||||||
import org.apache.hadoop.hbase.TableName;
|
import org.apache.hadoop.hbase.TableName;
|
||||||
import org.apache.hadoop.hbase.TableNotFoundException;
|
import org.apache.hadoop.hbase.TableNotFoundException;
|
||||||
|
@ -2126,6 +2125,89 @@ public class TestAccessController extends SecureTestUtil {
|
||||||
verifyAllowed(getAction, USER_NONE);
|
verifyAllowed(getAction, USER_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccessControlClientGrantRevoke() throws Exception {
|
||||||
|
// Create user for testing, who has no READ privileges by default.
|
||||||
|
User testGrantRevoke = User.createUserForTesting(conf, "testGrantRevoke", new String[0]);
|
||||||
|
AccessTestAction getAction = new AccessTestAction() {
|
||||||
|
@Override
|
||||||
|
public Object run() throws Exception {
|
||||||
|
HTable t = new HTable(conf, TEST_TABLE.getTableName());
|
||||||
|
try {
|
||||||
|
return t.get(new Get(TEST_ROW));
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
verifyDenied(getAction, testGrantRevoke);
|
||||||
|
|
||||||
|
// Grant table READ permissions to testGrantRevoke.
|
||||||
|
try {
|
||||||
|
grantOnTableUsingAccessControlClient(TEST_UTIL, conf, testGrantRevoke.getShortName(),
|
||||||
|
TEST_TABLE.getTableName(), null, null, Permission.Action.READ);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
LOG.error("error during call of AccessControlClient.grant. " + e.getStackTrace());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now testGrantRevoke should be able to read also
|
||||||
|
verifyAllowed(getAction, testGrantRevoke);
|
||||||
|
|
||||||
|
// Revoke table READ permission to testGrantRevoke.
|
||||||
|
try {
|
||||||
|
revokeFromTableUsingAccessControlClient(TEST_UTIL, conf, testGrantRevoke.getShortName(),
|
||||||
|
TEST_TABLE.getTableName(), null, null, Permission.Action.READ);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
LOG.error("error during call of AccessControlClient.revoke " + e.getStackTrace());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now testGrantRevoke shouldn't be able read
|
||||||
|
verifyDenied(getAction, testGrantRevoke);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccessControlClientGrantRevokeOnNamespace() throws Exception {
|
||||||
|
// Create user for testing, who has no READ privileges by default.
|
||||||
|
User testNS = User.createUserForTesting(conf, "testNS", new String[0]);
|
||||||
|
AccessTestAction getAction = new AccessTestAction() {
|
||||||
|
@Override
|
||||||
|
public Object run() throws Exception {
|
||||||
|
HTable t = new HTable(conf, TEST_TABLE.getTableName());
|
||||||
|
try {
|
||||||
|
return t.get(new Get(TEST_ROW));
|
||||||
|
} finally {
|
||||||
|
t.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
verifyDenied(getAction, testNS);
|
||||||
|
|
||||||
|
// Grant namespace READ to testNS, this should supersede any table permissions
|
||||||
|
try {
|
||||||
|
grantOnNamespaceUsingAccessControlClient(TEST_UTIL, conf, testNS.getShortName(),
|
||||||
|
TEST_TABLE.getTableName().getNamespaceAsString(), Permission.Action.READ);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
LOG.error("error during call of AccessControlClient.grant. " + e.getStackTrace());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now testNS should be able to read also
|
||||||
|
verifyAllowed(getAction, testNS);
|
||||||
|
|
||||||
|
// Revoke namespace READ to testNS, this should supersede any table permissions
|
||||||
|
try {
|
||||||
|
revokeFromNamespaceUsingAccessControlClient(TEST_UTIL, conf, testNS.getShortName(),
|
||||||
|
TEST_TABLE.getTableName().getNamespaceAsString(), Permission.Action.READ);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
LOG.error("error during call of AccessControlClient.revoke " + e.getStackTrace());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now testNS shouldn't be able read
|
||||||
|
verifyDenied(getAction, testNS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class PingCoprocessor extends PingService implements Coprocessor,
|
public static class PingCoprocessor extends PingService implements Coprocessor,
|
||||||
CoprocessorService {
|
CoprocessorService {
|
||||||
|
|
||||||
|
|
|
@ -47,11 +47,11 @@ import org.apache.hadoop.hbase.io.compress.Compression;
|
||||||
import org.apache.hadoop.hbase.io.crypto.Cipher;
|
import org.apache.hadoop.hbase.io.crypto.Cipher;
|
||||||
import org.apache.hadoop.hbase.io.crypto.Encryption;
|
import org.apache.hadoop.hbase.io.crypto.Encryption;
|
||||||
import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
|
import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
|
|
||||||
import org.apache.hadoop.hbase.regionserver.BloomType;
|
import org.apache.hadoop.hbase.regionserver.BloomType;
|
||||||
import org.apache.hadoop.hbase.security.EncryptionUtil;
|
import org.apache.hadoop.hbase.security.EncryptionUtil;
|
||||||
import org.apache.hadoop.hbase.security.User;
|
import org.apache.hadoop.hbase.security.User;
|
||||||
import org.apache.hadoop.hbase.security.access.AccessControlClient;
|
import org.apache.hadoop.hbase.security.access.AccessControlClient;
|
||||||
|
import org.apache.hadoop.hbase.security.access.Permission;
|
||||||
import org.apache.hadoop.hbase.util.test.LoadTestDataGenerator;
|
import org.apache.hadoop.hbase.util.test.LoadTestDataGenerator;
|
||||||
import org.apache.hadoop.hbase.util.test.LoadTestDataGeneratorWithACL;
|
import org.apache.hadoop.hbase.util.test.LoadTestDataGeneratorWithACL;
|
||||||
import org.apache.hadoop.security.SecurityUtil;
|
import org.apache.hadoop.security.SecurityUtil;
|
||||||
|
@ -572,9 +572,9 @@ public class LoadTestTool extends AbstractHBaseTool {
|
||||||
|
|
||||||
if (userOwner != null) {
|
if (userOwner != null) {
|
||||||
LOG.info("Granting permissions for user " + userOwner.getShortName());
|
LOG.info("Granting permissions for user " + userOwner.getShortName());
|
||||||
AccessControlProtos.Permission.Action[] actions = {
|
Permission.Action[] actions = {
|
||||||
AccessControlProtos.Permission.Action.ADMIN, AccessControlProtos.Permission.Action.CREATE,
|
Permission.Action.ADMIN, Permission.Action.CREATE,
|
||||||
AccessControlProtos.Permission.Action.READ, AccessControlProtos.Permission.Action.WRITE };
|
Permission.Action.READ, Permission.Action.WRITE };
|
||||||
try {
|
try {
|
||||||
AccessControlClient.grant(conf, tableName, userOwner.getShortName(), null, null, actions);
|
AccessControlClient.grant(conf, tableName, userOwner.getShortName(), null, null, actions);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ java_import org.apache.hadoop.hbase.util.Pair
|
||||||
java_import org.apache.hadoop.hbase.util.RegionSplitter
|
java_import org.apache.hadoop.hbase.util.RegionSplitter
|
||||||
java_import org.apache.hadoop.hbase.util.Bytes
|
java_import org.apache.hadoop.hbase.util.Bytes
|
||||||
java_import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos::SnapshotDescription
|
java_import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos::SnapshotDescription
|
||||||
|
java_import org.apache.commons.collections.MapUtils
|
||||||
|
|
||||||
# Wrapper for org.apache.hadoop.hbase.client.HBaseAdmin
|
# Wrapper for org.apache.hadoop.hbase.client.HBaseAdmin
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue