HBASE-19483 Add proper privilege check for rsgroup commands - revert due to pending review comment
This commit is contained in:
parent
fc7736eb00
commit
5ce9351129
|
@ -23,10 +23,11 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.hbase.io.hfile.HFile;
|
||||||
import org.apache.hadoop.hbase.security.User;
|
import org.apache.hadoop.hbase.security.User;
|
||||||
import org.apache.hadoop.hbase.security.visibility.LoadTestDataGeneratorWithVisibilityLabels;
|
import org.apache.hadoop.hbase.security.visibility.LoadTestDataGeneratorWithVisibilityLabels;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
||||||
import org.apache.hadoop.hbase.testclassification.IntegrationTests;
|
import org.apache.hadoop.hbase.testclassification.IntegrationTests;
|
||||||
import org.apache.hadoop.hbase.util.LoadTestTool;
|
import org.apache.hadoop.hbase.util.LoadTestTool;
|
||||||
import org.junit.experimental.categories.Category;
|
import org.junit.experimental.categories.Category;
|
||||||
|
@ -75,7 +76,9 @@ public class IntegrationTestIngestWithVisibilityLabels extends IntegrationTestIn
|
||||||
public void setUpCluster() throws Exception {
|
public void setUpCluster() throws Exception {
|
||||||
util = getTestingUtil(null);
|
util = getTestingUtil(null);
|
||||||
Configuration conf = util.getConfiguration();
|
Configuration conf = util.getConfiguration();
|
||||||
VisibilityTestUtil.enableVisiblityLabels(conf);
|
conf.setInt(HFile.FORMAT_VERSION_KEY, 3);
|
||||||
|
conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
|
||||||
|
conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
|
||||||
conf.set("hbase.superuser", "admin," + User.getCurrent().getName());
|
conf.set("hbase.superuser", "admin," + User.getCurrent().getName());
|
||||||
super.setUpCluster();
|
super.setUpCluster();
|
||||||
addLabels();
|
addLabels();
|
||||||
|
|
|
@ -47,6 +47,7 @@ import org.apache.hadoop.hbase.client.Put;
|
||||||
import org.apache.hadoop.hbase.client.Result;
|
import org.apache.hadoop.hbase.client.Result;
|
||||||
import org.apache.hadoop.hbase.client.Scan;
|
import org.apache.hadoop.hbase.client.Scan;
|
||||||
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
|
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
|
||||||
|
import org.apache.hadoop.hbase.io.hfile.HFile;
|
||||||
import org.apache.hadoop.hbase.log.HBaseMarkers;
|
import org.apache.hadoop.hbase.log.HBaseMarkers;
|
||||||
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;
|
||||||
|
@ -56,7 +57,7 @@ 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.VisibilityTestUtil;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
||||||
import org.apache.hadoop.hbase.testclassification.IntegrationTests;
|
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;
|
||||||
|
@ -372,7 +373,9 @@ public class IntegrationTestBigLinkedListWithVisibility extends IntegrationTestB
|
||||||
public void setUpCluster() throws Exception {
|
public void setUpCluster() throws Exception {
|
||||||
util = getTestingUtil(null);
|
util = getTestingUtil(null);
|
||||||
Configuration conf = util.getConfiguration();
|
Configuration conf = util.getConfiguration();
|
||||||
VisibilityTestUtil.enableVisiblityLabels(conf);
|
conf.setInt(HFile.FORMAT_VERSION_KEY, 3);
|
||||||
|
conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
|
||||||
|
conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
|
||||||
conf.set("hbase.superuser", User.getCurrent().getName());
|
conf.set("hbase.superuser", User.getCurrent().getName());
|
||||||
conf.setBoolean("dfs.permissions", false);
|
conf.setBoolean("dfs.permissions", false);
|
||||||
USER = User.createUserForTesting(conf, userName, new String[] {});
|
USER = User.createUserForTesting(conf, userName, new String[] {});
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.apache.hadoop.hbase.client.Result;
|
||||||
import org.apache.hadoop.hbase.client.Scan;
|
import org.apache.hadoop.hbase.client.Scan;
|
||||||
import org.apache.hadoop.hbase.client.ScannerCallable;
|
import org.apache.hadoop.hbase.client.ScannerCallable;
|
||||||
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
|
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
|
||||||
|
import org.apache.hadoop.hbase.io.hfile.HFile;
|
||||||
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
|
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
|
||||||
import org.apache.hadoop.hbase.mapreduce.TableMapper;
|
import org.apache.hadoop.hbase.mapreduce.TableMapper;
|
||||||
import org.apache.hadoop.hbase.mapreduce.TableRecordReaderImpl;
|
import org.apache.hadoop.hbase.mapreduce.TableRecordReaderImpl;
|
||||||
|
@ -47,7 +48,7 @@ import org.apache.hadoop.hbase.security.User;
|
||||||
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.VisibilityTestUtil;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
||||||
import org.apache.hadoop.hbase.testclassification.IntegrationTests;
|
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;
|
||||||
|
@ -115,7 +116,9 @@ public class IntegrationTestWithCellVisibilityLoadAndVerify extends IntegrationT
|
||||||
public void setUpCluster() throws Exception {
|
public void setUpCluster() throws Exception {
|
||||||
util = getTestingUtil(null);
|
util = getTestingUtil(null);
|
||||||
Configuration conf = util.getConfiguration();
|
Configuration conf = util.getConfiguration();
|
||||||
VisibilityTestUtil.enableVisiblityLabels(conf);
|
conf.setInt(HFile.FORMAT_VERSION_KEY, 3);
|
||||||
|
conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
|
||||||
|
conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
|
||||||
conf.set("hbase.superuser", User.getCurrent().getName());
|
conf.set("hbase.superuser", User.getCurrent().getName());
|
||||||
conf.setBoolean("dfs.permissions", false);
|
conf.setBoolean("dfs.permissions", false);
|
||||||
super.setUpCluster();
|
super.setUpCluster();
|
||||||
|
|
|
@ -58,7 +58,7 @@ import org.apache.hadoop.hbase.security.visibility.ScanLabelGenerator;
|
||||||
import org.apache.hadoop.hbase.security.visibility.SimpleScanLabelGenerator;
|
import org.apache.hadoop.hbase.security.visibility.SimpleScanLabelGenerator;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
|
||||||
import org.apache.hadoop.hbase.testclassification.LargeTests;
|
import org.apache.hadoop.hbase.testclassification.LargeTests;
|
||||||
import org.apache.hadoop.hbase.testclassification.MapReduceTests;
|
import org.apache.hadoop.hbase.testclassification.MapReduceTests;
|
||||||
|
@ -121,7 +121,9 @@ public class TestImportTSVWithVisibilityLabels implements Configurable {
|
||||||
conf = util.getConfiguration();
|
conf = util.getConfiguration();
|
||||||
SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
|
SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
|
||||||
conf.set("hbase.superuser", "admin,"+User.getCurrent().getName());
|
conf.set("hbase.superuser", "admin,"+User.getCurrent().getName());
|
||||||
VisibilityTestUtil.enableVisiblityLabels(conf);
|
conf.setInt("hfile.format.version", 3);
|
||||||
|
conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
|
||||||
|
conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
|
||||||
conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class,
|
conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class,
|
||||||
ScanLabelGenerator.class);
|
ScanLabelGenerator.class);
|
||||||
util.startMiniCluster();
|
util.startMiniCluster();
|
||||||
|
|
|
@ -43,7 +43,7 @@ import org.apache.hadoop.hbase.security.visibility.ScanLabelGenerator;
|
||||||
import org.apache.hadoop.hbase.security.visibility.SimpleScanLabelGenerator;
|
import org.apache.hadoop.hbase.security.visibility.SimpleScanLabelGenerator;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
|
||||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||||
import org.apache.hadoop.hbase.testclassification.RestTests;
|
import org.apache.hadoop.hbase.testclassification.RestTests;
|
||||||
|
@ -130,8 +130,10 @@ public class TestScannersWithLabels {
|
||||||
conf = TEST_UTIL.getConfiguration();
|
conf = TEST_UTIL.getConfiguration();
|
||||||
conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS,
|
conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS,
|
||||||
SimpleScanLabelGenerator.class, ScanLabelGenerator.class);
|
SimpleScanLabelGenerator.class, ScanLabelGenerator.class);
|
||||||
|
conf.setInt("hfile.format.version", 3);
|
||||||
conf.set("hbase.superuser", SUPERUSER.getShortName());
|
conf.set("hbase.superuser", SUPERUSER.getShortName());
|
||||||
VisibilityTestUtil.enableVisiblityLabels(conf);
|
conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
|
||||||
|
conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
|
||||||
TEST_UTIL.startMiniCluster(1);
|
TEST_UTIL.startMiniCluster(1);
|
||||||
// Wait for the labels table to become available
|
// Wait for the labels table to become available
|
||||||
TEST_UTIL.waitTableEnabled(VisibilityConstants.LABELS_TABLE_NAME.getName(), 50000);
|
TEST_UTIL.waitTableEnabled(VisibilityConstants.LABELS_TABLE_NAME.getName(), 50000);
|
||||||
|
|
|
@ -46,7 +46,6 @@ import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
|
||||||
import org.apache.hadoop.hbase.coprocessor.MasterObserver;
|
import org.apache.hadoop.hbase.coprocessor.MasterObserver;
|
||||||
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
|
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
|
||||||
import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
|
import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
|
||||||
import org.apache.hadoop.hbase.ipc.RpcServer;
|
|
||||||
import org.apache.hadoop.hbase.master.MasterServices;
|
import org.apache.hadoop.hbase.master.MasterServices;
|
||||||
import org.apache.hadoop.hbase.net.Address;
|
import org.apache.hadoop.hbase.net.Address;
|
||||||
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
|
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
|
||||||
|
@ -75,11 +74,6 @@ import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveRSGro
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupResponse;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveServersRequest;
|
import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveServersRequest;
|
||||||
import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveServersResponse;
|
import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveServersResponse;
|
||||||
import org.apache.hadoop.hbase.security.User;
|
|
||||||
import org.apache.hadoop.hbase.security.UserProvider;
|
|
||||||
import org.apache.hadoop.hbase.security.access.AccessChecker;
|
|
||||||
import org.apache.hadoop.hbase.security.access.Permission.Action;
|
|
||||||
import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
|
|
||||||
import org.apache.yetus.audience.InterfaceAudience;
|
import org.apache.yetus.audience.InterfaceAudience;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -98,17 +92,12 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
private RSGroupInfoManager groupInfoManager;
|
private RSGroupInfoManager groupInfoManager;
|
||||||
private RSGroupAdminServer groupAdminServer;
|
private RSGroupAdminServer groupAdminServer;
|
||||||
private final RSGroupAdminService groupAdminService = new RSGroupAdminServiceImpl();
|
private final RSGroupAdminService groupAdminService = new RSGroupAdminServiceImpl();
|
||||||
private AccessChecker accessChecker;
|
|
||||||
|
|
||||||
/** Provider for mapping principal names to Users */
|
|
||||||
private UserProvider userProvider;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(CoprocessorEnvironment env) throws IOException {
|
public void start(CoprocessorEnvironment env) throws IOException {
|
||||||
if (!(env instanceof HasMasterServices)) {
|
if (!(env instanceof HasMasterServices)) {
|
||||||
throw new IOException("Does not implement HMasterServices");
|
throw new IOException("Does not implement HMasterServices");
|
||||||
}
|
}
|
||||||
|
|
||||||
master = ((HasMasterServices)env).getMasterServices();
|
master = ((HasMasterServices)env).getMasterServices();
|
||||||
groupInfoManager = RSGroupInfoManagerImpl.getInstance(master);
|
groupInfoManager = RSGroupInfoManagerImpl.getInstance(master);
|
||||||
groupAdminServer = new RSGroupAdminServer(master, groupInfoManager);
|
groupAdminServer = new RSGroupAdminServer(master, groupInfoManager);
|
||||||
|
@ -117,11 +106,6 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
if (!RSGroupableBalancer.class.isAssignableFrom(clazz)) {
|
if (!RSGroupableBalancer.class.isAssignableFrom(clazz)) {
|
||||||
throw new IOException("Configured balancer does not support RegionServer groups.");
|
throw new IOException("Configured balancer does not support RegionServer groups.");
|
||||||
}
|
}
|
||||||
ZKWatcher zk = ((HasMasterServices)env).getMasterServices().getZooKeeper();
|
|
||||||
accessChecker = new AccessChecker(env.getConfiguration(), zk);
|
|
||||||
|
|
||||||
// set the user-provider.
|
|
||||||
this.userProvider = UserProvider.instantiate(env.getConfiguration());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -153,7 +137,6 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, group="
|
LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, group="
|
||||||
+ groupName);
|
+ groupName);
|
||||||
try {
|
try {
|
||||||
checkPermission("getRSGroupInfo");
|
|
||||||
RSGroupInfo rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName);
|
RSGroupInfo rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName);
|
||||||
if (rsGroupInfo != null) {
|
if (rsGroupInfo != null) {
|
||||||
builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(rsGroupInfo));
|
builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(rsGroupInfo));
|
||||||
|
@ -168,11 +151,10 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
public void getRSGroupInfoOfTable(RpcController controller,
|
public void getRSGroupInfoOfTable(RpcController controller,
|
||||||
GetRSGroupInfoOfTableRequest request, RpcCallback<GetRSGroupInfoOfTableResponse> done) {
|
GetRSGroupInfoOfTableRequest request, RpcCallback<GetRSGroupInfoOfTableResponse> done) {
|
||||||
GetRSGroupInfoOfTableResponse.Builder builder = GetRSGroupInfoOfTableResponse.newBuilder();
|
GetRSGroupInfoOfTableResponse.Builder builder = GetRSGroupInfoOfTableResponse.newBuilder();
|
||||||
TableName tableName = ProtobufUtil.toTableName(request.getTableName());
|
|
||||||
LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, table="
|
|
||||||
+ tableName);
|
|
||||||
try {
|
try {
|
||||||
checkPermission("getRSGroupInfoOfTable");
|
TableName tableName = ProtobufUtil.toTableName(request.getTableName());
|
||||||
|
LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, table="
|
||||||
|
+ tableName);
|
||||||
RSGroupInfo RSGroupInfo = groupAdminServer.getRSGroupInfoOfTable(tableName);
|
RSGroupInfo RSGroupInfo = groupAdminServer.getRSGroupInfoOfTable(tableName);
|
||||||
if (RSGroupInfo != null) {
|
if (RSGroupInfo != null) {
|
||||||
builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
|
builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
|
||||||
|
@ -187,14 +169,13 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
public void moveServers(RpcController controller, MoveServersRequest request,
|
public void moveServers(RpcController controller, MoveServersRequest request,
|
||||||
RpcCallback<MoveServersResponse> done) {
|
RpcCallback<MoveServersResponse> done) {
|
||||||
MoveServersResponse.Builder builder = MoveServersResponse.newBuilder();
|
MoveServersResponse.Builder builder = MoveServersResponse.newBuilder();
|
||||||
Set<Address> hostPorts = Sets.newHashSet();
|
|
||||||
for (HBaseProtos.ServerName el : request.getServersList()) {
|
|
||||||
hostPorts.add(Address.fromParts(el.getHostName(), el.getPort()));
|
|
||||||
}
|
|
||||||
LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts +" to rsgroup "
|
|
||||||
+ request.getTargetGroup());
|
|
||||||
try {
|
try {
|
||||||
checkPermission("moveServers");
|
Set<Address> hostPorts = Sets.newHashSet();
|
||||||
|
for (HBaseProtos.ServerName el : request.getServersList()) {
|
||||||
|
hostPorts.add(Address.fromParts(el.getHostName(), el.getPort()));
|
||||||
|
}
|
||||||
|
LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts +" to rsgroup "
|
||||||
|
+ request.getTargetGroup());
|
||||||
groupAdminServer.moveServers(hostPorts, request.getTargetGroup());
|
groupAdminServer.moveServers(hostPorts, request.getTargetGroup());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
CoprocessorRpcUtils.setControllerException(controller, e);
|
CoprocessorRpcUtils.setControllerException(controller, e);
|
||||||
|
@ -206,14 +187,13 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
public void moveTables(RpcController controller, MoveTablesRequest request,
|
public void moveTables(RpcController controller, MoveTablesRequest request,
|
||||||
RpcCallback<MoveTablesResponse> done) {
|
RpcCallback<MoveTablesResponse> done) {
|
||||||
MoveTablesResponse.Builder builder = MoveTablesResponse.newBuilder();
|
MoveTablesResponse.Builder builder = MoveTablesResponse.newBuilder();
|
||||||
Set<TableName> tables = new HashSet<>(request.getTableNameList().size());
|
|
||||||
for (HBaseProtos.TableName tableName : request.getTableNameList()) {
|
|
||||||
tables.add(ProtobufUtil.toTableName(tableName));
|
|
||||||
}
|
|
||||||
LOG.info(master.getClientIdAuditPrefix() + " move tables " + tables +" to rsgroup "
|
|
||||||
+ request.getTargetGroup());
|
|
||||||
try {
|
try {
|
||||||
checkPermission("moveTables");
|
Set<TableName> tables = new HashSet<>(request.getTableNameList().size());
|
||||||
|
for (HBaseProtos.TableName tableName : request.getTableNameList()) {
|
||||||
|
tables.add(ProtobufUtil.toTableName(tableName));
|
||||||
|
}
|
||||||
|
LOG.info(master.getClientIdAuditPrefix() + " move tables " + tables +" to rsgroup "
|
||||||
|
+ request.getTargetGroup());
|
||||||
groupAdminServer.moveTables(tables, request.getTargetGroup());
|
groupAdminServer.moveTables(tables, request.getTargetGroup());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
CoprocessorRpcUtils.setControllerException(controller, e);
|
CoprocessorRpcUtils.setControllerException(controller, e);
|
||||||
|
@ -227,7 +207,6 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
AddRSGroupResponse.Builder builder = AddRSGroupResponse.newBuilder();
|
AddRSGroupResponse.Builder builder = AddRSGroupResponse.newBuilder();
|
||||||
LOG.info(master.getClientIdAuditPrefix() + " add rsgroup " + request.getRSGroupName());
|
LOG.info(master.getClientIdAuditPrefix() + " add rsgroup " + request.getRSGroupName());
|
||||||
try {
|
try {
|
||||||
checkPermission("addRSGroup");
|
|
||||||
groupAdminServer.addRSGroup(request.getRSGroupName());
|
groupAdminServer.addRSGroup(request.getRSGroupName());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
CoprocessorRpcUtils.setControllerException(controller, e);
|
CoprocessorRpcUtils.setControllerException(controller, e);
|
||||||
|
@ -242,7 +221,6 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
RemoveRSGroupResponse.newBuilder();
|
RemoveRSGroupResponse.newBuilder();
|
||||||
LOG.info(master.getClientIdAuditPrefix() + " remove rsgroup " + request.getRSGroupName());
|
LOG.info(master.getClientIdAuditPrefix() + " remove rsgroup " + request.getRSGroupName());
|
||||||
try {
|
try {
|
||||||
checkPermission("removeRSGroup");
|
|
||||||
groupAdminServer.removeRSGroup(request.getRSGroupName());
|
groupAdminServer.removeRSGroup(request.getRSGroupName());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
CoprocessorRpcUtils.setControllerException(controller, e);
|
CoprocessorRpcUtils.setControllerException(controller, e);
|
||||||
|
@ -257,7 +235,6 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
LOG.info(master.getClientIdAuditPrefix() + " balance rsgroup, group=" +
|
LOG.info(master.getClientIdAuditPrefix() + " balance rsgroup, group=" +
|
||||||
request.getRSGroupName());
|
request.getRSGroupName());
|
||||||
try {
|
try {
|
||||||
checkPermission("balanceRSGroup");
|
|
||||||
builder.setBalanceRan(groupAdminServer.balanceRSGroup(request.getRSGroupName()));
|
builder.setBalanceRan(groupAdminServer.balanceRSGroup(request.getRSGroupName()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
CoprocessorRpcUtils.setControllerException(controller, e);
|
CoprocessorRpcUtils.setControllerException(controller, e);
|
||||||
|
@ -272,7 +249,6 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
ListRSGroupInfosResponse.Builder builder = ListRSGroupInfosResponse.newBuilder();
|
ListRSGroupInfosResponse.Builder builder = ListRSGroupInfosResponse.newBuilder();
|
||||||
LOG.info(master.getClientIdAuditPrefix() + " list rsgroup");
|
LOG.info(master.getClientIdAuditPrefix() + " list rsgroup");
|
||||||
try {
|
try {
|
||||||
checkPermission("listRSGroup");
|
|
||||||
for (RSGroupInfo RSGroupInfo : groupAdminServer.listRSGroups()) {
|
for (RSGroupInfo RSGroupInfo : groupAdminServer.listRSGroups()) {
|
||||||
builder.addRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
|
builder.addRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
|
||||||
}
|
}
|
||||||
|
@ -286,12 +262,11 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
public void getRSGroupInfoOfServer(RpcController controller,
|
public void getRSGroupInfoOfServer(RpcController controller,
|
||||||
GetRSGroupInfoOfServerRequest request, RpcCallback<GetRSGroupInfoOfServerResponse> done) {
|
GetRSGroupInfoOfServerRequest request, RpcCallback<GetRSGroupInfoOfServerResponse> done) {
|
||||||
GetRSGroupInfoOfServerResponse.Builder builder = GetRSGroupInfoOfServerResponse.newBuilder();
|
GetRSGroupInfoOfServerResponse.Builder builder = GetRSGroupInfoOfServerResponse.newBuilder();
|
||||||
Address hp = Address.fromParts(request.getServer().getHostName(),
|
|
||||||
request.getServer().getPort());
|
|
||||||
LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, server="
|
|
||||||
+ hp);
|
|
||||||
try {
|
try {
|
||||||
checkPermission("getRSGroupInfoOfServer");
|
Address hp = Address.fromParts(request.getServer().getHostName(),
|
||||||
|
request.getServer().getPort());
|
||||||
|
LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, server=" +
|
||||||
|
hp);
|
||||||
RSGroupInfo RSGroupInfo = groupAdminServer.getRSGroupOfServer(hp);
|
RSGroupInfo RSGroupInfo = groupAdminServer.getRSGroupOfServer(hp);
|
||||||
if (RSGroupInfo != null) {
|
if (RSGroupInfo != null) {
|
||||||
builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
|
builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
|
||||||
|
@ -306,18 +281,17 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
public void moveServersAndTables(RpcController controller,
|
public void moveServersAndTables(RpcController controller,
|
||||||
MoveServersAndTablesRequest request, RpcCallback<MoveServersAndTablesResponse> done) {
|
MoveServersAndTablesRequest request, RpcCallback<MoveServersAndTablesResponse> done) {
|
||||||
MoveServersAndTablesResponse.Builder builder = MoveServersAndTablesResponse.newBuilder();
|
MoveServersAndTablesResponse.Builder builder = MoveServersAndTablesResponse.newBuilder();
|
||||||
Set<Address> hostPorts = Sets.newHashSet();
|
|
||||||
for (HBaseProtos.ServerName el : request.getServersList()) {
|
|
||||||
hostPorts.add(Address.fromParts(el.getHostName(), el.getPort()));
|
|
||||||
}
|
|
||||||
Set<TableName> tables = new HashSet<>(request.getTableNameList().size());
|
|
||||||
for (HBaseProtos.TableName tableName : request.getTableNameList()) {
|
|
||||||
tables.add(ProtobufUtil.toTableName(tableName));
|
|
||||||
}
|
|
||||||
LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts
|
|
||||||
+ " and tables " + tables + " to rsgroup" + request.getTargetGroup());
|
|
||||||
try {
|
try {
|
||||||
checkPermission("moveServersAndTables");
|
Set<Address> hostPorts = Sets.newHashSet();
|
||||||
|
for (HBaseProtos.ServerName el : request.getServersList()) {
|
||||||
|
hostPorts.add(Address.fromParts(el.getHostName(), el.getPort()));
|
||||||
|
}
|
||||||
|
Set<TableName> tables = new HashSet<>(request.getTableNameList().size());
|
||||||
|
for (HBaseProtos.TableName tableName : request.getTableNameList()) {
|
||||||
|
tables.add(ProtobufUtil.toTableName(tableName));
|
||||||
|
}
|
||||||
|
LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts
|
||||||
|
+ " and tables " + tables + " to rsgroup" + request.getTargetGroup());
|
||||||
groupAdminServer.moveServersAndTables(hostPorts, tables, request.getTargetGroup());
|
groupAdminServer.moveServersAndTables(hostPorts, tables, request.getTargetGroup());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
CoprocessorRpcUtils.setControllerException(controller, e);
|
CoprocessorRpcUtils.setControllerException(controller, e);
|
||||||
|
@ -331,14 +305,13 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
RpcCallback<RemoveServersResponse> done) {
|
RpcCallback<RemoveServersResponse> done) {
|
||||||
RemoveServersResponse.Builder builder =
|
RemoveServersResponse.Builder builder =
|
||||||
RemoveServersResponse.newBuilder();
|
RemoveServersResponse.newBuilder();
|
||||||
Set<Address> servers = Sets.newHashSet();
|
|
||||||
for (HBaseProtos.ServerName el : request.getServersList()) {
|
|
||||||
servers.add(Address.fromParts(el.getHostName(), el.getPort()));
|
|
||||||
}
|
|
||||||
LOG.info(master.getClientIdAuditPrefix()
|
|
||||||
+ " remove decommissioned servers from rsgroup: " + servers);
|
|
||||||
try {
|
try {
|
||||||
checkPermission("removeServers");
|
Set<Address> servers = Sets.newHashSet();
|
||||||
|
for (HBaseProtos.ServerName el : request.getServersList()) {
|
||||||
|
servers.add(Address.fromParts(el.getHostName(), el.getPort()));
|
||||||
|
}
|
||||||
|
LOG.info(master.getClientIdAuditPrefix()
|
||||||
|
+ " remove decommissioned servers from rsgroup: " + servers);
|
||||||
groupAdminServer.removeServers(servers);
|
groupAdminServer.removeServers(servers);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
CoprocessorRpcUtils.setControllerException(controller, e);
|
CoprocessorRpcUtils.setControllerException(controller, e);
|
||||||
|
@ -424,21 +397,5 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
|
||||||
groupAdminServer.removeServers(clearedServer);
|
groupAdminServer.removeServers(clearedServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkPermission(String request) throws IOException {
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
accessChecker.requirePermission(getActiveUser(), request, Action.ADMIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the active user to which authorization checks should be applied.
|
|
||||||
* If we are in the context of an RPC call, the remote user is used,
|
|
||||||
* otherwise the currently logged in user is used.
|
|
||||||
*/
|
|
||||||
public User getActiveUser() throws IOException {
|
|
||||||
// for non-rpc handling, fallback to system user
|
|
||||||
Optional<User> optionalUser = RpcServer.getRequestUser();
|
|
||||||
if (optionalUser.isPresent()) {
|
|
||||||
return optionalUser.get();
|
|
||||||
}
|
|
||||||
return userProvider.getCurrent();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,6 @@ import org.apache.hadoop.hbase.replication.ReplicationException;
|
||||||
import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
|
import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
|
||||||
import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
|
import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
|
||||||
import org.apache.hadoop.hbase.security.User;
|
import org.apache.hadoop.hbase.security.User;
|
||||||
import org.apache.hadoop.hbase.security.access.AccessChecker;
|
|
||||||
import org.apache.hadoop.hbase.security.access.AccessController;
|
import org.apache.hadoop.hbase.security.access.AccessController;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
||||||
import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
|
import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
|
||||||
|
@ -1811,7 +1810,7 @@ public class MasterRpcServices extends RSRpcServices
|
||||||
// A coprocessor that implements AccessControlService can provide AUTHORIZATION and
|
// A coprocessor that implements AccessControlService can provide AUTHORIZATION and
|
||||||
// CELL_AUTHORIZATION
|
// CELL_AUTHORIZATION
|
||||||
if (master.cpHost != null && hasAccessControlServiceCoprocessor(master.cpHost)) {
|
if (master.cpHost != null && hasAccessControlServiceCoprocessor(master.cpHost)) {
|
||||||
if (AccessChecker.isAuthorizationSupported(master.getConfiguration())) {
|
if (AccessController.isAuthorizationSupported(master.getConfiguration())) {
|
||||||
capabilities.add(SecurityCapabilitiesResponse.Capability.AUTHORIZATION);
|
capabilities.add(SecurityCapabilitiesResponse.Capability.AUTHORIZATION);
|
||||||
}
|
}
|
||||||
if (AccessController.isCellAuthorizationSupported(master.getConfiguration())) {
|
if (AccessController.isCellAuthorizationSupported(master.getConfiguration())) {
|
||||||
|
|
|
@ -1,333 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.io.IOException;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
|
||||||
import org.apache.hadoop.hbase.DoNotRetryIOException;
|
|
||||||
import org.apache.hadoop.hbase.TableName;
|
|
||||||
import org.apache.hadoop.hbase.client.RegionInfo;
|
|
||||||
import org.apache.hadoop.hbase.ipc.RpcServer;
|
|
||||||
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.hadoop.hbase.zookeeper.ZKWatcher;
|
|
||||||
import org.apache.yetus.audience.InterfaceAudience;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@InterfaceAudience.Private
|
|
||||||
public final class AccessChecker {
|
|
||||||
private static final Logger AUDITLOG =
|
|
||||||
LoggerFactory.getLogger("SecurityLogger." + AccessChecker.class.getName());
|
|
||||||
private TableAuthManager authManager;
|
|
||||||
/**
|
|
||||||
* if we are active, usually false, only true if "hbase.security.authorization"
|
|
||||||
* has been set to true in site configuration.see HBASE-19483.
|
|
||||||
*/
|
|
||||||
private boolean authorizationEnabled;
|
|
||||||
|
|
||||||
public static boolean isAuthorizationSupported(Configuration conf) {
|
|
||||||
return conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor with existing configuration
|
|
||||||
*
|
|
||||||
* @param conf Existing configuration to use
|
|
||||||
* @param zkw reference to the {@link ZKWatcher}
|
|
||||||
* @return the AccessChecker instance
|
|
||||||
*/
|
|
||||||
public AccessChecker(final Configuration conf, final ZKWatcher zkw)
|
|
||||||
throws RuntimeException {
|
|
||||||
// If zk is null or IOException while obtaining auth manager,
|
|
||||||
// throw RuntimeException so that the coprocessor is unloaded.
|
|
||||||
if (zkw != null) {
|
|
||||||
try {
|
|
||||||
this.authManager = TableAuthManager.getOrCreate(zkw, conf);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new RuntimeException("Error obtaining AccessChecker", ioe);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new NullPointerException("Error obtaining AccessChecker, zk found null.");
|
|
||||||
}
|
|
||||||
authorizationEnabled = isAuthorizationSupported(conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TableAuthManager getAuthManager() {
|
|
||||||
return authManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authorizes that the current user has any of the given permissions to access the table.
|
|
||||||
*
|
|
||||||
* @param tableName Table requested
|
|
||||||
* @param permissions Actions being requested
|
|
||||||
* @throws IOException if obtaining the current user fails
|
|
||||||
* @throws AccessDeniedException if user has no authorization
|
|
||||||
*/
|
|
||||||
public void requireAccess(User user, String request, TableName tableName,
|
|
||||||
Action... permissions) throws IOException {
|
|
||||||
AuthResult result = null;
|
|
||||||
|
|
||||||
for (Action permission : permissions) {
|
|
||||||
if (authManager.hasAccess(user, tableName, permission)) {
|
|
||||||
result = AuthResult.allow(request, "Table permission granted",
|
|
||||||
user, permission, tableName, null, null);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// rest of the world
|
|
||||||
result = AuthResult.deny(request, "Insufficient permissions",
|
|
||||||
user, permission, tableName, null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logResult(result);
|
|
||||||
if (authorizationEnabled && !result.isAllowed()) {
|
|
||||||
throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authorizes that the current user has global privileges for the given action.
|
|
||||||
*
|
|
||||||
* @param perm The action being requested
|
|
||||||
* @throws IOException if obtaining the current user fails
|
|
||||||
* @throws AccessDeniedException if authorization is denied
|
|
||||||
*/
|
|
||||||
public void requirePermission(User user, String request, Action perm)
|
|
||||||
throws IOException {
|
|
||||||
requireGlobalPermission(user, request, perm, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks that the user has the given global permission. The generated
|
|
||||||
* audit log message will contain context information for the operation
|
|
||||||
* being authorized, based on the given parameters.
|
|
||||||
*
|
|
||||||
* @param perm Action being requested
|
|
||||||
* @param tableName Affected table name.
|
|
||||||
* @param familyMap Affected column families.
|
|
||||||
*/
|
|
||||||
public void requireGlobalPermission(User user, String request,
|
|
||||||
Action perm, TableName tableName,
|
|
||||||
Map<byte[], ? extends Collection<byte[]>> familyMap)throws IOException {
|
|
||||||
AuthResult result;
|
|
||||||
if (authManager.authorize(user, perm)) {
|
|
||||||
result = AuthResult.allow(request, "Global check allowed",
|
|
||||||
user, perm, tableName, familyMap);
|
|
||||||
result.getParams().setTableName(tableName).setFamilies(familyMap);
|
|
||||||
logResult(result);
|
|
||||||
} else {
|
|
||||||
result = AuthResult.deny(request, "Global check failed",
|
|
||||||
user, perm, tableName, familyMap);
|
|
||||||
result.getParams().setTableName(tableName).setFamilies(familyMap);
|
|
||||||
logResult(result);
|
|
||||||
if (authorizationEnabled) {
|
|
||||||
throw new AccessDeniedException(
|
|
||||||
"Insufficient permissions for user '" + (user != null ? user.getShortName() : "null")
|
|
||||||
+ "' (global, action=" + perm.toString() + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks that the user has the given global permission. The generated
|
|
||||||
* audit log message will contain context information for the operation
|
|
||||||
* being authorized, based on the given parameters.
|
|
||||||
*
|
|
||||||
* @param perm Action being requested
|
|
||||||
* @param namespace The given namespace
|
|
||||||
*/
|
|
||||||
public void requireGlobalPermission(User user, String request, Action perm,
|
|
||||||
String namespace) throws IOException {
|
|
||||||
AuthResult authResult;
|
|
||||||
if (authManager.authorize(user, perm)) {
|
|
||||||
authResult = AuthResult.allow(request, "Global check allowed",
|
|
||||||
user, perm, null);
|
|
||||||
authResult.getParams().setNamespace(namespace);
|
|
||||||
logResult(authResult);
|
|
||||||
} else {
|
|
||||||
authResult = AuthResult.deny(request, "Global check failed",
|
|
||||||
user, perm, null);
|
|
||||||
authResult.getParams().setNamespace(namespace);
|
|
||||||
logResult(authResult);
|
|
||||||
if (authorizationEnabled) {
|
|
||||||
throw new AccessDeniedException(
|
|
||||||
"Insufficient permissions for user '" + (user != null ? user.getShortName() : "null")
|
|
||||||
+ "' (global, action=" + perm.toString() + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks that the user has the given global or namespace permission.
|
|
||||||
*
|
|
||||||
* @param namespace The given namespace
|
|
||||||
* @param permissions Actions being requested
|
|
||||||
*/
|
|
||||||
public void requireNamespacePermission(User user, String request, String namespace,
|
|
||||||
Action... permissions) throws IOException {
|
|
||||||
AuthResult result = null;
|
|
||||||
|
|
||||||
for (Action permission : permissions) {
|
|
||||||
if (authManager.authorize(user, namespace, permission)) {
|
|
||||||
result =
|
|
||||||
AuthResult.allow(request, "Namespace permission granted",
|
|
||||||
user, permission, namespace);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// rest of the world
|
|
||||||
result = AuthResult.deny(request, "Insufficient permissions",
|
|
||||||
user, permission, namespace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logResult(result);
|
|
||||||
if (authorizationEnabled && !result.isAllowed()) {
|
|
||||||
throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks that the user has the given global or namespace permission.
|
|
||||||
*
|
|
||||||
* @param namespace The given namespace
|
|
||||||
* @param permissions Actions being requested
|
|
||||||
*/
|
|
||||||
public void requireNamespacePermission(User user, String request, String namespace,
|
|
||||||
TableName tableName, Map<byte[], ? extends Collection<byte[]>> familyMap,
|
|
||||||
Action... permissions) throws IOException {
|
|
||||||
AuthResult result = null;
|
|
||||||
|
|
||||||
for (Action permission : permissions) {
|
|
||||||
if (authManager.authorize(user, namespace, permission)) {
|
|
||||||
result =
|
|
||||||
AuthResult.allow(request, "Namespace permission granted",
|
|
||||||
user, permission, namespace);
|
|
||||||
result.getParams().setTableName(tableName).setFamilies(familyMap);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// rest of the world
|
|
||||||
result = AuthResult.deny(request, "Insufficient permissions",
|
|
||||||
user, permission, namespace);
|
|
||||||
result.getParams().setTableName(tableName).setFamilies(familyMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logResult(result);
|
|
||||||
if (authorizationEnabled && !result.isAllowed()) {
|
|
||||||
throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authorizes that the current user has any of the given permissions for the
|
|
||||||
* given table, column family and column qualifier.
|
|
||||||
*
|
|
||||||
* @param tableName Table requested
|
|
||||||
* @param family Column family requested
|
|
||||||
* @param qualifier Column qualifier requested
|
|
||||||
* @throws IOException if obtaining the current user fails
|
|
||||||
* @throws AccessDeniedException if user has no authorization
|
|
||||||
*/
|
|
||||||
public void requirePermission(User user, String request, TableName tableName, byte[] family,
|
|
||||||
byte[] qualifier, Action... permissions) throws IOException {
|
|
||||||
AuthResult result = null;
|
|
||||||
|
|
||||||
for (Action permission : permissions) {
|
|
||||||
if (authManager.authorize(user, tableName, family, qualifier, permission)) {
|
|
||||||
result = AuthResult.allow(request, "Table permission granted",
|
|
||||||
user, permission, tableName, family,
|
|
||||||
qualifier);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// rest of the world
|
|
||||||
result = AuthResult.deny(request, "Insufficient permissions",
|
|
||||||
user, permission, tableName, family,
|
|
||||||
qualifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logResult(result);
|
|
||||||
if (authorizationEnabled && !result.isAllowed()) {
|
|
||||||
throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authorizes that the current user has any of the given permissions for the
|
|
||||||
* given table, column family and column qualifier.
|
|
||||||
*
|
|
||||||
* @param tableName Table requested
|
|
||||||
* @param family Column family param
|
|
||||||
* @param qualifier Column qualifier param
|
|
||||||
* @throws IOException if obtaining the current user fails
|
|
||||||
* @throws AccessDeniedException if user has no authorization
|
|
||||||
*/
|
|
||||||
public void requireTablePermission(User user, String request,
|
|
||||||
TableName tableName,byte[] family, byte[] qualifier,
|
|
||||||
Action... permissions) throws IOException {
|
|
||||||
AuthResult result = null;
|
|
||||||
|
|
||||||
for (Action permission : permissions) {
|
|
||||||
if (authManager.authorize(user, tableName, null, null, permission)) {
|
|
||||||
result = AuthResult.allow(request, "Table permission granted",
|
|
||||||
user, permission, tableName, null, null);
|
|
||||||
result.getParams().setFamily(family).setQualifier(qualifier);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// rest of the world
|
|
||||||
result = AuthResult.deny(request, "Insufficient permissions",
|
|
||||||
user, permission, tableName, family, qualifier);
|
|
||||||
result.getParams().setFamily(family).setQualifier(qualifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logResult(result);
|
|
||||||
if (authorizationEnabled && !result.isAllowed()) {
|
|
||||||
throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkLockPermissions(User user, String namespace,
|
|
||||||
TableName tableName, RegionInfo[] regionInfos, String reason)
|
|
||||||
throws IOException {
|
|
||||||
if (namespace != null && !namespace.isEmpty()) {
|
|
||||||
requireNamespacePermission(user, reason, namespace, Action.ADMIN, Action.CREATE);
|
|
||||||
} else if (tableName != null || (regionInfos != null && regionInfos.length > 0)) {
|
|
||||||
// So, either a table or regions op. If latter, check perms ons table.
|
|
||||||
TableName tn = tableName != null? tableName: regionInfos[0].getTable();
|
|
||||||
requireTablePermission(user, reason, tn, null, null,
|
|
||||||
Action.ADMIN, Action.CREATE);
|
|
||||||
} else {
|
|
||||||
throw new DoNotRetryIOException("Invalid lock level when requesting permissions.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void logResult(AuthResult result) {
|
|
||||||
if (AUDITLOG.isTraceEnabled()) {
|
|
||||||
AUDITLOG.trace("Access " + (result.isAllowed() ? "allowed" : "denied") + " for user " + (
|
|
||||||
result.getUser() != null ?
|
|
||||||
result.getUser().getShortName() :
|
|
||||||
"UNKNOWN") + "; reason: " + result.getReason() + "; remote address: "
|
|
||||||
+ RpcServer.getRemoteAddress().map(InetAddress::toString).orElse("")
|
|
||||||
+ "; request: " + result.getRequest() + "; context: " + result.toContextString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -105,7 +105,6 @@ import org.apache.hadoop.hbase.regionserver.querymatcher.DeleteTracker;
|
||||||
import org.apache.hadoop.hbase.security.AccessDeniedException;
|
import org.apache.hadoop.hbase.security.AccessDeniedException;
|
||||||
import org.apache.hadoop.hbase.security.Superusers;
|
import org.apache.hadoop.hbase.security.Superusers;
|
||||||
import org.apache.hadoop.hbase.security.User;
|
import org.apache.hadoop.hbase.security.User;
|
||||||
import org.apache.hadoop.hbase.security.access.AccessChecker;
|
|
||||||
import org.apache.hadoop.hbase.security.access.AccessController;
|
import org.apache.hadoop.hbase.security.access.AccessController;
|
||||||
import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
|
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.MapMaker;
|
||||||
|
@ -142,8 +141,8 @@ public class VisibilityController implements MasterCoprocessor, RegionCoprocesso
|
||||||
|
|
||||||
private VisibilityLabelService visibilityLabelService;
|
private VisibilityLabelService visibilityLabelService;
|
||||||
|
|
||||||
/** if we are active, usually false, only true if "hbase.security.authorization"
|
/** if we are active, usually true, only not true if "hbase.security.authorization"
|
||||||
has been set to true in site configuration */
|
has been set to false in site configuration */
|
||||||
boolean authorizationEnabled;
|
boolean authorizationEnabled;
|
||||||
|
|
||||||
// Add to this list if there are any reserved tag types
|
// Add to this list if there are any reserved tag types
|
||||||
|
@ -154,15 +153,19 @@ public class VisibilityController implements MasterCoprocessor, RegionCoprocesso
|
||||||
RESERVED_VIS_TAG_TYPES.add(TagType.STRING_VIS_TAG_TYPE);
|
RESERVED_VIS_TAG_TYPES.add(TagType.STRING_VIS_TAG_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isAuthorizationSupported(Configuration conf) {
|
||||||
|
return conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isCellAuthorizationSupported(Configuration conf) {
|
public static boolean isCellAuthorizationSupported(Configuration conf) {
|
||||||
return AccessChecker.isAuthorizationSupported(conf);
|
return isAuthorizationSupported(conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(CoprocessorEnvironment env) throws IOException {
|
public void start(CoprocessorEnvironment env) throws IOException {
|
||||||
this.conf = env.getConfiguration();
|
this.conf = env.getConfiguration();
|
||||||
|
|
||||||
authorizationEnabled = AccessChecker.isAuthorizationSupported(conf);
|
authorizationEnabled = isAuthorizationSupported(conf);
|
||||||
if (!authorizationEnabled) {
|
if (!authorizationEnabled) {
|
||||||
LOG.warn("The VisibilityController has been loaded with authorization checks disabled.");
|
LOG.warn("The VisibilityController has been loaded with authorization checks disabled.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,6 @@ public class SecureTestUtil {
|
||||||
conf.set(CoprocessorHost.REGIONSERVER_COPROCESSOR_CONF_KEY, AccessController.class.getName());
|
conf.set(CoprocessorHost.REGIONSERVER_COPROCESSOR_CONF_KEY, AccessController.class.getName());
|
||||||
// Need HFile V3 for tags for security features
|
// Need HFile V3 for tags for security features
|
||||||
conf.setInt(HFile.FORMAT_VERSION_KEY, 3);
|
conf.setInt(HFile.FORMAT_VERSION_KEY, 3);
|
||||||
conf.set(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, "true");
|
|
||||||
configureSuperuser(conf);
|
configureSuperuser(conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,11 +129,6 @@ public class SecureTestUtil {
|
||||||
if (conf.getInt(HFile.FORMAT_VERSION_KEY, 2) < HFile.MIN_FORMAT_VERSION_WITH_TAGS) {
|
if (conf.getInt(HFile.FORMAT_VERSION_KEY, 2) < HFile.MIN_FORMAT_VERSION_WITH_TAGS) {
|
||||||
throw new RuntimeException("Post 0.96 security features require HFile version >= 3");
|
throw new RuntimeException("Post 0.96 security features require HFile version >= 3");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false)) {
|
|
||||||
throw new RuntimeException("Post 2.0.0 security features require set "
|
|
||||||
+ User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY + " to true");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkTablePerms(Configuration conf, TableName table, byte[] family, byte[] column,
|
public static void checkTablePerms(Configuration conf, TableName table, byte[] family, byte[] column,
|
||||||
|
|
|
@ -2838,6 +2838,81 @@ public class TestAccessController extends SecureTestUtil {
|
||||||
USER_GROUP_READ, USER_GROUP_ADMIN, USER_GROUP_CREATE);
|
USER_GROUP_READ, USER_GROUP_ADMIN, USER_GROUP_CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMoveServers() throws Exception {
|
||||||
|
AccessTestAction action1 = new AccessTestAction() {
|
||||||
|
@Override
|
||||||
|
public Object run() throws Exception {
|
||||||
|
ACCESS_CONTROLLER.preMoveServers(ObserverContextImpl.createAndPrepare(CP_ENV),
|
||||||
|
null, null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
verifyAllowed(action1, SUPERUSER, USER_ADMIN);
|
||||||
|
verifyDenied(action1, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMoveTables() throws Exception {
|
||||||
|
AccessTestAction action1 = new AccessTestAction() {
|
||||||
|
@Override
|
||||||
|
public Object run() throws Exception {
|
||||||
|
ACCESS_CONTROLLER.preMoveTables(ObserverContextImpl.createAndPrepare(CP_ENV),
|
||||||
|
null, null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
verifyAllowed(action1, SUPERUSER, USER_ADMIN);
|
||||||
|
verifyDenied(action1, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddGroup() throws Exception {
|
||||||
|
AccessTestAction action1 = new AccessTestAction() {
|
||||||
|
@Override
|
||||||
|
public Object run() throws Exception {
|
||||||
|
ACCESS_CONTROLLER.preAddRSGroup(ObserverContextImpl.createAndPrepare(CP_ENV),
|
||||||
|
null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
verifyAllowed(action1, SUPERUSER, USER_ADMIN);
|
||||||
|
verifyDenied(action1, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveGroup() throws Exception {
|
||||||
|
AccessTestAction action1 = new AccessTestAction() {
|
||||||
|
@Override
|
||||||
|
public Object run() throws Exception {
|
||||||
|
ACCESS_CONTROLLER.preRemoveRSGroup(ObserverContextImpl.createAndPrepare(CP_ENV),
|
||||||
|
null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
verifyAllowed(action1, SUPERUSER, USER_ADMIN);
|
||||||
|
verifyDenied(action1, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBalanceGroup() throws Exception {
|
||||||
|
AccessTestAction action1 = new AccessTestAction() {
|
||||||
|
@Override
|
||||||
|
public Object run() throws Exception {
|
||||||
|
ACCESS_CONTROLLER.preBalanceRSGroup(ObserverContextImpl.createAndPrepare(CP_ENV),
|
||||||
|
null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
verifyAllowed(action1, SUPERUSER, USER_ADMIN);
|
||||||
|
verifyDenied(action1, USER_CREATE, USER_RW, USER_RO, USER_NONE, USER_OWNER);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddReplicationPeer() throws Exception {
|
public void testAddReplicationPeer() throws Exception {
|
||||||
AccessTestAction action = new AccessTestAction() {
|
AccessTestAction action = new AccessTestAction() {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
|
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
|
||||||
import org.apache.hadoop.hbase.security.User;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods for testing visibility labels.
|
* Utility methods for testing visibility labels.
|
||||||
|
@ -23,7 +23,6 @@ public class VisibilityTestUtil {
|
||||||
|
|
||||||
public static void enableVisiblityLabels(Configuration conf) throws IOException {
|
public static void enableVisiblityLabels(Configuration conf) throws IOException {
|
||||||
conf.setInt("hfile.format.version", 3);
|
conf.setInt("hfile.format.version", 3);
|
||||||
conf.setBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, true);
|
|
||||||
appendCoprocessor(conf, CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
|
appendCoprocessor(conf, CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
|
||||||
VisibilityController.class.getName());
|
VisibilityController.class.getName());
|
||||||
appendCoprocessor(conf, CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
|
appendCoprocessor(conf, CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
|
||||||
|
|
|
@ -47,7 +47,7 @@ import org.apache.hadoop.hbase.security.visibility.ScanLabelGenerator;
|
||||||
import org.apache.hadoop.hbase.security.visibility.SimpleScanLabelGenerator;
|
import org.apache.hadoop.hbase.security.visibility.SimpleScanLabelGenerator;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
|
||||||
import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
|
import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
|
||||||
import org.apache.hadoop.hbase.testclassification.ClientTests;
|
import org.apache.hadoop.hbase.testclassification.ClientTests;
|
||||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||||
|
@ -78,386 +78,389 @@ public class TestThriftHBaseServiceHandlerWithLabels {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory
|
private static final Logger LOG = LoggerFactory
|
||||||
.getLogger(TestThriftHBaseServiceHandlerWithLabels.class);
|
.getLogger(TestThriftHBaseServiceHandlerWithLabels.class);
|
||||||
private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
|
private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
|
||||||
|
|
||||||
// Static names for tables, columns, rows, and values
|
// Static names for tables, columns, rows, and values
|
||||||
private static byte[] tableAname = Bytes.toBytes("tableA");
|
private static byte[] tableAname = Bytes.toBytes("tableA");
|
||||||
private static byte[] familyAname = Bytes.toBytes("familyA");
|
private static byte[] familyAname = Bytes.toBytes("familyA");
|
||||||
private static byte[] familyBname = Bytes.toBytes("familyB");
|
private static byte[] familyBname = Bytes.toBytes("familyB");
|
||||||
private static byte[] qualifierAname = Bytes.toBytes("qualifierA");
|
private static byte[] qualifierAname = Bytes.toBytes("qualifierA");
|
||||||
private static byte[] qualifierBname = Bytes.toBytes("qualifierB");
|
private static byte[] qualifierBname = Bytes.toBytes("qualifierB");
|
||||||
private static byte[] valueAname = Bytes.toBytes("valueA");
|
private static byte[] valueAname = Bytes.toBytes("valueA");
|
||||||
private static byte[] valueBname = Bytes.toBytes("valueB");
|
private static byte[] valueBname = Bytes.toBytes("valueB");
|
||||||
private static HColumnDescriptor[] families = new HColumnDescriptor[] {
|
private static HColumnDescriptor[] families = new HColumnDescriptor[] {
|
||||||
new HColumnDescriptor(familyAname).setMaxVersions(3),
|
new HColumnDescriptor(familyAname).setMaxVersions(3),
|
||||||
new HColumnDescriptor(familyBname).setMaxVersions(2) };
|
new HColumnDescriptor(familyBname).setMaxVersions(2) };
|
||||||
|
|
||||||
private final static String TOPSECRET = "topsecret";
|
private final static String TOPSECRET = "topsecret";
|
||||||
private final static String PUBLIC = "public";
|
private final static String PUBLIC = "public";
|
||||||
private final static String PRIVATE = "private";
|
private final static String PRIVATE = "private";
|
||||||
private final static String CONFIDENTIAL = "confidential";
|
private final static String CONFIDENTIAL = "confidential";
|
||||||
private final static String SECRET = "secret";
|
private final static String SECRET = "secret";
|
||||||
private static User SUPERUSER;
|
private static User SUPERUSER;
|
||||||
|
|
||||||
private static Configuration conf;
|
private static Configuration conf;
|
||||||
|
|
||||||
public void assertTColumnValuesEqual(List<TColumnValue> columnValuesA,
|
public void assertTColumnValuesEqual(List<TColumnValue> columnValuesA,
|
||||||
List<TColumnValue> columnValuesB) {
|
List<TColumnValue> columnValuesB) {
|
||||||
assertEquals(columnValuesA.size(), columnValuesB.size());
|
assertEquals(columnValuesA.size(), columnValuesB.size());
|
||||||
Comparator<TColumnValue> comparator = new Comparator<TColumnValue>() {
|
Comparator<TColumnValue> comparator = new Comparator<TColumnValue>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(TColumnValue o1, TColumnValue o2) {
|
public int compare(TColumnValue o1, TColumnValue o2) {
|
||||||
return Bytes.compareTo(Bytes.add(o1.getFamily(), o1.getQualifier()),
|
return Bytes.compareTo(Bytes.add(o1.getFamily(), o1.getQualifier()),
|
||||||
Bytes.add(o2.getFamily(), o2.getQualifier()));
|
Bytes.add(o2.getFamily(), o2.getQualifier()));
|
||||||
}
|
|
||||||
};
|
|
||||||
Collections.sort(columnValuesA, comparator);
|
|
||||||
Collections.sort(columnValuesB, comparator);
|
|
||||||
|
|
||||||
for (int i = 0; i < columnValuesA.size(); i++) {
|
|
||||||
TColumnValue a = columnValuesA.get(i);
|
|
||||||
TColumnValue b = columnValuesB.get(i);
|
|
||||||
assertArrayEquals(a.getFamily(), b.getFamily());
|
|
||||||
assertArrayEquals(a.getQualifier(), b.getQualifier());
|
|
||||||
assertArrayEquals(a.getValue(), b.getValue());
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
Collections.sort(columnValuesA, comparator);
|
||||||
|
Collections.sort(columnValuesB, comparator);
|
||||||
|
|
||||||
@BeforeClass
|
for (int i = 0; i < columnValuesA.size(); i++) {
|
||||||
public static void beforeClass() throws Exception {
|
TColumnValue a = columnValuesA.get(i);
|
||||||
SUPERUSER = User.createUserForTesting(conf, "admin",
|
TColumnValue b = columnValuesB.get(i);
|
||||||
new String[] { "supergroup" });
|
assertArrayEquals(a.getFamily(), b.getFamily());
|
||||||
conf = UTIL.getConfiguration();
|
assertArrayEquals(a.getQualifier(), b.getQualifier());
|
||||||
conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS,
|
assertArrayEquals(a.getValue(), b.getValue());
|
||||||
SimpleScanLabelGenerator.class, ScanLabelGenerator.class);
|
|
||||||
conf.set("hbase.superuser", SUPERUSER.getShortName());
|
|
||||||
VisibilityTestUtil.enableVisiblityLabels(conf);
|
|
||||||
UTIL.startMiniCluster(1);
|
|
||||||
// Wait for the labels table to become available
|
|
||||||
UTIL.waitTableEnabled(VisibilityConstants.LABELS_TABLE_NAME.getName(), 50000);
|
|
||||||
createLabels();
|
|
||||||
Admin admin = UTIL.getAdmin();
|
|
||||||
HTableDescriptor tableDescriptor = new HTableDescriptor(
|
|
||||||
TableName.valueOf(tableAname));
|
|
||||||
for (HColumnDescriptor family : families) {
|
|
||||||
tableDescriptor.addFamily(family);
|
|
||||||
}
|
|
||||||
admin.createTable(tableDescriptor);
|
|
||||||
admin.close();
|
|
||||||
setAuths();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void createLabels() throws IOException, InterruptedException {
|
|
||||||
PrivilegedExceptionAction<VisibilityLabelsResponse> action =
|
|
||||||
new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
|
|
||||||
public VisibilityLabelsResponse run() throws Exception {
|
|
||||||
String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, PUBLIC, TOPSECRET };
|
|
||||||
try (Connection conn = ConnectionFactory.createConnection(conf)) {
|
|
||||||
VisibilityClient.addLabels(conn, labels);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
throw new IOException(t);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
SUPERUSER.runAs(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setAuths() throws IOException {
|
|
||||||
String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, PUBLIC, TOPSECRET };
|
|
||||||
try {
|
|
||||||
VisibilityClient.setAuths(UTIL.getConnection(), labels, User.getCurrent().getShortName());
|
|
||||||
} catch (Throwable t) {
|
|
||||||
throw new IOException(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterClass() throws Exception {
|
|
||||||
UTIL.shutdownMiniCluster();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setup() throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private ThriftHBaseServiceHandler createHandler() throws IOException {
|
|
||||||
return new ThriftHBaseServiceHandler(conf, UserProvider.instantiate(conf));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testScanWithVisibilityLabels() throws Exception {
|
|
||||||
ThriftHBaseServiceHandler handler = createHandler();
|
|
||||||
ByteBuffer table = wrap(tableAname);
|
|
||||||
|
|
||||||
// insert data
|
|
||||||
TColumnValue columnValue = new TColumnValue(wrap(familyAname),
|
|
||||||
wrap(qualifierAname), wrap(valueAname));
|
|
||||||
List<TColumnValue> columnValues = new ArrayList<>(1);
|
|
||||||
columnValues.add(columnValue);
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
TPut put = new TPut(wrap(("testScan" + i).getBytes()), columnValues);
|
|
||||||
if (i == 5) {
|
|
||||||
put.setCellVisibility(new TCellVisibility().setExpression(PUBLIC));
|
|
||||||
} else {
|
|
||||||
put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET
|
|
||||||
+ "|" + CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
|
|
||||||
}
|
|
||||||
handler.put(table, put);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create scan instance
|
|
||||||
TScan scan = new TScan();
|
|
||||||
List<TColumn> columns = new ArrayList<>(1);
|
|
||||||
TColumn column = new TColumn();
|
|
||||||
column.setFamily(familyAname);
|
|
||||||
column.setQualifier(qualifierAname);
|
|
||||||
columns.add(column);
|
|
||||||
scan.setColumns(columns);
|
|
||||||
scan.setStartRow("testScan".getBytes());
|
|
||||||
scan.setStopRow("testScan\uffff".getBytes());
|
|
||||||
|
|
||||||
TAuthorization tauth = new TAuthorization();
|
|
||||||
List<String> labels = new ArrayList<>(2);
|
|
||||||
labels.add(SECRET);
|
|
||||||
labels.add(PRIVATE);
|
|
||||||
tauth.setLabels(labels);
|
|
||||||
scan.setAuthorizations(tauth);
|
|
||||||
// get scanner and rows
|
|
||||||
int scanId = handler.openScanner(table, scan);
|
|
||||||
List<TResult> results = handler.getScannerRows(scanId, 10);
|
|
||||||
assertEquals(9, results.size());
|
|
||||||
Assert.assertFalse(Bytes.equals(results.get(5).getRow(),
|
|
||||||
("testScan" + 5).getBytes()));
|
|
||||||
for (int i = 0; i < 9; i++) {
|
|
||||||
if (i < 5) {
|
|
||||||
assertArrayEquals(("testScan" + i).getBytes(), results.get(i).getRow());
|
|
||||||
} else if (i == 5) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
assertArrayEquals(("testScan" + (i + 1)).getBytes(), results.get(i)
|
|
||||||
.getRow());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check that we are at the end of the scan
|
|
||||||
results = handler.getScannerRows(scanId, 9);
|
|
||||||
assertEquals(0, results.size());
|
|
||||||
|
|
||||||
// close scanner and check that it was indeed closed
|
|
||||||
handler.closeScanner(scanId);
|
|
||||||
try {
|
|
||||||
handler.getScannerRows(scanId, 9);
|
|
||||||
fail("Scanner id should be invalid");
|
|
||||||
} catch (TIllegalArgument e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetScannerResultsWithAuthorizations() throws Exception {
|
|
||||||
ThriftHBaseServiceHandler handler = createHandler();
|
|
||||||
ByteBuffer table = wrap(tableAname);
|
|
||||||
|
|
||||||
// insert data
|
|
||||||
TColumnValue columnValue = new TColumnValue(wrap(familyAname),
|
|
||||||
wrap(qualifierAname), wrap(valueAname));
|
|
||||||
List<TColumnValue> columnValues = new ArrayList<>(1);
|
|
||||||
columnValues.add(columnValue);
|
|
||||||
for (int i = 0; i < 20; i++) {
|
|
||||||
TPut put = new TPut(
|
|
||||||
wrap(("testGetScannerResults" + pad(i, (byte) 2)).getBytes()),
|
|
||||||
columnValues);
|
|
||||||
if (i == 3) {
|
|
||||||
put.setCellVisibility(new TCellVisibility().setExpression(PUBLIC));
|
|
||||||
} else {
|
|
||||||
put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET
|
|
||||||
+ "|" + CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
|
|
||||||
}
|
|
||||||
handler.put(table, put);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create scan instance
|
|
||||||
TScan scan = new TScan();
|
|
||||||
List<TColumn> columns = new ArrayList<>(1);
|
|
||||||
TColumn column = new TColumn();
|
|
||||||
column.setFamily(familyAname);
|
|
||||||
column.setQualifier(qualifierAname);
|
|
||||||
columns.add(column);
|
|
||||||
scan.setColumns(columns);
|
|
||||||
scan.setStartRow("testGetScannerResults".getBytes());
|
|
||||||
|
|
||||||
// get 5 rows and check the returned results
|
|
||||||
scan.setStopRow("testGetScannerResults05".getBytes());
|
|
||||||
TAuthorization tauth = new TAuthorization();
|
|
||||||
List<String> labels = new ArrayList<>(2);
|
|
||||||
labels.add(SECRET);
|
|
||||||
labels.add(PRIVATE);
|
|
||||||
tauth.setLabels(labels);
|
|
||||||
scan.setAuthorizations(tauth);
|
|
||||||
List<TResult> results = handler.getScannerResults(table, scan, 5);
|
|
||||||
assertEquals(4, results.size());
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
if (i < 3) {
|
|
||||||
assertArrayEquals(
|
|
||||||
("testGetScannerResults" + pad(i, (byte) 2)).getBytes(),
|
|
||||||
results.get(i).getRow());
|
|
||||||
} else if (i == 3) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
assertArrayEquals(
|
|
||||||
("testGetScannerResults" + pad(i + 1, (byte) 2)).getBytes(), results
|
|
||||||
.get(i).getRow());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetsWithLabels() throws Exception {
|
|
||||||
ThriftHBaseServiceHandler handler = createHandler();
|
|
||||||
byte[] rowName = "testPutGet".getBytes();
|
|
||||||
ByteBuffer table = wrap(tableAname);
|
|
||||||
|
|
||||||
List<TColumnValue> columnValues = new ArrayList<>(2);
|
|
||||||
columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
|
|
||||||
wrap(valueAname)));
|
|
||||||
columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname),
|
|
||||||
wrap(valueBname)));
|
|
||||||
TPut put = new TPut(wrap(rowName), columnValues);
|
|
||||||
|
|
||||||
put.setColumnValues(columnValues);
|
|
||||||
put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET + "|"
|
|
||||||
+ CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
|
|
||||||
handler.put(table, put);
|
|
||||||
TGet get = new TGet(wrap(rowName));
|
|
||||||
TAuthorization tauth = new TAuthorization();
|
|
||||||
List<String> labels = new ArrayList<>(2);
|
|
||||||
labels.add(SECRET);
|
|
||||||
labels.add(PRIVATE);
|
|
||||||
tauth.setLabels(labels);
|
|
||||||
get.setAuthorizations(tauth);
|
|
||||||
TResult result = handler.get(table, get);
|
|
||||||
assertArrayEquals(rowName, result.getRow());
|
|
||||||
List<TColumnValue> returnedColumnValues = result.getColumnValues();
|
|
||||||
assertTColumnValuesEqual(columnValues, returnedColumnValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIncrementWithTags() throws Exception {
|
|
||||||
ThriftHBaseServiceHandler handler = createHandler();
|
|
||||||
byte[] rowName = "testIncrementWithTags".getBytes();
|
|
||||||
ByteBuffer table = wrap(tableAname);
|
|
||||||
|
|
||||||
List<TColumnValue> columnValues = new ArrayList<>(1);
|
|
||||||
columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
|
|
||||||
wrap(Bytes.toBytes(1L))));
|
|
||||||
TPut put = new TPut(wrap(rowName), columnValues);
|
|
||||||
put.setColumnValues(columnValues);
|
|
||||||
put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
|
|
||||||
handler.put(table, put);
|
|
||||||
|
|
||||||
List<TColumnIncrement> incrementColumns = new ArrayList<>(1);
|
|
||||||
incrementColumns.add(new TColumnIncrement(wrap(familyAname),
|
|
||||||
wrap(qualifierAname)));
|
|
||||||
TIncrement increment = new TIncrement(wrap(rowName), incrementColumns);
|
|
||||||
increment.setCellVisibility(new TCellVisibility().setExpression(SECRET));
|
|
||||||
handler.increment(table, increment);
|
|
||||||
|
|
||||||
TGet get = new TGet(wrap(rowName));
|
|
||||||
TAuthorization tauth = new TAuthorization();
|
|
||||||
List<String> labels = new ArrayList<>(1);
|
|
||||||
labels.add(SECRET);
|
|
||||||
tauth.setLabels(labels);
|
|
||||||
get.setAuthorizations(tauth);
|
|
||||||
TResult result = handler.get(table, get);
|
|
||||||
|
|
||||||
assertArrayEquals(rowName, result.getRow());
|
|
||||||
assertEquals(1, result.getColumnValuesSize());
|
|
||||||
TColumnValue columnValue = result.getColumnValues().get(0);
|
|
||||||
assertArrayEquals(Bytes.toBytes(2L), columnValue.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIncrementWithTagsWithNotMatchLabels() throws Exception {
|
|
||||||
ThriftHBaseServiceHandler handler = createHandler();
|
|
||||||
byte[] rowName = "testIncrementWithTagsWithNotMatchLabels".getBytes();
|
|
||||||
ByteBuffer table = wrap(tableAname);
|
|
||||||
|
|
||||||
List<TColumnValue> columnValues = new ArrayList<>(1);
|
|
||||||
columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
|
|
||||||
wrap(Bytes.toBytes(1L))));
|
|
||||||
TPut put = new TPut(wrap(rowName), columnValues);
|
|
||||||
put.setColumnValues(columnValues);
|
|
||||||
put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
|
|
||||||
handler.put(table, put);
|
|
||||||
|
|
||||||
List<TColumnIncrement> incrementColumns = new ArrayList<>(1);
|
|
||||||
incrementColumns.add(new TColumnIncrement(wrap(familyAname),
|
|
||||||
wrap(qualifierAname)));
|
|
||||||
TIncrement increment = new TIncrement(wrap(rowName), incrementColumns);
|
|
||||||
increment.setCellVisibility(new TCellVisibility().setExpression(SECRET));
|
|
||||||
handler.increment(table, increment);
|
|
||||||
|
|
||||||
TGet get = new TGet(wrap(rowName));
|
|
||||||
TAuthorization tauth = new TAuthorization();
|
|
||||||
List<String> labels = new ArrayList<>(1);
|
|
||||||
labels.add(PUBLIC);
|
|
||||||
tauth.setLabels(labels);
|
|
||||||
get.setAuthorizations(tauth);
|
|
||||||
TResult result = handler.get(table, get);
|
|
||||||
assertNull(result.getRow());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAppend() throws Exception {
|
|
||||||
ThriftHBaseServiceHandler handler = createHandler();
|
|
||||||
byte[] rowName = "testAppend".getBytes();
|
|
||||||
ByteBuffer table = wrap(tableAname);
|
|
||||||
byte[] v1 = Bytes.toBytes(1L);
|
|
||||||
byte[] v2 = Bytes.toBytes(5L);
|
|
||||||
List<TColumnValue> columnValues = new ArrayList<>(1);
|
|
||||||
columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
|
|
||||||
wrap(Bytes.toBytes(1L))));
|
|
||||||
TPut put = new TPut(wrap(rowName), columnValues);
|
|
||||||
put.setColumnValues(columnValues);
|
|
||||||
put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
|
|
||||||
handler.put(table, put);
|
|
||||||
|
|
||||||
List<TColumnValue> appendColumns = new ArrayList<>(1);
|
|
||||||
appendColumns.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
|
|
||||||
wrap(v2)));
|
|
||||||
TAppend append = new TAppend(wrap(rowName), appendColumns);
|
|
||||||
append.setCellVisibility(new TCellVisibility().setExpression(SECRET));
|
|
||||||
handler.append(table, append);
|
|
||||||
|
|
||||||
TGet get = new TGet(wrap(rowName));
|
|
||||||
TAuthorization tauth = new TAuthorization();
|
|
||||||
List<String> labels = new ArrayList<>(1);
|
|
||||||
labels.add(SECRET);
|
|
||||||
tauth.setLabels(labels);
|
|
||||||
get.setAuthorizations(tauth);
|
|
||||||
TResult result = handler.get(table, get);
|
|
||||||
|
|
||||||
assertArrayEquals(rowName, result.getRow());
|
|
||||||
assertEquals(1, result.getColumnValuesSize());
|
|
||||||
TColumnValue columnValue = result.getColumnValues().get(0);
|
|
||||||
assertArrayEquals(Bytes.add(v1, v2), columnValue.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Padding numbers to make comparison of sort order easier in a for loop
|
|
||||||
*
|
|
||||||
* @param n
|
|
||||||
* The number to pad.
|
|
||||||
* @param pad
|
|
||||||
* The length to pad up to.
|
|
||||||
* @return The padded number as a string.
|
|
||||||
*/
|
|
||||||
private String pad(int n, byte pad) {
|
|
||||||
String res = Integer.toString(n);
|
|
||||||
while (res.length() < pad) {
|
|
||||||
res = "0" + res;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() throws Exception {
|
||||||
|
SUPERUSER = User.createUserForTesting(conf, "admin",
|
||||||
|
new String[] { "supergroup" });
|
||||||
|
conf = UTIL.getConfiguration();
|
||||||
|
conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS,
|
||||||
|
SimpleScanLabelGenerator.class, ScanLabelGenerator.class);
|
||||||
|
conf.set("hbase.superuser", SUPERUSER.getShortName());
|
||||||
|
conf.set("hbase.coprocessor.master.classes",
|
||||||
|
VisibilityController.class.getName());
|
||||||
|
conf.set("hbase.coprocessor.region.classes",
|
||||||
|
VisibilityController.class.getName());
|
||||||
|
conf.setInt("hfile.format.version", 3);
|
||||||
|
UTIL.startMiniCluster(1);
|
||||||
|
// Wait for the labels table to become available
|
||||||
|
UTIL.waitTableEnabled(VisibilityConstants.LABELS_TABLE_NAME.getName(), 50000);
|
||||||
|
createLabels();
|
||||||
|
Admin admin = UTIL.getAdmin();
|
||||||
|
HTableDescriptor tableDescriptor = new HTableDescriptor(
|
||||||
|
TableName.valueOf(tableAname));
|
||||||
|
for (HColumnDescriptor family : families) {
|
||||||
|
tableDescriptor.addFamily(family);
|
||||||
|
}
|
||||||
|
admin.createTable(tableDescriptor);
|
||||||
|
admin.close();
|
||||||
|
setAuths();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createLabels() throws IOException, InterruptedException {
|
||||||
|
PrivilegedExceptionAction<VisibilityLabelsResponse> action =
|
||||||
|
new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
|
||||||
|
public VisibilityLabelsResponse run() throws Exception {
|
||||||
|
String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, PUBLIC, TOPSECRET };
|
||||||
|
try (Connection conn = ConnectionFactory.createConnection(conf)) {
|
||||||
|
VisibilityClient.addLabels(conn, labels);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new IOException(t);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SUPERUSER.runAs(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setAuths() throws IOException {
|
||||||
|
String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, PUBLIC, TOPSECRET };
|
||||||
|
try {
|
||||||
|
VisibilityClient.setAuths(UTIL.getConnection(), labels, User.getCurrent().getShortName());
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new IOException(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClass() throws Exception {
|
||||||
|
UTIL.shutdownMiniCluster();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private ThriftHBaseServiceHandler createHandler() throws IOException {
|
||||||
|
return new ThriftHBaseServiceHandler(conf, UserProvider.instantiate(conf));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testScanWithVisibilityLabels() throws Exception {
|
||||||
|
ThriftHBaseServiceHandler handler = createHandler();
|
||||||
|
ByteBuffer table = wrap(tableAname);
|
||||||
|
|
||||||
|
// insert data
|
||||||
|
TColumnValue columnValue = new TColumnValue(wrap(familyAname),
|
||||||
|
wrap(qualifierAname), wrap(valueAname));
|
||||||
|
List<TColumnValue> columnValues = new ArrayList<>(1);
|
||||||
|
columnValues.add(columnValue);
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
TPut put = new TPut(wrap(("testScan" + i).getBytes()), columnValues);
|
||||||
|
if (i == 5) {
|
||||||
|
put.setCellVisibility(new TCellVisibility().setExpression(PUBLIC));
|
||||||
|
} else {
|
||||||
|
put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET
|
||||||
|
+ "|" + CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
|
||||||
|
}
|
||||||
|
handler.put(table, put);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create scan instance
|
||||||
|
TScan scan = new TScan();
|
||||||
|
List<TColumn> columns = new ArrayList<>(1);
|
||||||
|
TColumn column = new TColumn();
|
||||||
|
column.setFamily(familyAname);
|
||||||
|
column.setQualifier(qualifierAname);
|
||||||
|
columns.add(column);
|
||||||
|
scan.setColumns(columns);
|
||||||
|
scan.setStartRow("testScan".getBytes());
|
||||||
|
scan.setStopRow("testScan\uffff".getBytes());
|
||||||
|
|
||||||
|
TAuthorization tauth = new TAuthorization();
|
||||||
|
List<String> labels = new ArrayList<>(2);
|
||||||
|
labels.add(SECRET);
|
||||||
|
labels.add(PRIVATE);
|
||||||
|
tauth.setLabels(labels);
|
||||||
|
scan.setAuthorizations(tauth);
|
||||||
|
// get scanner and rows
|
||||||
|
int scanId = handler.openScanner(table, scan);
|
||||||
|
List<TResult> results = handler.getScannerRows(scanId, 10);
|
||||||
|
assertEquals(9, results.size());
|
||||||
|
Assert.assertFalse(Bytes.equals(results.get(5).getRow(),
|
||||||
|
("testScan" + 5).getBytes()));
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
if (i < 5) {
|
||||||
|
assertArrayEquals(("testScan" + i).getBytes(), results.get(i).getRow());
|
||||||
|
} else if (i == 5) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
assertArrayEquals(("testScan" + (i + 1)).getBytes(), results.get(i)
|
||||||
|
.getRow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that we are at the end of the scan
|
||||||
|
results = handler.getScannerRows(scanId, 9);
|
||||||
|
assertEquals(0, results.size());
|
||||||
|
|
||||||
|
// close scanner and check that it was indeed closed
|
||||||
|
handler.closeScanner(scanId);
|
||||||
|
try {
|
||||||
|
handler.getScannerRows(scanId, 9);
|
||||||
|
fail("Scanner id should be invalid");
|
||||||
|
} catch (TIllegalArgument e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetScannerResultsWithAuthorizations() throws Exception {
|
||||||
|
ThriftHBaseServiceHandler handler = createHandler();
|
||||||
|
ByteBuffer table = wrap(tableAname);
|
||||||
|
|
||||||
|
// insert data
|
||||||
|
TColumnValue columnValue = new TColumnValue(wrap(familyAname),
|
||||||
|
wrap(qualifierAname), wrap(valueAname));
|
||||||
|
List<TColumnValue> columnValues = new ArrayList<>(1);
|
||||||
|
columnValues.add(columnValue);
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
TPut put = new TPut(
|
||||||
|
wrap(("testGetScannerResults" + pad(i, (byte) 2)).getBytes()),
|
||||||
|
columnValues);
|
||||||
|
if (i == 3) {
|
||||||
|
put.setCellVisibility(new TCellVisibility().setExpression(PUBLIC));
|
||||||
|
} else {
|
||||||
|
put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET
|
||||||
|
+ "|" + CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
|
||||||
|
}
|
||||||
|
handler.put(table, put);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create scan instance
|
||||||
|
TScan scan = new TScan();
|
||||||
|
List<TColumn> columns = new ArrayList<>(1);
|
||||||
|
TColumn column = new TColumn();
|
||||||
|
column.setFamily(familyAname);
|
||||||
|
column.setQualifier(qualifierAname);
|
||||||
|
columns.add(column);
|
||||||
|
scan.setColumns(columns);
|
||||||
|
scan.setStartRow("testGetScannerResults".getBytes());
|
||||||
|
|
||||||
|
// get 5 rows and check the returned results
|
||||||
|
scan.setStopRow("testGetScannerResults05".getBytes());
|
||||||
|
TAuthorization tauth = new TAuthorization();
|
||||||
|
List<String> labels = new ArrayList<>(2);
|
||||||
|
labels.add(SECRET);
|
||||||
|
labels.add(PRIVATE);
|
||||||
|
tauth.setLabels(labels);
|
||||||
|
scan.setAuthorizations(tauth);
|
||||||
|
List<TResult> results = handler.getScannerResults(table, scan, 5);
|
||||||
|
assertEquals(4, results.size());
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (i < 3) {
|
||||||
|
assertArrayEquals(
|
||||||
|
("testGetScannerResults" + pad(i, (byte) 2)).getBytes(),
|
||||||
|
results.get(i).getRow());
|
||||||
|
} else if (i == 3) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
assertArrayEquals(
|
||||||
|
("testGetScannerResults" + pad(i + 1, (byte) 2)).getBytes(), results
|
||||||
|
.get(i).getRow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetsWithLabels() throws Exception {
|
||||||
|
ThriftHBaseServiceHandler handler = createHandler();
|
||||||
|
byte[] rowName = "testPutGet".getBytes();
|
||||||
|
ByteBuffer table = wrap(tableAname);
|
||||||
|
|
||||||
|
List<TColumnValue> columnValues = new ArrayList<>(2);
|
||||||
|
columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
|
||||||
|
wrap(valueAname)));
|
||||||
|
columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname),
|
||||||
|
wrap(valueBname)));
|
||||||
|
TPut put = new TPut(wrap(rowName), columnValues);
|
||||||
|
|
||||||
|
put.setColumnValues(columnValues);
|
||||||
|
put.setCellVisibility(new TCellVisibility().setExpression("(" + SECRET + "|"
|
||||||
|
+ CONFIDENTIAL + ")" + "&" + "!" + TOPSECRET));
|
||||||
|
handler.put(table, put);
|
||||||
|
TGet get = new TGet(wrap(rowName));
|
||||||
|
TAuthorization tauth = new TAuthorization();
|
||||||
|
List<String> labels = new ArrayList<>(2);
|
||||||
|
labels.add(SECRET);
|
||||||
|
labels.add(PRIVATE);
|
||||||
|
tauth.setLabels(labels);
|
||||||
|
get.setAuthorizations(tauth);
|
||||||
|
TResult result = handler.get(table, get);
|
||||||
|
assertArrayEquals(rowName, result.getRow());
|
||||||
|
List<TColumnValue> returnedColumnValues = result.getColumnValues();
|
||||||
|
assertTColumnValuesEqual(columnValues, returnedColumnValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIncrementWithTags() throws Exception {
|
||||||
|
ThriftHBaseServiceHandler handler = createHandler();
|
||||||
|
byte[] rowName = "testIncrementWithTags".getBytes();
|
||||||
|
ByteBuffer table = wrap(tableAname);
|
||||||
|
|
||||||
|
List<TColumnValue> columnValues = new ArrayList<>(1);
|
||||||
|
columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
|
||||||
|
wrap(Bytes.toBytes(1L))));
|
||||||
|
TPut put = new TPut(wrap(rowName), columnValues);
|
||||||
|
put.setColumnValues(columnValues);
|
||||||
|
put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
|
||||||
|
handler.put(table, put);
|
||||||
|
|
||||||
|
List<TColumnIncrement> incrementColumns = new ArrayList<>(1);
|
||||||
|
incrementColumns.add(new TColumnIncrement(wrap(familyAname),
|
||||||
|
wrap(qualifierAname)));
|
||||||
|
TIncrement increment = new TIncrement(wrap(rowName), incrementColumns);
|
||||||
|
increment.setCellVisibility(new TCellVisibility().setExpression(SECRET));
|
||||||
|
handler.increment(table, increment);
|
||||||
|
|
||||||
|
TGet get = new TGet(wrap(rowName));
|
||||||
|
TAuthorization tauth = new TAuthorization();
|
||||||
|
List<String> labels = new ArrayList<>(1);
|
||||||
|
labels.add(SECRET);
|
||||||
|
tauth.setLabels(labels);
|
||||||
|
get.setAuthorizations(tauth);
|
||||||
|
TResult result = handler.get(table, get);
|
||||||
|
|
||||||
|
assertArrayEquals(rowName, result.getRow());
|
||||||
|
assertEquals(1, result.getColumnValuesSize());
|
||||||
|
TColumnValue columnValue = result.getColumnValues().get(0);
|
||||||
|
assertArrayEquals(Bytes.toBytes(2L), columnValue.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIncrementWithTagsWithNotMatchLabels() throws Exception {
|
||||||
|
ThriftHBaseServiceHandler handler = createHandler();
|
||||||
|
byte[] rowName = "testIncrementWithTagsWithNotMatchLabels".getBytes();
|
||||||
|
ByteBuffer table = wrap(tableAname);
|
||||||
|
|
||||||
|
List<TColumnValue> columnValues = new ArrayList<>(1);
|
||||||
|
columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
|
||||||
|
wrap(Bytes.toBytes(1L))));
|
||||||
|
TPut put = new TPut(wrap(rowName), columnValues);
|
||||||
|
put.setColumnValues(columnValues);
|
||||||
|
put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
|
||||||
|
handler.put(table, put);
|
||||||
|
|
||||||
|
List<TColumnIncrement> incrementColumns = new ArrayList<>(1);
|
||||||
|
incrementColumns.add(new TColumnIncrement(wrap(familyAname),
|
||||||
|
wrap(qualifierAname)));
|
||||||
|
TIncrement increment = new TIncrement(wrap(rowName), incrementColumns);
|
||||||
|
increment.setCellVisibility(new TCellVisibility().setExpression(SECRET));
|
||||||
|
handler.increment(table, increment);
|
||||||
|
|
||||||
|
TGet get = new TGet(wrap(rowName));
|
||||||
|
TAuthorization tauth = new TAuthorization();
|
||||||
|
List<String> labels = new ArrayList<>(1);
|
||||||
|
labels.add(PUBLIC);
|
||||||
|
tauth.setLabels(labels);
|
||||||
|
get.setAuthorizations(tauth);
|
||||||
|
TResult result = handler.get(table, get);
|
||||||
|
assertNull(result.getRow());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAppend() throws Exception {
|
||||||
|
ThriftHBaseServiceHandler handler = createHandler();
|
||||||
|
byte[] rowName = "testAppend".getBytes();
|
||||||
|
ByteBuffer table = wrap(tableAname);
|
||||||
|
byte[] v1 = Bytes.toBytes(1L);
|
||||||
|
byte[] v2 = Bytes.toBytes(5L);
|
||||||
|
List<TColumnValue> columnValues = new ArrayList<>(1);
|
||||||
|
columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
|
||||||
|
wrap(Bytes.toBytes(1L))));
|
||||||
|
TPut put = new TPut(wrap(rowName), columnValues);
|
||||||
|
put.setColumnValues(columnValues);
|
||||||
|
put.setCellVisibility(new TCellVisibility().setExpression(PRIVATE));
|
||||||
|
handler.put(table, put);
|
||||||
|
|
||||||
|
List<TColumnValue> appendColumns = new ArrayList<>(1);
|
||||||
|
appendColumns.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname),
|
||||||
|
wrap(v2)));
|
||||||
|
TAppend append = new TAppend(wrap(rowName), appendColumns);
|
||||||
|
append.setCellVisibility(new TCellVisibility().setExpression(SECRET));
|
||||||
|
handler.append(table, append);
|
||||||
|
|
||||||
|
TGet get = new TGet(wrap(rowName));
|
||||||
|
TAuthorization tauth = new TAuthorization();
|
||||||
|
List<String> labels = new ArrayList<>(1);
|
||||||
|
labels.add(SECRET);
|
||||||
|
tauth.setLabels(labels);
|
||||||
|
get.setAuthorizations(tauth);
|
||||||
|
TResult result = handler.get(table, get);
|
||||||
|
|
||||||
|
assertArrayEquals(rowName, result.getRow());
|
||||||
|
assertEquals(1, result.getColumnValuesSize());
|
||||||
|
TColumnValue columnValue = result.getColumnValues().get(0);
|
||||||
|
assertArrayEquals(Bytes.add(v1, v2), columnValue.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Padding numbers to make comparison of sort order easier in a for loop
|
||||||
|
*
|
||||||
|
* @param n
|
||||||
|
* The number to pad.
|
||||||
|
* @param pad
|
||||||
|
* The length to pad up to.
|
||||||
|
* @return The padded number as a string.
|
||||||
|
*/
|
||||||
|
private String pad(int n, byte pad) {
|
||||||
|
String res = Integer.toString(n);
|
||||||
|
while (res.length() < pad)
|
||||||
|
res = "0" + res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -164,17 +164,6 @@ In case the table goes out of date, the unit tests which check for accuracy of p
|
||||||
| | mergeRegions | superuser\|global(A)
|
| | mergeRegions | superuser\|global(A)
|
||||||
| | rollWALWriterRequest | superuser\|global(A)
|
| | rollWALWriterRequest | superuser\|global(A)
|
||||||
| | replicateLogEntries | superuser\|global(W)
|
| | replicateLogEntries | superuser\|global(W)
|
||||||
|RSGroup |addRSGroup |superuser\|global(A)
|
|
||||||
| |balanceRSGroup |superuser\|global(A)
|
|
||||||
| |getRSGroupInfo |superuser\|global(A)
|
|
||||||
| |getRSGroupInfoOfTable|superuser\|global(A)
|
|
||||||
| |getRSGroupOfServer |superuser\|global(A)
|
|
||||||
| |listRSGroups |superuser\|global(A)
|
|
||||||
| |moveServers |superuser\|global(A)
|
|
||||||
| |moveServersAndTables |superuser\|global(A)
|
|
||||||
| |moveTables |superuser\|global(A)
|
|
||||||
| |removeRSGroup |superuser\|global(A)
|
|
||||||
| |removeServers |superuser\|global(A)
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
:numbered:
|
:numbered:
|
||||||
|
|
|
@ -2703,18 +2703,6 @@ Viewing the Master log will give you insight on rsgroup operation.
|
||||||
|
|
||||||
If it appears stuck, restart the Master process.
|
If it appears stuck, restart the Master process.
|
||||||
|
|
||||||
=== ACL
|
|
||||||
To enable ACL, add the following to your hbase-site.xml and restart your Master:
|
|
||||||
|
|
||||||
[source,xml]
|
|
||||||
----
|
|
||||||
<property>
|
|
||||||
<name>hbase.security.authorization</name>
|
|
||||||
<value>true</value>
|
|
||||||
<property>
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[normalizer]]
|
[[normalizer]]
|
||||||
== Region Normalizer
|
== Region Normalizer
|
||||||
|
|
|
@ -806,10 +806,6 @@ For an example of using both together, see <<security.example.config>>.
|
||||||
+
|
+
|
||||||
[source,xml]
|
[source,xml]
|
||||||
----
|
----
|
||||||
<property>
|
|
||||||
<name>hbase.security.authorization</name>
|
|
||||||
<value>true</value>
|
|
||||||
</property>
|
|
||||||
<property>
|
<property>
|
||||||
<name>hbase.coprocessor.region.classes</name>
|
<name>hbase.coprocessor.region.classes</name>
|
||||||
<value>org.apache.hadoop.hbase.security.access.AccessController, org.apache.hadoop.hbase.security.token.TokenProvider</value>
|
<value>org.apache.hadoop.hbase.security.access.AccessController, org.apache.hadoop.hbase.security.token.TokenProvider</value>
|
||||||
|
@ -1190,10 +1186,6 @@ NOTE: Visibility labels are not currently applied for superusers.
|
||||||
+
|
+
|
||||||
[source,xml]
|
[source,xml]
|
||||||
----
|
----
|
||||||
<property>
|
|
||||||
<name>hbase.security.authorization</name>
|
|
||||||
<value>true</value>
|
|
||||||
</property>
|
|
||||||
<property>
|
<property>
|
||||||
<name>hbase.coprocessor.region.classes</name>
|
<name>hbase.coprocessor.region.classes</name>
|
||||||
<value>org.apache.hadoop.hbase.security.visibility.VisibilityController</value>
|
<value>org.apache.hadoop.hbase.security.visibility.VisibilityController</value>
|
||||||
|
@ -1461,10 +1453,6 @@ As mentioned in the above sections, the interface `VisibilityLabelService` could
|
||||||
|
|
||||||
[source,xml]
|
[source,xml]
|
||||||
----
|
----
|
||||||
<property>
|
|
||||||
<name>hbase.security.authorization</name>
|
|
||||||
<value>true</value>
|
|
||||||
</property>
|
|
||||||
<property>
|
<property>
|
||||||
<name>hbase.coprocessor.regionserver.classes</name>
|
<name>hbase.coprocessor.regionserver.classes</name>
|
||||||
<value>org.apache.hadoop.hbase.security.visibility.VisibilityController$VisibilityReplication</value>
|
<value>org.apache.hadoop.hbase.security.visibility.VisibilityController$VisibilityReplication</value>
|
||||||
|
@ -1683,10 +1671,6 @@ To enable secure bulk load, add the following properties to _hbase-site.xml_.
|
||||||
|
|
||||||
[source,xml]
|
[source,xml]
|
||||||
----
|
----
|
||||||
<property>
|
|
||||||
<name>hbase.security.authorization</name>
|
|
||||||
<value>true</value>
|
|
||||||
</property>
|
|
||||||
<property>
|
<property>
|
||||||
<name>hbase.bulkload.staging.dir</name>
|
<name>hbase.bulkload.staging.dir</name>
|
||||||
<value>/tmp/hbase-staging</value>
|
<value>/tmp/hbase-staging</value>
|
||||||
|
@ -1698,22 +1682,6 @@ To enable secure bulk load, add the following properties to _hbase-site.xml_.
|
||||||
</property>
|
</property>
|
||||||
----
|
----
|
||||||
|
|
||||||
[[hbase.secure.enable]]
|
|
||||||
=== Secure Enable
|
|
||||||
After hbase-2.x, the default 'hbase.security.authorization' changed.
|
|
||||||
Before hbase-2.x, it defaulted to true, in later HBase versions, the
|
|
||||||
default became false.
|
|
||||||
So to enable hbase authorization, the following propertie must be configured in _hbase-site.xml_.
|
|
||||||
See link:https://issues.apache.org/jira/browse/HBASE-19483[HBASE-19483];
|
|
||||||
|
|
||||||
[source,xml]
|
|
||||||
----
|
|
||||||
<property>
|
|
||||||
<name>hbase.security.authorization</name>
|
|
||||||
<value>true</value>
|
|
||||||
</property>
|
|
||||||
----
|
|
||||||
|
|
||||||
[[security.example.config]]
|
[[security.example.config]]
|
||||||
== Security Configuration Example
|
== Security Configuration Example
|
||||||
|
|
||||||
|
@ -1735,10 +1703,6 @@ All options have been discussed separately in the sections above.
|
||||||
<value>hbase, admin</value>
|
<value>hbase, admin</value>
|
||||||
</property>
|
</property>
|
||||||
<!-- Coprocessors for ACLs and Visibility Tags -->
|
<!-- Coprocessors for ACLs and Visibility Tags -->
|
||||||
<property>
|
|
||||||
<name>hbase.security.authorization</name>
|
|
||||||
<value>true</value>
|
|
||||||
</property>
|
|
||||||
<property>
|
<property>
|
||||||
<name>hbase.coprocessor.region.classes</name>
|
<name>hbase.coprocessor.region.classes</name>
|
||||||
<value>org.apache.hadoop.hbase.security.access.AccessController,
|
<value>org.apache.hadoop.hbase.security.access.AccessController,
|
||||||
|
|
Loading…
Reference in New Issue