From 83109a035f7e1891e25e9a8707c7d5e62eea3124 Mon Sep 17 00:00:00 2001 From: Guangxu Cheng Date: Tue, 12 Dec 2017 15:04:20 +0800 Subject: [PATCH] HBASE-19483 Add proper privilege check for rsgroup commands --- .../hadoop/hbase/rsgroup/RSGroupAdminServer.java | 37 ++++++++- .../hadoop/hbase/coprocessor/MasterObserver.java | 67 ++++++++++++++++ .../hadoop/hbase/master/MasterCoprocessorHost.java | 89 ++++++++++++++++++++++ .../hbase/security/access/AccessController.java | 24 ++++++ src/main/asciidoc/_chapters/ops_mgt.adoc | 18 +++++ 5 files changed, 231 insertions(+), 4 deletions(-) diff --git a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java index 45421e325b..8da099e484 100644 --- a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java +++ b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java @@ -67,15 +67,30 @@ public class RSGroupAdminServer implements RSGroupAdmin { @Override public RSGroupInfo getRSGroupInfo(String groupName) throws IOException { - return rsGroupInfoManager.getRSGroup(groupName); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preGetRSGroupInfo(groupName); + } + RSGroupInfo rsGroupInfo = rsGroupInfoManager.getRSGroup(groupName); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postGetRSGroupInfo(groupName, rsGroupInfo); + } + return rsGroupInfo; } @Override public RSGroupInfo getRSGroupInfoOfTable(TableName tableName) throws IOException { + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preGetRSGroupInfoOfTable(tableName); + } // We are reading across two Maps in the below with out synchronizing across // them; should be safe most of the time. String groupName = rsGroupInfoManager.getRSGroupOfTable(tableName); - return groupName == null? null: rsGroupInfoManager.getRSGroup(groupName); + RSGroupInfo rsGroupInfo = groupName == null? + null: rsGroupInfoManager.getRSGroup(groupName); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postGetRSGroupInfoOfTable(tableName, rsGroupInfo); + } + return rsGroupInfo; } private void checkOnlineServersOnly(Set
servers) throws ConstraintException { @@ -536,12 +551,26 @@ public class RSGroupAdminServer implements RSGroupAdmin { @Override public List listRSGroups() throws IOException { - return rsGroupInfoManager.listRSGroups(); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preListRSGroup(); + } + List groupInfos = rsGroupInfoManager.listRSGroups(); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postListRSGroup(groupInfos); + } + return groupInfos; } @Override public RSGroupInfo getRSGroupOfServer(Address hostPort) throws IOException { - return rsGroupInfoManager.getRSGroupOfServer(hostPort); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preGetRSGroupOfServer(hostPort); + } + RSGroupInfo rsGroupInfo = rsGroupInfoManager.getRSGroupOfServer(hostPort); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postGetRSGroupOfServer(hostPort, rsGroupInfo); + } + return rsGroupInfo; } @Override diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java index 6ef5504ad9..5eb9908a04 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java @@ -37,6 +37,7 @@ import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.net.Address; import org.apache.hadoop.hbase.quotas.GlobalQuotaSettings; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; +import org.apache.hadoop.hbase.rsgroup.RSGroupInfo; import org.apache.yetus.audience.InterfaceAudience; import org.apache.yetus.audience.InterfaceStability; @@ -1117,6 +1118,72 @@ public interface MasterObserver { Set
servers) throws IOException {} /** + * Called before list rsgroup + * @param ctx the environment to interact with the framework and master + */ + default void preListRSGroup( + final ObserverContext ctx) throws IOException {} + + /** + * Called after list rsgroup + * @param ctx the environment to interact with the framework and master + * @param groupInfos list of regionserver group. + */ + default void postListRSGroup(final ObserverContext ctx, + final List groupInfos) throws IOException {} + + /** + * Called before get rsgroup info for given group name + * @param ctx the environment to interact with the framework and master + * @param groupName the given group name + */ + default void preGetRSGroupInfo(final ObserverContext ctx, + final String groupName) throws IOException {} + + /** + * Called after get rsgroup info for given group name + * @param ctx the environment to interact with the framework and master + * @param groupName the given group name + * @param rsGroupInfo the group information + */ + default void postGetRSGroupInfo(final ObserverContext ctx, + final String groupName, final RSGroupInfo rsGroupInfo) throws IOException {} + + /** + * Called before get rsgroup info for given table name + * @param ctx the environment to interact with the framework and master + * @param tableName the given table name + */ + default void preGetRSGroupInfoOfTable(final ObserverContext ctx, + final TableName tableName) throws IOException {} + + /** + * Called after get rsgroup info for given table name + * @param ctx the environment to interact with the framework and master + * @param tableName the given table name + * @param rsGroupInfo the group information + */ + default void postGetRSGroupInfoOfTable(final ObserverContext ctx, + final TableName tableName, final RSGroupInfo rsGroupInfo) throws IOException {} + + /** + * Called before get rsgroup info for given server + * @param ctx the environment to interact with the framework and master + * @param hostPort the given server + */ + default void preGetRSGroupOfServer(final ObserverContext ctx, + final Address hostPort) throws IOException {} + + /** + * Called after get rsgroup info for given server + * @param ctx the environment to interact with the framework and master + * @param hostPort the given server + * @param rsGroupInfo the group information + */ + default void postGetRSGroupOfServer(final ObserverContext ctx, + final Address hostPort, final RSGroupInfo rsGroupInfo) throws IOException {} + + /** * Called before add a replication peer * @param ctx the environment to interact with the framework and master * @param peerId a short name that identifies the peer diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java index bc262290fc..e9fc91f08d 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java @@ -59,6 +59,7 @@ import org.apache.hadoop.hbase.procedure2.Procedure; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.quotas.GlobalQuotaSettings; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; +import org.apache.hadoop.hbase.rsgroup.RSGroupInfo; import org.apache.hadoop.hbase.security.User; import org.apache.yetus.audience.InterfaceAudience; @@ -1426,6 +1427,94 @@ public class MasterCoprocessorHost }); } + public void preListRSGroup() throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + if(((MasterEnvironment)getEnvironment()).supportGroupCPs) { + observer.preListRSGroup(this); + } + } + }); + } + + public void postListRSGroup(List groupInfos) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + if(((MasterEnvironment)getEnvironment()).supportGroupCPs) { + observer.postListRSGroup(this, groupInfos); + } + } + }); + } + + public void preGetRSGroupInfo(String groupName) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + if(((MasterEnvironment)getEnvironment()).supportGroupCPs) { + observer.preGetRSGroupInfo(this, groupName); + } + } + }); + } + + public void postGetRSGroupInfo(String groupName, RSGroupInfo rsGroupInfo) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + if(((MasterEnvironment)getEnvironment()).supportGroupCPs) { + observer.postGetRSGroupInfo(this, groupName, rsGroupInfo); + } + } + }); + } + + public void preGetRSGroupInfoOfTable(TableName tableName) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + if(((MasterEnvironment)getEnvironment()).supportGroupCPs) { + observer.preGetRSGroupInfoOfTable(this, tableName); + } + } + }); + } + + public void postGetRSGroupInfoOfTable(TableName tableName, RSGroupInfo rsGroupInfo) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + if(((MasterEnvironment)getEnvironment()).supportGroupCPs) { + observer.postGetRSGroupInfoOfTable(this, tableName, rsGroupInfo); + } + } + }); + } + + public void preGetRSGroupOfServer(Address hostPort) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + if(((MasterEnvironment)getEnvironment()).supportGroupCPs) { + observer.preGetRSGroupOfServer(this, hostPort); + } + } + }); + } + + public void postGetRSGroupOfServer(Address hostPort, RSGroupInfo rsGroupInfo) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + if(((MasterEnvironment)getEnvironment()).supportGroupCPs) { + observer.postGetRSGroupOfServer(this, hostPort, rsGroupInfo); + } + } + }); + } + public void preAddReplicationPeer(final String peerId, final ReplicationPeerConfig peerConfig) throws IOException { execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java index 2e2d263ee3..d310dbf60b 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/AccessController.java @@ -2693,6 +2693,30 @@ public class AccessController implements MasterCoprocessor, RegionCoprocessor, } @Override + public void preListRSGroup(ObserverContext ctx) + throws IOException { + requirePermission(getActiveUser(ctx), "listRSGroup", Action.ADMIN); + } + + @Override + public void preGetRSGroupInfo(ObserverContext ctx, + String groupName) throws IOException { + requirePermission(getActiveUser(ctx), "getRSGroup", Action.ADMIN); + } + + @Override + public void preGetRSGroupInfoOfTable(ObserverContext ctx, + TableName tableName) throws IOException { + requirePermission(getActiveUser(ctx), "getRSGroupInfoOfTable", Action.ADMIN); + } + + @Override + public void preGetRSGroupOfServer(ObserverContext ctx, + Address hostPort) throws IOException { + requirePermission(getActiveUser(ctx), "getRSGroupOfServer", Action.ADMIN); + } + + @Override public void preAddReplicationPeer(final ObserverContext ctx, String peerId, ReplicationPeerConfig peerConfig) throws IOException { requirePermission(getActiveUser(ctx), "addReplicationPeer", Action.ADMIN); diff --git a/src/main/asciidoc/_chapters/ops_mgt.adoc b/src/main/asciidoc/_chapters/ops_mgt.adoc index 7b0f89b47d..0f2d8e252d 100644 --- a/src/main/asciidoc/_chapters/ops_mgt.adoc +++ b/src/main/asciidoc/_chapters/ops_mgt.adoc @@ -2704,4 +2704,22 @@ Viewing the Master log will give you insight on rsgroup operation. If it appears stuck, restart the Master process. +=== Access Control +The following matrix shows the permission set required to perform operations in +RegionServer Grouping. +.ACL Matrix +[cols="1,1", frame="all", options="header"] +|=== +|Operation |Permissions +|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) \ No newline at end of file -- 2.13.0.windows.1