From 7053fcd1c02acbccfc0051bc443717273af5a3b9 Mon Sep 17 00:00:00 2001 From: Guangxu Cheng Date: Wed, 13 Dec 2017 10:25:29 +0800 Subject: [PATCH] HBASE-19483 Add proper privilege check for rsgroup commands --- .../hadoop/hbase/rsgroup/RSGroupAdminServer.java | 37 ++++++++- .../hadoop/hbase/coprocessor/MasterObserver.java | 70 +++++++++++++++++ .../hadoop/hbase/master/MasterCoprocessorHost.java | 89 ++++++++++++++++++++++ .../hbase/security/access/AccessController.java | 24 ++++++ .../asciidoc/_chapters/appendix_acl_matrix.adoc | 11 +++ 5 files changed, 227 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..fcec9f241c 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 rsGroupInfos = rsGroupInfoManager.listRSGroups(); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postListRSGroup(rsGroupInfos); + } + return rsGroupInfos; } @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..014fd9ed3d 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,75 @@ 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 rsGroupInfos list of RSGroupInfo or an empty list if there is no group + */ + default void postListRSGroup(final ObserverContext ctx, + final List rsGroupInfos) 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 RSGroupInfo to which the given group belongs + * or null if the group is not found + */ + 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 RSGroupInfo to which the given table belongs + * or null if the given table not belongs to any group + */ + 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 RSGroupInfo to which the given server belongs + * or null if the given server not belongs to any group + */ + 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..a7e5926f06 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 rsGroupInfos) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + if(((MasterEnvironment)getEnvironment()).supportGroupCPs) { + observer.postListRSGroup(this, rsGroupInfos); + } + } + }); + } + + 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/appendix_acl_matrix.adoc b/src/main/asciidoc/_chapters/appendix_acl_matrix.adoc index 0c99b1f361..626b2668a7 100644 --- a/src/main/asciidoc/_chapters/appendix_acl_matrix.adoc +++ b/src/main/asciidoc/_chapters/appendix_acl_matrix.adoc @@ -164,6 +164,17 @@ In case the table goes out of date, the unit tests which check for accuracy of p | | mergeRegions | superuser\|global(A) | | rollWALWriterRequest | superuser\|global(A) | | 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: -- 2.13.0.windows.1