diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java index 581e3c9..9e598ed 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java @@ -47,6 +47,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Maps; import com.google.protobuf.Descriptors; import com.google.protobuf.Service; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; @@ -78,6 +79,7 @@ import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.client.RegionReplicaUtil; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.TableState; +import org.apache.hadoop.hbase.constraint.ConstraintException; import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.executor.ExecutorType; @@ -115,7 +117,9 @@ import org.apache.hadoop.hbase.regionserver.RSRpcServices; import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost; import org.apache.hadoop.hbase.regionserver.RegionSplitPolicy; import org.apache.hadoop.hbase.replication.regionserver.Replication; +import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.security.UserProvider; +import org.apache.hadoop.hbase.security.UserUtil; import org.apache.hadoop.hbase.util.Addressing; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.CompressionTest; @@ -299,6 +303,9 @@ public class HMaster extends HRegionServer implements MasterServices, Server { /** jetty server for master to redirect requests to regionserver infoServer */ private org.mortbay.jetty.Server masterJettyServer; + private List superUsers; + private List superGroups; + public static class RedirectServlet extends HttpServlet { private static final long serialVersionUID = 2894774810058302472L; private static int regionServerInfoPort; @@ -381,6 +388,9 @@ public class HMaster extends HRegionServer implements MasterServices, Server { activeMasterManager = new ActiveMasterManager(zooKeeper, this.serverName, this); int infoPort = putUpJettyServer(); startActiveMasterManager(infoPort); + Pair, List> superUsersAndGroups = UserUtil.getSuperUsers(this.conf); + this.superUsers = superUsersAndGroups.getFirst(); + this.superGroups = superUsersAndGroups.getSecond(); } // return the actual infoPort, -1 means disable info server. @@ -1288,6 +1298,15 @@ public class HMaster extends HRegionServer implements MasterServices, Server { } String namespace = hTableDescriptor.getTableName().getNamespaceAsString(); + // Do not allow non super users to create tables in system namespace + if (NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR.equals(namespace)) { + User user = UserUtil.getActiveUser(); + if (!UserUtil.isSuperUser(user, this.superUsers, this.superGroups)) { + throw new ConstraintException("User : " + user.getShortName() + " can't create tables in '" + + NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR + "' namespace"); + } + } + ensureNamespaceExists(namespace); HRegionInfo[] newRegions = getHRegionInfos(hTableDescriptor, splitKeys); @@ -1535,10 +1554,6 @@ public class HMaster extends HRegionServer implements MasterServices, Server { return hRegionInfos; } - private static boolean isCatalogTable(final TableName tableName) { - return tableName.equals(TableName.META_TABLE_NAME); - } - @Override public void deleteTable(final TableName tableName) throws IOException { checkInitialized(); @@ -1641,6 +1656,17 @@ public class HMaster extends HRegionServer implements MasterServices, Server { cpHost.preDisableTable(tableName); } LOG.info(getClientIdAuditPrefix() + " disable " + tableName); + if (tableName.equals(TableName.META_TABLE_NAME)) { + throw new ConstraintException("Cannot disable " + TableName.META_TABLE_NAME + " table"); + } + if (tableName.getNamespaceAsString().equals(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR)) { + User user = UserUtil.getActiveUser(); + if (!UserUtil.isSuperUser(user, this.superUsers, this.superGroups)) { + throw new ConstraintException("User : " + user.getShortName() + + " can't disable tables in '" + NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR + + "' namespace"); + } + } this.service.submit(new DisableTableHandler(this, tableName, assignmentManager, tableLockManager, false).prepare()); if (cpHost != null) { @@ -1701,8 +1727,12 @@ public class HMaster extends HRegionServer implements MasterServices, Server { @Override public void checkTableModifiable(final TableName tableName) throws IOException, TableNotFoundException, TableNotDisabledException { - if (isCatalogTable(tableName)) { - throw new IOException("Can't modify catalog tables"); + if (tableName.getNamespaceAsString().equals(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR)) { + User user = UserUtil.getActiveUser(); + if (!UserUtil.isSuperUser(user, this.superUsers, this.superGroups)) { + throw new ConstraintException("User : " + user.getShortName() + " can't modify tables in '" + + NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR + "' namespace"); + } } if (!MetaTableAccessor.tableExists(getConnection(), tableName)) { throw new TableNotFoundException(tableName); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/handler/DisableTableHandler.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/handler/DisableTableHandler.java index ee77419..726b7cd 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/handler/DisableTableHandler.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/handler/DisableTableHandler.java @@ -32,7 +32,6 @@ import org.apache.hadoop.hbase.TableNotEnabledException; import org.apache.hadoop.hbase.TableNotFoundException; import org.apache.hadoop.hbase.MetaTableAccessor; import org.apache.hadoop.hbase.client.TableState; -import org.apache.hadoop.hbase.constraint.ConstraintException; import org.apache.hadoop.hbase.executor.EventHandler; import org.apache.hadoop.hbase.executor.EventType; import org.apache.hadoop.hbase.master.AssignmentManager; @@ -69,9 +68,6 @@ public class DisableTableHandler extends EventHandler { public DisableTableHandler prepare() throws TableNotFoundException, TableNotEnabledException, IOException { - if(tableName.equals(TableName.META_TABLE_NAME)) { - throw new ConstraintException("Cannot disable catalog table"); - } //acquire the table write lock, blocking this.tableLock = this.tableLockManager.writeLock(tableName, EventType.C_M_DISABLE_TABLE.toString()); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/UserUtil.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/UserUtil.java new file mode 100644 index 0000000..ce348bb --- /dev/null +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/UserUtil.java @@ -0,0 +1,105 @@ +/** + * 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; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.classification.InterfaceAudience; +import org.apache.hadoop.hbase.ipc.RpcServer; +import org.apache.hadoop.hbase.security.access.AccessControlLists; +import org.apache.hadoop.hbase.security.visibility.VisibilityUtils; +import org.apache.hadoop.hbase.util.Pair; + +@InterfaceAudience.Private +public class UserUtil { + + private static final Log LOG = LogFactory.getLog(VisibilityUtils.class); + + /** + * Get the super users and groups defined in the configuration. + * The user running the hbase server is always included as a super user. + * @param conf + * @return Pair of super user list and super group list. + * @throws IOException + */ + public static Pair, List> getSuperUsers(Configuration conf) + throws IOException { + ArrayList superUsers = new ArrayList(); + ArrayList superGroups = new ArrayList(); + User user = User.getCurrent(); + if (user == null) { + throw new IOException("Unable to obtain the current user, " + + "authorization checks for internal operations will not work correctly!"); + } + String currentUser = user.getShortName(); + String[] superUserList = conf.getStrings(AccessControlLists.SUPERUSER_CONF_KEY, new String[0]); + for (String name : superUserList) { + if (AccessControlLists.isGroupPrincipal(name)) { + superGroups.add(AccessControlLists.getGroupName(name)); + } else { + superUsers.add(name); + } + } + superUsers.add(currentUser); + return new Pair, List>(superUsers, superGroups); + } + + /** + * @return User who called RPC method. For non-RPC handling, falls back to system user + * @throws IOException When there is IOE in getting the system user (During non-RPC handling). + */ + public static User getActiveUser() throws IOException { + User user = RpcServer.getRequestUser(); + if (user == null) { + user = User.getCurrent(); + } + if (LOG.isTraceEnabled()) { + LOG.trace("Current active user name is " + user.getShortName()); + } + return user; + } + + /** + * Checks whether the passed user is having super user privilege or not. + * @param user Given user to check + * @param superUsers All super users configured for the system + * @param superGroups All super groups configured for the system + * @return true if passed user is part of superUsers or any of his group is part of superGroups + * @throws IOException + */ + public static boolean isSuperUser(User user, List superUsers, List superGroups) + throws IOException { + if (superUsers.contains(user.getShortName())) { + return true; + } + String[] groups = user.getGroupNames(); + if (groups != null && groups.length > 0) { + for (String group : groups) { + if (superGroups.contains(group)) { + return true; + } + } + } + return false; + } +} 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 2bab7e8..e21b675 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 @@ -98,6 +98,7 @@ import org.apache.hadoop.hbase.replication.ReplicationEndpoint; import org.apache.hadoop.hbase.security.AccessDeniedException; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.security.UserProvider; +import org.apache.hadoop.hbase.security.UserUtil; import org.apache.hadoop.hbase.security.access.Permission.Action; import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils; import org.apache.hadoop.hbase.util.ByteRange; @@ -957,9 +958,8 @@ public class AccessController extends BaseMasterAndRegionObserver this.userProvider = UserProvider.instantiate(env.getConfiguration()); // set up the list of users with superuser privilege - User user = userProvider.getCurrent(); - superusers = Lists.asList(user.getShortName(), - conf.getStrings(AccessControlLists.SUPERUSER_CONF_KEY, new String[0])); + superusers = UserUtil.getSuperUsers(conf).getFirst(); + // TODO we need to check against super groups also? // If zk is null or IOException while obtaining auth manager, // throw RuntimeException so that the coprocessor is unloaded. @@ -1160,10 +1160,6 @@ public class AccessController extends BaseMasterAndRegionObserver @Override public void preDisableTable(ObserverContext c, TableName tableName) throws IOException { - if (Bytes.equals(tableName.getName(), AccessControlLists.ACL_GLOBAL_NAME)) { - throw new AccessDeniedException("Not allowed to disable " - + AccessControlLists.ACL_TABLE_NAME + " table."); - } requirePermission("disableTable", tableName, null, null, Action.ADMIN, Action.CREATE); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/TableAuthManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/TableAuthManager.java index d043735..19bae59 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/TableAuthManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/TableAuthManager.java @@ -34,13 +34,14 @@ import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.security.UserProvider; +import org.apache.hadoop.hbase.security.UserUtil; import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.util.Pair; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; import org.apache.zookeeper.KeeperException; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; -import com.google.common.collect.Lists; /** * Performs authorization checks for a given user's assigned permissions @@ -135,20 +136,14 @@ public class TableAuthManager { "authorization checks for internal operations will not work correctly!"); } PermissionCache newCache = new PermissionCache(); - String currentUser = user.getShortName(); - - // the system user is always included - List superusers = Lists.asList(currentUser, conf.getStrings( - AccessControlLists.SUPERUSER_CONF_KEY, new String[0])); - if (superusers != null) { - for (String name : superusers) { - if (AccessControlLists.isGroupPrincipal(name)) { - newCache.putGroup(AccessControlLists.getGroupName(name), - new Permission(Permission.Action.values())); - } else { - newCache.putUser(name, new Permission(Permission.Action.values())); - } - } + Pair, List> superUsers = UserUtil.getSuperUsers(conf); + // Super users + for (String name : superUsers.getFirst()) { + newCache.putUser(name, new Permission(Permission.Action.values())); + } + // Super groups + for (String name : superUsers.getSecond()) { + newCache.putGroup(name, new Permission(Permission.Action.values())); } return newCache; } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.java index 34ccb4a..449a329 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.java @@ -60,6 +60,7 @@ import org.apache.hadoop.hbase.regionserver.OperationStatus; import org.apache.hadoop.hbase.regionserver.Region; import org.apache.hadoop.hbase.regionserver.RegionScanner; import org.apache.hadoop.hbase.security.User; +import org.apache.hadoop.hbase.security.UserUtil; import org.apache.hadoop.hbase.security.access.AccessControlLists; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Pair; @@ -118,8 +119,8 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService throw ioe; } this.scanLabelGenerators = VisibilityUtils.getScanLabelGenerators(this.conf); - Pair, List> superUsersAndGroups = - VisibilityUtils.getSystemAndSuperUsers(this.conf); + Pair, List> superUsersAndGroups = UserUtil + .getSuperUsers(this.conf); this.superUsers = superUsersAndGroups.getFirst(); this.superGroups = superUsersAndGroups.getSecond(); if (e.getRegion().getRegionInfo().getTable().equals(LABELS_TABLE_NAME)) { @@ -421,7 +422,7 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService boolean checkAuths) throws IOException { Set auths = new HashSet(); if (checkAuths) { - User user = VisibilityUtils.getActiveUser(); + User user = UserUtil.getActiveUser(); auths.addAll(this.labelsCache.getUserAuthsAsOrdinals(user.getShortName())); auths.addAll(this.labelsCache.getGroupAuthsAsOrdinals(user.getGroupNames())); } @@ -464,7 +465,7 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService for (ScanLabelGenerator scanLabelGenerator : scanLabelGenerators) { try { // null authorizations to be handled inside SLG impl. - authLabels = scanLabelGenerator.getLabels(VisibilityUtils.getActiveUser(), authorizations); + authLabels = scanLabelGenerator.getLabels(UserUtil.getActiveUser(), authorizations); authLabels = (authLabels == null) ? new ArrayList() : authLabels; authorizations = new Authorizations(authLabels); } catch (Throwable t) { @@ -532,14 +533,14 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService } protected boolean isReadFromSystemAuthUser() throws IOException { - User user = VisibilityUtils.getActiveUser(); + User user = UserUtil.getActiveUser(); return havingSystemAuth(user); } @Override public boolean havingSystemAuth(User user) throws IOException { // A super user has 'system' auth. - if (isSystemOrSuperUser(user)) { + if (UserUtil.isSuperUser(user, this.superUsers, this.superGroups)) { return true; } // A user can also be explicitly granted 'system' auth. @@ -557,21 +558,6 @@ public class DefaultVisibilityLabelServiceImpl implements VisibilityLabelService return auths.contains(SYSTEM_LABEL); } - private boolean isSystemOrSuperUser(User user) throws IOException { - if (this.superUsers.contains(user.getShortName())) { - return true; - } - String[] groups = user.getGroupNames(); - if (groups != null && groups.length > 0) { - for (String group : groups) { - if (this.superGroups.contains(group)) { - return true; - } - } - } - return false; - } - @Override public boolean matchVisibility(List putVisTags, Byte putTagsFormat, List deleteVisTags, Byte deleteTagsFormat) throws IOException { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java index 5fb0234..a1dc0e4 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityController.java @@ -57,7 +57,6 @@ import org.apache.hadoop.hbase.client.Mutation; 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.constraint.ConstraintException; import org.apache.hadoop.hbase.coprocessor.BaseMasterAndRegionObserver; import org.apache.hadoop.hbase.coprocessor.BaseRegionServerObserver; import org.apache.hadoop.hbase.coprocessor.CoprocessorException; @@ -98,6 +97,7 @@ import org.apache.hadoop.hbase.regionserver.RegionScanner; import org.apache.hadoop.hbase.replication.ReplicationEndpoint; import org.apache.hadoop.hbase.security.AccessDeniedException; import org.apache.hadoop.hbase.security.User; +import org.apache.hadoop.hbase.security.UserUtil; import org.apache.hadoop.hbase.security.access.AccessControlLists; import org.apache.hadoop.hbase.security.access.AccessController; import org.apache.hadoop.hbase.util.ByteStringer; @@ -163,8 +163,8 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements visibilityLabelService = VisibilityLabelServiceManager.getInstance() .getVisibilityLabelService(this.conf); } - Pair, List> superUsersAndGroups = - VisibilityUtils.getSystemAndSuperUsers(this.conf); + Pair, List> superUsersAndGroups = UserUtil + .getSuperUsers(this.conf); this.superUsers = superUsersAndGroups.getFirst(); this.superGroups = superUsersAndGroups.getSecond(); } @@ -197,46 +197,6 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements } } - @Override - public void preModifyTable(ObserverContext ctx, - TableName tableName, HTableDescriptor htd) throws IOException { - if (LABELS_TABLE_NAME.equals(tableName)) { - throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); - } - } - - @Override - public void preAddColumn(ObserverContext ctx, TableName tableName, - HColumnDescriptor column) throws IOException { - if (LABELS_TABLE_NAME.equals(tableName)) { - throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); - } - } - - @Override - public void preModifyColumn(ObserverContext ctx, - TableName tableName, HColumnDescriptor descriptor) throws IOException { - if (LABELS_TABLE_NAME.equals(tableName)) { - throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); - } - } - - @Override - public void preDeleteColumn(ObserverContext ctx, - TableName tableName, byte[] c) throws IOException { - if (LABELS_TABLE_NAME.equals(tableName)) { - throw new ConstraintException("Cannot alter " + LABELS_TABLE_NAME); - } - } - - @Override - public void preDisableTable(ObserverContext ctx, TableName tableName) - throws IOException { - if (LABELS_TABLE_NAME.equals(tableName)) { - throw new ConstraintException("Cannot disable " + LABELS_TABLE_NAME); - } - } - /****************************** Region related hooks ******************************/ @Override @@ -563,7 +523,7 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements @Override public RegionScanner postScannerOpen(final ObserverContext c, final Scan scan, final RegionScanner s) throws IOException { - User user = VisibilityUtils.getActiveUser(); + User user = UserUtil.getActiveUser(); if (user != null && user.getShortName() != null) { scannerOwners.put(s, user.getShortName()); } @@ -639,7 +599,7 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements } private boolean isSystemOrSuperUser() throws IOException { - User activeUser = VisibilityUtils.getActiveUser(); + User activeUser = UserUtil.getActiveUser(); if (this.superUsers.contains(activeUser.getShortName())) { return true; } @@ -837,7 +797,7 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements User requestingUser = null; try { - requestingUser = VisibilityUtils.getActiveUser(); + requestingUser = UserUtil.getActiveUser(); } catch (IOException e) { LOG.warn("Failed to get active system user."); LOG.debug("Details on failure to get active system user.", e); @@ -863,7 +823,7 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements // We do ACL check here as we create scanner directly on region. It will not make calls to // AccessController CP methods. if (this.acOn && !isSystemOrSuperUser()) { - User requestingUser = VisibilityUtils.getActiveUser(); + User requestingUser = UserUtil.getActiveUser(); throw new AccessDeniedException("User '" + (requestingUser != null ? requestingUser.getShortName() : "null") + "' is not authorized to perform this action."); @@ -906,7 +866,7 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements try { // When AC is ON, do AC based user auth check if (this.acOn && !isSystemOrSuperUser()) { - User user = VisibilityUtils.getActiveUser(); + User user = UserUtil.getActiveUser(); throw new AccessDeniedException("User '" + (user != null ? user.getShortName() : "null") + " is not authorized to perform this action."); } @@ -956,7 +916,7 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements // We do ACL check here as we create scanner directly on region. It will not make calls to // AccessController CP methods. if (this.acOn && !isSystemOrSuperUser()) { - User requestingUser = VisibilityUtils.getActiveUser(); + User requestingUser = UserUtil.getActiveUser(); throw new AccessDeniedException("User '" + (requestingUser != null ? requestingUser.getShortName() : "null") + "' is not authorized to perform this action."); @@ -980,7 +940,7 @@ public class VisibilityController extends BaseMasterAndRegionObserver implements private void checkCallingUserAuth() throws IOException { if (!this.acOn) { - User user = VisibilityUtils.getActiveUser(); + User user = UserUtil.getActiveUser(); if (user == null) { throw new IOException("Unable to retrieve calling user"); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityUtils.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityUtils.java index 916a34c..13bfeb4 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityUtils.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/visibility/VisibilityUtils.java @@ -44,7 +44,6 @@ import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.filter.Filter; import org.apache.hadoop.hbase.io.util.StreamUtils; -import org.apache.hadoop.hbase.ipc.RpcServer; import org.apache.hadoop.hbase.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.MultiUserAuthorizations; import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.UserAuthorizations; @@ -52,8 +51,7 @@ import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.Visibil import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsRequest; import org.apache.hadoop.hbase.regionserver.Region; import org.apache.hadoop.hbase.security.AccessDeniedException; -import org.apache.hadoop.hbase.security.User; -import org.apache.hadoop.hbase.security.access.AccessControlLists; +import org.apache.hadoop.hbase.security.UserUtil; import org.apache.hadoop.hbase.security.visibility.expression.ExpressionNode; import org.apache.hadoop.hbase.security.visibility.expression.LeafExpressionNode; import org.apache.hadoop.hbase.security.visibility.expression.NonLeafExpressionNode; @@ -61,7 +59,6 @@ import org.apache.hadoop.hbase.security.visibility.expression.Operator; import org.apache.hadoop.hbase.util.ByteRange; import org.apache.hadoop.hbase.util.ByteStringer; import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.hbase.util.Pair; import org.apache.hadoop.hbase.util.SimpleMutableByteRange; import org.apache.hadoop.util.ReflectionUtils; @@ -103,38 +100,6 @@ public class VisibilityUtils { } /** - * Get the super users and groups defined in the configuration. - * The user running the hbase server is always included. - * @param conf - * @return Pair of super user list and super group list. - * @throws IOException - */ - public static Pair, List> getSystemAndSuperUsers(Configuration conf) - throws IOException { - ArrayList superUsers = new ArrayList(); - ArrayList superGroups = new ArrayList(); - User user = User.getCurrent(); - if (user == null) { - throw new IOException("Unable to obtain the current user, " - + "authorization checks for internal operations will not work correctly!"); - } - if (LOG.isTraceEnabled()) { - LOG.trace("Current user name is " + user.getShortName()); - } - String currentUser = user.getShortName(); - String[] superUserList = conf.getStrings(AccessControlLists.SUPERUSER_CONF_KEY, new String[0]); - for (String name : superUserList) { - if (AccessControlLists.isGroupPrincipal(name)) { - superGroups.add(AccessControlLists.getGroupName(name)); - } else { - superUsers.add(name); - } - } - superUsers.add(currentUser); - return new Pair, List>(superUsers, superGroups); - } - - /** * Creates the user auth data to be written to zookeeper. * @param userAuths * @return Bytes form of user auths details to be written to zookeeper. @@ -321,21 +286,6 @@ public class VisibilityUtils { return visibilityLabelFilter; } - /** - * @return User who called RPC method. For non-RPC handling, falls back to system user - * @throws IOException When there is IOE in getting the system user (During non-RPC handling). - */ - public static User getActiveUser() throws IOException { - User user = RpcServer.getRequestUser(); - if (user == null) { - user = User.getCurrent(); - } - if (LOG.isTraceEnabled()) { - LOG.trace("Current active user name is " + user.getShortName()); - } - return user; - } - public static List createVisibilityExpTags(String visExpression, boolean withSerializationFormat, boolean checkAuths, Set auths, VisibilityLabelOrdinalProvider ordinalProvider) throws IOException { @@ -437,7 +387,7 @@ public class VisibilityUtils { if (checkAuths) { if (auths == null || (!auths.contains(labelOrdinal))) { throw new AccessDeniedException("Visibility label " + identifier - + " not authorized for the user " + VisibilityUtils.getActiveUser().getShortName()); + + " not authorized for the user " + UserUtil.getActiveUser().getShortName()); } } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/ExpAsStringVisibilityLabelServiceImpl.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/ExpAsStringVisibilityLabelServiceImpl.java index 63fe418..32eefe7 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/ExpAsStringVisibilityLabelServiceImpl.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/ExpAsStringVisibilityLabelServiceImpl.java @@ -52,14 +52,14 @@ import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; import org.apache.hadoop.hbase.regionserver.OperationStatus; import org.apache.hadoop.hbase.regionserver.Region; import org.apache.hadoop.hbase.security.User; +import org.apache.hadoop.hbase.security.UserUtil; import org.apache.hadoop.hbase.security.access.AccessControlLists; import org.apache.hadoop.hbase.security.visibility.expression.ExpressionNode; import org.apache.hadoop.hbase.security.visibility.expression.LeafExpressionNode; import org.apache.hadoop.hbase.security.visibility.expression.NonLeafExpressionNode; import org.apache.hadoop.hbase.security.visibility.expression.Operator; import org.apache.hadoop.hbase.util.Bytes; - -import com.google.common.collect.Lists; +import org.apache.hadoop.hbase.util.Pair; /** * This is a VisibilityLabelService where labels in Mutation's visibility @@ -269,7 +269,7 @@ public class ExpAsStringVisibilityLabelServiceImpl implements VisibilityLabelSer for (ScanLabelGenerator scanLabelGenerator : scanLabelGenerators) { try { // null authorizations to be handled inside SLG impl. - authLabels = scanLabelGenerator.getLabels(VisibilityUtils.getActiveUser(), authorizations); + authLabels = scanLabelGenerator.getLabels(UserUtil.getActiveUser(), authorizations); authLabels = (authLabels == null) ? new ArrayList() : authLabels; authorizations = new Authorizations(authLabels); } catch (Throwable t) { @@ -328,7 +328,7 @@ public class ExpAsStringVisibilityLabelServiceImpl implements VisibilityLabelSer } protected boolean isReadFromSystemAuthUser() throws IOException { - User user = VisibilityUtils.getActiveUser(); + User user = UserUtil.getActiveUser(); return havingSystemAuth(user); } @@ -400,48 +400,14 @@ public class ExpAsStringVisibilityLabelServiceImpl implements VisibilityLabelSer } private void initSystemAndSuperUsers() throws IOException { - this.superUsers = new ArrayList(); - this.superGroups = new ArrayList(); - User user = User.getCurrent(); - if (user == null) { - throw new IOException("Unable to obtain the current user, " - + "authorization checks for internal operations will not work correctly!"); - } - if (LOG.isTraceEnabled()) { - LOG.trace("Current user name is " + user.getShortName()); - } - String currentUser = user.getShortName(); - List superUserList = Lists.asList(currentUser, - this.conf.getStrings(AccessControlLists.SUPERUSER_CONF_KEY, new String[0])); - if (superUserList != null) { - for (String name : superUserList) { - if (AccessControlLists.isGroupPrincipal(name)) { - this.superGroups.add(AccessControlLists.getGroupName(name)); - } else { - this.superUsers.add(name); - } - } - }; - } - - protected boolean isSystemOrSuperUser(User user) throws IOException { - if (this.superUsers.contains(user.getShortName())) { - return true; - } - String[] groups = user.getGroupNames(); - if (groups != null) { - for (String group : groups) { - if (this.superGroups.contains(group)) { - return true; - } - } - } - return false; + Pair, List> superUsersAndGroups = UserUtil.getSuperUsers(conf); + this.superUsers = superUsersAndGroups.getFirst(); + this.superGroups = superUsersAndGroups.getSecond(); } @Override public boolean havingSystemAuth(User user) throws IOException { - if (isSystemOrSuperUser(user)) { + if (UserUtil.isSuperUser(user, this.superUsers, this.superGroups)) { return true; } Set auths = new HashSet();