You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by te...@apache.org on 2018/01/05 19:18:22 UTC
[3/3] hbase git commit: HBASE-19483 Add proper privilege check for
rsgroup commands
HBASE-19483 Add proper privilege check for rsgroup commands
Signed-off-by: tedyu <yu...@gmail.com>
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/fc7736eb
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/fc7736eb
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/fc7736eb
Branch: refs/heads/master
Commit: fc7736eb00bb47d619a1345e32f0136751ea8c0b
Parents: 032fdc5
Author: Guangxu Cheng <gu...@gmail.com>
Authored: Fri Jan 5 23:22:32 2018 +0800
Committer: tedyu <yu...@gmail.com>
Committed: Fri Jan 5 11:18:07 2018 -0800
----------------------------------------------------------------------
...tegrationTestIngestWithVisibilityLabels.java | 7 +-
...egrationTestBigLinkedListWithVisibility.java | 7 +-
...tionTestWithCellVisibilityLoadAndVerify.java | 7 +-
.../TestImportTSVWithVisibilityLabels.java | 6 +-
.../hbase/rest/TestScannersWithLabels.java | 6 +-
.../hbase/rsgroup/RSGroupAdminEndpoint.java | 115 ++-
.../hadoop/hbase/master/MasterRpcServices.java | 3 +-
.../hbase/security/access/AccessChecker.java | 333 +++++++++
.../hbase/security/access/AccessController.java | 697 ++++++------------
.../visibility/VisibilityController.java | 13 +-
.../hbase/security/access/SecureTestUtil.java | 6 +
.../security/access/TestAccessController.java | 75 --
.../security/visibility/VisibilityTestUtil.java | 3 +-
...TestThriftHBaseServiceHandlerWithLabels.java | 703 +++++++++----------
.../asciidoc/_chapters/appendix_acl_matrix.adoc | 11 +
src/main/asciidoc/_chapters/ops_mgt.adoc | 12 +
src/main/asciidoc/_chapters/security.adoc | 36 +
17 files changed, 1080 insertions(+), 960 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.java
----------------------------------------------------------------------
diff --git a/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.java b/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.java
index b7d8dad..2928b6d 100644
--- a/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.java
+++ b/hbase-it/src/test/java/org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.java
@@ -23,11 +23,10 @@ import java.util.Arrays;
import java.util.List;
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.visibility.LoadTestDataGeneratorWithVisibilityLabels;
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
-import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
import org.apache.hadoop.hbase.testclassification.IntegrationTests;
import org.apache.hadoop.hbase.util.LoadTestTool;
import org.junit.experimental.categories.Category;
@@ -76,9 +75,7 @@ public class IntegrationTestIngestWithVisibilityLabels extends IntegrationTestIn
public void setUpCluster() throws Exception {
util = getTestingUtil(null);
Configuration conf = util.getConfiguration();
- 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());
+ VisibilityTestUtil.enableVisiblityLabels(conf);
conf.set("hbase.superuser", "admin," + User.getCurrent().getName());
super.setUpCluster();
addLabels();
http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestBigLinkedListWithVisibility.java
----------------------------------------------------------------------
diff --git a/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestBigLinkedListWithVisibility.java b/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestBigLinkedListWithVisibility.java
index d0e6e52..9349f7b 100644
--- a/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestBigLinkedListWithVisibility.java
+++ b/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestBigLinkedListWithVisibility.java
@@ -47,7 +47,6 @@ import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
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.mapreduce.Import;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
@@ -57,7 +56,7 @@ import org.apache.hadoop.hbase.security.access.Permission;
import org.apache.hadoop.hbase.security.visibility.Authorizations;
import org.apache.hadoop.hbase.security.visibility.CellVisibility;
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
-import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
import org.apache.hadoop.hbase.testclassification.IntegrationTests;
import org.apache.hadoop.hbase.util.AbstractHBaseTool;
import org.apache.hadoop.hbase.util.Bytes;
@@ -373,9 +372,7 @@ public class IntegrationTestBigLinkedListWithVisibility extends IntegrationTestB
public void setUpCluster() throws Exception {
util = getTestingUtil(null);
Configuration conf = util.getConfiguration();
- 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());
+ VisibilityTestUtil.enableVisiblityLabels(conf);
conf.set("hbase.superuser", User.getCurrent().getName());
conf.setBoolean("dfs.permissions", false);
USER = User.createUserForTesting(conf, userName, new String[] {});
http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.java
----------------------------------------------------------------------
diff --git a/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.java b/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.java
index 3f97fbb..32c1ddd 100644
--- a/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.java
+++ b/hbase-it/src/test/java/org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.java
@@ -40,7 +40,6 @@ import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.ScannerCallable;
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.TableMapper;
import org.apache.hadoop.hbase.mapreduce.TableRecordReaderImpl;
@@ -48,7 +47,7 @@ import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.security.visibility.Authorizations;
import org.apache.hadoop.hbase.security.visibility.CellVisibility;
import org.apache.hadoop.hbase.security.visibility.VisibilityClient;
-import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
import org.apache.hadoop.hbase.testclassification.IntegrationTests;
import org.apache.hadoop.hbase.util.AbstractHBaseTool;
import org.apache.hadoop.hbase.util.Bytes;
@@ -116,9 +115,7 @@ public class IntegrationTestWithCellVisibilityLoadAndVerify extends IntegrationT
public void setUpCluster() throws Exception {
util = getTestingUtil(null);
Configuration conf = util.getConfiguration();
- 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());
+ VisibilityTestUtil.enableVisiblityLabels(conf);
conf.set("hbase.superuser", User.getCurrent().getName());
conf.setBoolean("dfs.permissions", false);
super.setUpCluster();
http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestImportTSVWithVisibilityLabels.java
----------------------------------------------------------------------
diff --git a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestImportTSVWithVisibilityLabels.java b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestImportTSVWithVisibilityLabels.java
index 8d3f3df..6d6b729 100644
--- a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestImportTSVWithVisibilityLabels.java
+++ b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestImportTSVWithVisibilityLabels.java
@@ -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.VisibilityClient;
import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
-import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.apache.hadoop.hbase.testclassification.MapReduceTests;
@@ -121,9 +121,7 @@ public class TestImportTSVWithVisibilityLabels implements Configurable {
conf = util.getConfiguration();
SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
conf.set("hbase.superuser", "admin,"+User.getCurrent().getName());
- conf.setInt("hfile.format.version", 3);
- conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
- conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
+ VisibilityTestUtil.enableVisiblityLabels(conf);
conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class,
ScanLabelGenerator.class);
util.startMiniCluster();
http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithLabels.java
----------------------------------------------------------------------
diff --git a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithLabels.java b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithLabels.java
index 6ac8e87..8d738ed 100644
--- a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithLabels.java
+++ b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestScannersWithLabels.java
@@ -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.VisibilityClient;
import org.apache.hadoop.hbase.security.visibility.VisibilityConstants;
-import org.apache.hadoop.hbase.security.visibility.VisibilityController;
+import org.apache.hadoop.hbase.security.visibility.VisibilityTestUtil;
import org.apache.hadoop.hbase.security.visibility.VisibilityUtils;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.testclassification.RestTests;
@@ -130,10 +130,8 @@ public class TestScannersWithLabels {
conf = TEST_UTIL.getConfiguration();
conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS,
SimpleScanLabelGenerator.class, ScanLabelGenerator.class);
- conf.setInt("hfile.format.version", 3);
conf.set("hbase.superuser", SUPERUSER.getShortName());
- conf.set("hbase.coprocessor.master.classes", VisibilityController.class.getName());
- conf.set("hbase.coprocessor.region.classes", VisibilityController.class.getName());
+ VisibilityTestUtil.enableVisiblityLabels(conf);
TEST_UTIL.startMiniCluster(1);
// Wait for the labels table to become available
TEST_UTIL.waitTableEnabled(VisibilityConstants.LABELS_TABLE_NAME.getName(), 50000);
http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java
----------------------------------------------------------------------
diff --git a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java
index 7e148e0..964b5da 100644
--- a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java
+++ b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java
@@ -46,6 +46,7 @@ import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
import org.apache.hadoop.hbase.coprocessor.MasterObserver;
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils;
+import org.apache.hadoop.hbase.ipc.RpcServer;
import org.apache.hadoop.hbase.master.MasterServices;
import org.apache.hadoop.hbase.net.Address;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
@@ -74,6 +75,11 @@ 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.RemoveServersRequest;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -92,12 +98,17 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
private RSGroupInfoManager groupInfoManager;
private RSGroupAdminServer groupAdminServer;
private final RSGroupAdminService groupAdminService = new RSGroupAdminServiceImpl();
+ private AccessChecker accessChecker;
+
+ /** Provider for mapping principal names to Users */
+ private UserProvider userProvider;
@Override
public void start(CoprocessorEnvironment env) throws IOException {
if (!(env instanceof HasMasterServices)) {
throw new IOException("Does not implement HMasterServices");
}
+
master = ((HasMasterServices)env).getMasterServices();
groupInfoManager = RSGroupInfoManagerImpl.getInstance(master);
groupAdminServer = new RSGroupAdminServer(master, groupInfoManager);
@@ -106,6 +117,11 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
if (!RSGroupableBalancer.class.isAssignableFrom(clazz)) {
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
@@ -137,6 +153,7 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, group="
+ groupName);
try {
+ checkPermission("getRSGroupInfo");
RSGroupInfo rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName);
if (rsGroupInfo != null) {
builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(rsGroupInfo));
@@ -151,10 +168,11 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
public void getRSGroupInfoOfTable(RpcController controller,
GetRSGroupInfoOfTableRequest request, RpcCallback<GetRSGroupInfoOfTableResponse> done) {
GetRSGroupInfoOfTableResponse.Builder builder = GetRSGroupInfoOfTableResponse.newBuilder();
+ TableName tableName = ProtobufUtil.toTableName(request.getTableName());
+ LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, table="
+ + tableName);
try {
- TableName tableName = ProtobufUtil.toTableName(request.getTableName());
- LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, table="
- + tableName);
+ checkPermission("getRSGroupInfoOfTable");
RSGroupInfo RSGroupInfo = groupAdminServer.getRSGroupInfoOfTable(tableName);
if (RSGroupInfo != null) {
builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
@@ -169,13 +187,14 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
public void moveServers(RpcController controller, MoveServersRequest request,
RpcCallback<MoveServersResponse> done) {
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 {
- 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());
+ checkPermission("moveServers");
groupAdminServer.moveServers(hostPorts, request.getTargetGroup());
} catch (IOException e) {
CoprocessorRpcUtils.setControllerException(controller, e);
@@ -187,13 +206,14 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
public void moveTables(RpcController controller, MoveTablesRequest request,
RpcCallback<MoveTablesResponse> done) {
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 {
- 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());
+ checkPermission("moveTables");
groupAdminServer.moveTables(tables, request.getTargetGroup());
} catch (IOException e) {
CoprocessorRpcUtils.setControllerException(controller, e);
@@ -207,6 +227,7 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
AddRSGroupResponse.Builder builder = AddRSGroupResponse.newBuilder();
LOG.info(master.getClientIdAuditPrefix() + " add rsgroup " + request.getRSGroupName());
try {
+ checkPermission("addRSGroup");
groupAdminServer.addRSGroup(request.getRSGroupName());
} catch (IOException e) {
CoprocessorRpcUtils.setControllerException(controller, e);
@@ -221,6 +242,7 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
RemoveRSGroupResponse.newBuilder();
LOG.info(master.getClientIdAuditPrefix() + " remove rsgroup " + request.getRSGroupName());
try {
+ checkPermission("removeRSGroup");
groupAdminServer.removeRSGroup(request.getRSGroupName());
} catch (IOException e) {
CoprocessorRpcUtils.setControllerException(controller, e);
@@ -235,6 +257,7 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
LOG.info(master.getClientIdAuditPrefix() + " balance rsgroup, group=" +
request.getRSGroupName());
try {
+ checkPermission("balanceRSGroup");
builder.setBalanceRan(groupAdminServer.balanceRSGroup(request.getRSGroupName()));
} catch (IOException e) {
CoprocessorRpcUtils.setControllerException(controller, e);
@@ -249,6 +272,7 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
ListRSGroupInfosResponse.Builder builder = ListRSGroupInfosResponse.newBuilder();
LOG.info(master.getClientIdAuditPrefix() + " list rsgroup");
try {
+ checkPermission("listRSGroup");
for (RSGroupInfo RSGroupInfo : groupAdminServer.listRSGroups()) {
builder.addRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
}
@@ -262,11 +286,12 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
public void getRSGroupInfoOfServer(RpcController controller,
GetRSGroupInfoOfServerRequest request, RpcCallback<GetRSGroupInfoOfServerResponse> done) {
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 {
- Address hp = Address.fromParts(request.getServer().getHostName(),
- request.getServer().getPort());
- LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, server=" +
- hp);
+ checkPermission("getRSGroupInfoOfServer");
RSGroupInfo RSGroupInfo = groupAdminServer.getRSGroupOfServer(hp);
if (RSGroupInfo != null) {
builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo));
@@ -281,17 +306,18 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
public void moveServersAndTables(RpcController controller,
MoveServersAndTablesRequest request, RpcCallback<MoveServersAndTablesResponse> done) {
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 {
- 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());
+ checkPermission("moveServersAndTables");
groupAdminServer.moveServersAndTables(hostPorts, tables, request.getTargetGroup());
} catch (IOException e) {
CoprocessorRpcUtils.setControllerException(controller, e);
@@ -305,13 +331,14 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
RpcCallback<RemoveServersResponse> done) {
RemoveServersResponse.Builder builder =
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 {
- 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);
+ checkPermission("removeServers");
groupAdminServer.removeServers(servers);
} catch (IOException e) {
CoprocessorRpcUtils.setControllerException(controller, e);
@@ -397,5 +424,21 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
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();
+ }
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
index 8f41e4f..907ca9b 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
@@ -83,6 +83,7 @@ import org.apache.hadoop.hbase.replication.ReplicationException;
import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.security.access.AccessChecker;
import org.apache.hadoop.hbase.security.access.AccessController;
import org.apache.hadoop.hbase.security.visibility.VisibilityController;
import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
@@ -1810,7 +1811,7 @@ public class MasterRpcServices extends RSRpcServices
// A coprocessor that implements AccessControlService can provide AUTHORIZATION and
// CELL_AUTHORIZATION
if (master.cpHost != null && hasAccessControlServiceCoprocessor(master.cpHost)) {
- if (AccessController.isAuthorizationSupported(master.getConfiguration())) {
+ if (AccessChecker.isAuthorizationSupported(master.getConfiguration())) {
capabilities.add(SecurityCapabilitiesResponse.Capability.AUTHORIZATION);
}
if (AccessController.isCellAuthorizationSupported(master.getConfiguration())) {
http://git-wip-us.apache.org/repos/asf/hbase/blob/fc7736eb/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessChecker.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessChecker.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessChecker.java
new file mode 100644
index 0000000..2a7373e
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessChecker.java
@@ -0,0 +1,333 @@
+/*
+ * 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());
+ }
+ }
+}
\ No newline at end of file