@Override public boolean havingSystemAuth(User user) throws IOException { // A super user has 'system' auth. if (Superusers.isSuperUser(user)) { return true; } // A user can also be explicitly granted 'system' auth. List<String> auths = this.getUserAuths(Bytes.toBytes(user.getShortName()), true); if (LOG.isTraceEnabled()) { LOG.trace("The auths for user " + user.getShortName() + " are " + auths); } if (auths.contains(SYSTEM_LABEL)) { return true; } auths = this.getGroupAuths(user.getGroupNames(), true); if (LOG.isTraceEnabled()) { LOG.trace("The auths for groups of user " + user.getShortName() + " are " + auths); } return auths.contains(SYSTEM_LABEL); }
/** * Returns a new {@code PermissionCache} initialized with permission assignments * from the {@code hbase.superuser} configuration key. */ private PermissionCache<Permission> initGlobal(Configuration conf) throws IOException { UserProvider userProvider = UserProvider.instantiate(conf); User user = userProvider.getCurrent(); if (user == null) { throw new IOException("Unable to obtain the current user, " + "authorization checks for internal operations will not work correctly!"); } PermissionCache<Permission> newCache = new PermissionCache<Permission>(); String currentUser = user.getShortName(); // the system user is always included List<String> superusers = Lists.asList(currentUser, conf.getStrings( Superusers.SUPERUSER_CONF_KEY, new String[0])); if (superusers != null) { for (String name : superusers) { if (AuthUtil.isGroupPrincipal(name)) { newCache.putGroup(AuthUtil.getGroupName(name), new Permission(Permission.Action.values())); } else { newCache.putUser(name, new Permission(Permission.Action.values())); } } } return newCache; }
/** * Returns a 'priority' based on the request type. * * Currently the returned priority is used for queue selection. * See the SimpleRpcScheduler as example. It maintains a queue per 'priory type' * HIGH_QOS (meta requests), REPLICATION_QOS (replication requests), * NORMAL_QOS (user requests). */ @Override public int getPriority(RequestHeader header, Message param, User user) { int priorityByAnnotation = getAnnotatedPriority(header); if (priorityByAnnotation >= 0) { return priorityByAnnotation; } // all requests executed by super users have high QoS try { if (Superusers.isSuperUser(user)) { return HConstants.ADMIN_QOS; } } catch (IllegalStateException ex) { // Not good throwing an exception out of here, a runtime anyways. Let the query go into the // server and have it throw the exception if still an issue. Just mark it normal priority. if (LOG.isTraceEnabled()) LOG.trace("Marking normal priority after getting exception=" + ex); return HConstants.NORMAL_QOS; } return getBasePriority(header, param); }
@Test public void testQosFunctionForRequestCalledBySuperUser() throws Exception { RequestHeader.Builder headerBuilder = RequestHeader.newBuilder(); headerBuilder.setMethodName("foo"); RequestHeader header = headerBuilder.build(); PriorityFunction qosFunc = regionServer.rpcServices.getPriority(); //test superusers regionServer.conf.set(Superusers.SUPERUSER_CONF_KEY, "samplesuperuser"); Superusers.initialize(regionServer.conf); assertEquals(HConstants.ADMIN_QOS, qosFunc.getPriority(header, null, User.createUserForTesting(regionServer.conf, "samplesuperuser", new String[]{"somegroup"}))); //test supergroups regionServer.conf.set(Superusers.SUPERUSER_CONF_KEY, "@samplesupergroup"); Superusers.initialize(regionServer.conf); assertEquals(HConstants.ADMIN_QOS, qosFunc.getPriority(header, null, User.createUserForTesting(regionServer.conf, "regularuser", new String[]{"samplesupergroup"}))); }
private void checkForReservedTagPresence(User user, Mutation m) throws IOException { // No need to check if we're not going to throw if (!authorizationEnabled) { m.setAttribute(TAG_CHECK_PASSED, TRUE); return; } // Superusers are allowed to store cells unconditionally. if (Superusers.isSuperUser(user)) { m.setAttribute(TAG_CHECK_PASSED, TRUE); return; } // We already checked (prePut vs preBatchMutation) if (m.getAttribute(TAG_CHECK_PASSED) != null) { return; } for (CellScanner cellScanner = m.cellScanner(); cellScanner.advance();) { Iterator<Tag> tagsItr = PrivateCellUtil.tagsIterator(cellScanner.current()); while (tagsItr.hasNext()) { if (tagsItr.next().getType() == AccessControlLists.ACL_TAG_TYPE) { throw new AccessDeniedException("Mutation contains cell with reserved type tag"); } } } m.setAttribute(TAG_CHECK_PASSED, TRUE); }
/** * Returns a new {@code PermissionCache} initialized with permission assignments * from the {@code hbase.superuser} configuration key. */ private PermissionCache<Permission> initGlobal(Configuration conf) throws IOException { UserProvider userProvider = UserProvider.instantiate(conf); User user = userProvider.getCurrent(); if (user == null) { throw new IOException("Unable to obtain the current user, " + "authorization checks for internal operations will not work correctly!"); } PermissionCache<Permission> newCache = new PermissionCache<>(); String currentUser = user.getShortName(); // the system user is always included List<String> superusers = Lists.asList(currentUser, conf.getStrings( Superusers.SUPERUSER_CONF_KEY, new String[0])); if (superusers != null) { for (String name : superusers) { if (AuthUtil.isGroupPrincipal(name)) { newCache.putGroup(AuthUtil.getGroupName(name), new Permission(Permission.Action.values())); } else { newCache.putUser(name, new Permission(Permission.Action.values())); } } } return newCache; }
@Test (timeout=180000) public void testGlobalPermissionList() throws Exception { List<UserPermission> perms; Table acl = systemUserConnection.getTable(AccessControlLists.ACL_TABLE_NAME); try { BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW); AccessControlService.BlockingInterface protocol = AccessControlService.newBlockingStub(service); perms = AccessControlUtil.getUserPermissions(null, protocol); } finally { acl.close(); } Collection<String> superUsers = Superusers.getSuperUsers(); List<UserPermission> adminPerms = new ArrayList<>(superUsers.size() + 1); adminPerms.add(new UserPermission(Bytes.toBytes(USER_ADMIN.getShortName()), AccessControlLists.ACL_TABLE_NAME, null, null, Bytes.toBytes("ACRW"))); for(String user: superUsers) { adminPerms.add(new UserPermission(Bytes.toBytes(user), AccessControlLists.ACL_TABLE_NAME, null, null, Action.values())); } assertTrue("Only super users, global users and user admin has permission on table hbase:acl " + "per setup", perms.size() == 5 + superUsers.size() && hasFoundUserPermission(adminPerms, perms)); }
@Override @Deprecated public boolean havingSystemAuth(byte[] user) throws IOException { // Implementation for backward compatibility if (Superusers.isSuperUser(Bytes.toString(user))) { return true; } List<String> auths = this.getUserAuths(user, true); if (LOG.isTraceEnabled()) { LOG.trace("The auths for user " + Bytes.toString(user) + " are " + auths); } return auths.contains(SYSTEM_LABEL); }
private void checkForReservedTagPresence(User user, Mutation m) throws IOException { // No need to check if we're not going to throw if (!authorizationEnabled) { m.setAttribute(TAG_CHECK_PASSED, TRUE); return; } // Superusers are allowed to store cells unconditionally. if (Superusers.isSuperUser(user)) { m.setAttribute(TAG_CHECK_PASSED, TRUE); return; } // We already checked (prePut vs preBatchMutation) if (m.getAttribute(TAG_CHECK_PASSED) != null) { return; } for (CellScanner cellScanner = m.cellScanner(); cellScanner.advance();) { Cell cell = cellScanner.current(); if (cell.getTagsLength() > 0) { Iterator<Tag> tagsItr = CellUtil.tagsIterator(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength()); while (tagsItr.hasNext()) { if (tagsItr.next().getType() == AccessControlLists.ACL_TAG_TYPE) { throw new AccessDeniedException("Mutation contains cell with reserved type tag"); } } } } m.setAttribute(TAG_CHECK_PASSED, TRUE); }
private void checkSystemOrSuperUser() throws IOException { // No need to check if we're not going to throw if (!authorizationEnabled) { return; } User activeUser = getActiveUser(); if (!Superusers.isSuperUser(activeUser)) { throw new AccessDeniedException("User '" + (activeUser != null ? activeUser.getShortName() : "null") + "is not system or super user."); } }
@Override public boolean havingSystemAuth(User user) throws IOException { if (Superusers.isSuperUser(user)) { return true; } Set<String> auths = new HashSet<String>(); auths.addAll(this.getUserAuths(Bytes.toBytes(user.getShortName()), true)); auths.addAll(this.getGroupAuths(user.getGroupNames(), true)); return auths.contains(SYSTEM_LABEL); }
public static ArrayList<ACL> createACL(ZooKeeperWatcher zkw, String node, boolean isSecureZooKeeper) { if (!node.startsWith(zkw.baseZNode)) { return Ids.OPEN_ACL_UNSAFE; } if (isSecureZooKeeper) { ArrayList<ACL> acls = new ArrayList<ACL>(); // add permission to hbase supper user String[] superUsers = zkw.getConfiguration().getStrings(Superusers.SUPERUSER_CONF_KEY); if (superUsers != null) { List<String> groups = new ArrayList<String>(); for (String user : superUsers) { if (user.startsWith(AuthUtil.GROUP_PREFIX)) { // TODO: Set node ACL for groups when ZK supports this feature groups.add(user); } else { acls.add(new ACL(Perms.ALL, new Id("auth", user))); } } if (!groups.isEmpty()) { LOG.warn("Znode ACL setting for group " + groups + " is skipped, Zookeeper doesn't support this feature presently."); } } // Certain znodes are accessed directly by the client, // so they must be readable by non-authenticated clients if (zkw.isClientReadable(node)) { acls.addAll(Ids.CREATOR_ALL_ACL); acls.addAll(Ids.READ_ACL_UNSAFE); } else { acls.addAll(Ids.CREATOR_ALL_ACL); } return acls; } else { return Ids.OPEN_ACL_UNSAFE; } }
@Test public void testCreateACL() throws ZooKeeperConnectionException, IOException { Configuration conf = HBaseConfiguration.create(); conf.set(Superusers.SUPERUSER_CONF_KEY, "user1,@group1,user2,@group2,user3"); String node = "/hbase/testCreateACL"; ZooKeeperWatcher watcher = new ZooKeeperWatcher(conf, node, null, false); List<ACL> aclList = ZKUtil.createACL(watcher, node, true); Assert.assertEquals(aclList.size(), 4); // 3+1, since ACL will be set for the creator by default Assert.assertTrue(!aclList.contains(new ACL(Perms.ALL, new Id("auth", "@group1"))) && !aclList.contains(new ACL(Perms.ALL, new Id("auth", "@group2")))); Assert.assertTrue(aclList.contains(new ACL(Perms.ALL, new Id("auth", "user1"))) && aclList.contains(new ACL(Perms.ALL, new Id("auth", "user2"))) && aclList.contains(new ACL(Perms.ALL, new Id("auth", "user3")))); }
private Configuration setupConf() throws IOException { final Configuration conf = HBaseConfiguration.create(); VisibilityTestUtil.enableVisiblityLabels(conf); conf.set(Superusers.SUPERUSER_CONF_KEY, ADMIN_USERNAME); conf.setInt(HFile.FORMAT_VERSION_KEY, HFile.MIN_FORMAT_VERSION_WITH_TAGS); conf.set(JTConfig.JT_IPC_ADDRESS, JTConfig.LOCAL_FRAMEWORK_NAME); conf.set(CommonConfigurationKeysPublic.FS_DEFAULT_NAME_KEY, CommonConfigurationKeysPublic.FS_DEFAULT_NAME_DEFAULT); conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class, ScanLabelGenerator.class); conf.set(HConstants.REPLICATION_CODEC_CONF_KEY, KeyValueCodecWithTags.class.getName()); return conf; }
private void checkSystemOrSuperUser(User activeUser) throws IOException { // No need to check if we're not going to throw if (!authorizationEnabled) { return; } if (!Superusers.isSuperUser(activeUser)) { throw new AccessDeniedException("User '" + (activeUser != null ? activeUser.getShortName() : "null") + "' is not system or super user."); } }
@Override public boolean havingSystemAuth(User user) throws IOException { if (Superusers.isSuperUser(user)) { return true; } Set<String> auths = new HashSet<>(); auths.addAll(this.getUserAuths(Bytes.toBytes(user.getShortName()), true)); auths.addAll(this.getGroupAuths(user.getGroupNames(), true)); return auths.contains(SYSTEM_LABEL); }
@Test public void testUnsecure() throws ZooKeeperConnectionException, IOException { Configuration conf = HBaseConfiguration.create(); conf.set(Superusers.SUPERUSER_CONF_KEY, "user1"); String node = "/hbase/testUnsecure"; ZKWatcher watcher = new ZKWatcher(conf, node, null, false); List<ACL> aclList = ZKUtil.createACL(watcher, node, false); assertEquals(1, aclList.size()); assertTrue(aclList.contains(Ids.OPEN_ACL_UNSAFE.iterator().next())); }
@Test public void testSecuritySingleSuperuser() throws ZooKeeperConnectionException, IOException { Configuration conf = HBaseConfiguration.create(); conf.set(Superusers.SUPERUSER_CONF_KEY, "user1"); String node = "/hbase/testSecuritySingleSuperuser"; ZKWatcher watcher = new ZKWatcher(conf, node, null, false); List<ACL> aclList = ZKUtil.createACL(watcher, node, true); assertEquals(2, aclList.size()); // 1+1, since ACL will be set for the creator by default assertTrue(aclList.contains(new ACL(Perms.ALL, new Id("sasl", "user1")))); assertTrue(aclList.contains(Ids.CREATOR_ALL_ACL.iterator().next())); }
@Test public void testCreateACL() throws ZooKeeperConnectionException, IOException { Configuration conf = HBaseConfiguration.create(); conf.set(Superusers.SUPERUSER_CONF_KEY, "user1,@group1,user2,@group2,user3"); String node = "/hbase/testCreateACL"; ZKWatcher watcher = new ZKWatcher(conf, node, null, false); List<ACL> aclList = ZKUtil.createACL(watcher, node, true); assertEquals(4, aclList.size()); // 3+1, since ACL will be set for the creator by default assertFalse(aclList.contains(new ACL(Perms.ALL, new Id("sasl", "@group1")))); assertFalse(aclList.contains(new ACL(Perms.ALL, new Id("sasl", "@group2")))); assertTrue(aclList.contains(new ACL(Perms.ALL, new Id("sasl", "user1")))); assertTrue(aclList.contains(new ACL(Perms.ALL, new Id("sasl", "user2")))); assertTrue(aclList.contains(new ACL(Perms.ALL, new Id("sasl", "user3")))); }
@Test public void testCreateACLWithSameUser() throws ZooKeeperConnectionException, IOException { Configuration conf = HBaseConfiguration.create(); conf.set(Superusers.SUPERUSER_CONF_KEY, "user4,@group1,user5,user6"); UserGroupInformation.setLoginUser(UserGroupInformation.createRemoteUser("user4")); String node = "/hbase/testCreateACL"; ZKWatcher watcher = new ZKWatcher(conf, node, null, false); List<ACL> aclList = ZKUtil.createACL(watcher, node, true); assertEquals(3, aclList.size()); // 3, since service user the same as one of superuser assertFalse(aclList.contains(new ACL(Perms.ALL, new Id("sasl", "@group1")))); assertTrue(aclList.contains(new ACL(Perms.ALL, new Id("auth", "")))); assertTrue(aclList.contains(new ACL(Perms.ALL, new Id("sasl", "user5")))); assertTrue(aclList.contains(new ACL(Perms.ALL, new Id("sasl", "user6")))); }
private boolean isSystemOrSuperUser() throws IOException { return Superusers.isSuperUser(VisibilityUtils.getActiveUser()); }
/** * Checks whether the ACLs returned from the base znode (/hbase) is set for secure setup. * @param acls acls from zookeeper * @return whether ACLs are set for the base znode * @throws IOException */ private boolean isBaseZnodeAclSetup(List<ACL> acls) throws IOException { if (LOG.isDebugEnabled()) { LOG.debug("Checking znode ACLs"); } String[] superUsers = conf.getStrings(Superusers.SUPERUSER_CONF_KEY); // Check whether ACL set for all superusers if (superUsers != null && !checkACLForSuperUsers(superUsers, acls)) { return false; } // this assumes that current authenticated user is the same as zookeeper client user // configured via JAAS String hbaseUser = UserGroupInformation.getCurrentUser().getShortUserName(); if (acls.isEmpty()) { if (LOG.isDebugEnabled()) { LOG.debug("ACL is empty"); } return false; } for (ACL acl : acls) { int perms = acl.getPerms(); Id id = acl.getId(); // We should only set at most 3 possible ACLs for 3 Ids. One for everyone, one for superuser // and one for the hbase user if (Ids.ANYONE_ID_UNSAFE.equals(id)) { if (perms != Perms.READ) { if (LOG.isDebugEnabled()) { LOG.debug(String.format("permissions for '%s' are not correct: have 0x%x, want 0x%x", id, perms, Perms.READ)); } return false; } } else if (superUsers != null && isSuperUserId(superUsers, id)) { if (perms != Perms.ALL) { if (LOG.isDebugEnabled()) { LOG.debug(String.format("permissions for '%s' are not correct: have 0x%x, want 0x%x", id, perms, Perms.ALL)); } return false; } } else if ("sasl".equals(id.getScheme())) { String name = id.getId(); // If ZooKeeper recorded the Kerberos full name in the ACL, use only the shortname Matcher match = NAME_PATTERN.matcher(name); if (match.matches()) { name = match.group(1); } if (name.equals(hbaseUser)) { if (perms != Perms.ALL) { if (LOG.isDebugEnabled()) { LOG.debug(String.format("permissions for '%s' are not correct: have 0x%x, want 0x%x", id, perms, Perms.ALL)); } return false; } } else { if (LOG.isDebugEnabled()) { LOG.debug("Unexpected shortname in SASL ACL: " + id); } return false; } } else { if (LOG.isDebugEnabled()) { LOG.debug("unexpected ACL id '" + id + "'"); } return false; } } return true; }
public User getRequestUser() { return RpcServer.getRequestUser().orElse(Superusers.getSystemUser()); }
/** * Checks whether the ACLs returned from the base znode (/hbase) is set for secure setup. * @param acls acls from zookeeper * @return whether ACLs are set for the base znode * @throws IOException if getting the current user fails */ private boolean isBaseZnodeAclSetup(List<ACL> acls) throws IOException { if (LOG.isDebugEnabled()) { LOG.debug("Checking znode ACLs"); } String[] superUsers = conf.getStrings(Superusers.SUPERUSER_CONF_KEY); // Check whether ACL set for all superusers if (superUsers != null && !checkACLForSuperUsers(superUsers, acls)) { return false; } // this assumes that current authenticated user is the same as zookeeper client user // configured via JAAS String hbaseUser = UserGroupInformation.getCurrentUser().getShortUserName(); if (acls.isEmpty()) { if (LOG.isDebugEnabled()) { LOG.debug("ACL is empty"); } return false; } for (ACL acl : acls) { int perms = acl.getPerms(); Id id = acl.getId(); // We should only set at most 3 possible ACLs for 3 Ids. One for everyone, one for superuser // and one for the hbase user if (Ids.ANYONE_ID_UNSAFE.equals(id)) { if (perms != Perms.READ) { if (LOG.isDebugEnabled()) { LOG.debug(String.format("permissions for '%s' are not correct: have 0x%x, want 0x%x", id, perms, Perms.READ)); } return false; } } else if (superUsers != null && isSuperUserId(superUsers, id)) { if (perms != Perms.ALL) { if (LOG.isDebugEnabled()) { LOG.debug(String.format("permissions for '%s' are not correct: have 0x%x, want 0x%x", id, perms, Perms.ALL)); } return false; } } else if ("sasl".equals(id.getScheme())) { String name = id.getId(); // If ZooKeeper recorded the Kerberos full name in the ACL, use only the shortname Matcher match = NAME_PATTERN.matcher(name); if (match.matches()) { name = match.group(1); } if (name.equals(hbaseUser)) { if (perms != Perms.ALL) { if (LOG.isDebugEnabled()) { LOG.debug(String.format("permissions for '%s' are not correct: have 0x%x, want 0x%x", id, perms, Perms.ALL)); } return false; } } else { if (LOG.isDebugEnabled()) { LOG.debug("Unexpected shortname in SASL ACL: " + id); } return false; } } else { if (LOG.isDebugEnabled()) { LOG.debug("unexpected ACL id '" + id + "'"); } return false; } } return true; }
public static ArrayList<ACL> createACL(ZKWatcher zkw, String node, boolean isSecureZooKeeper) { if (!node.startsWith(zkw.znodePaths.baseZNode)) { return Ids.OPEN_ACL_UNSAFE; } if (isSecureZooKeeper) { ArrayList<ACL> acls = new ArrayList<>(); // add permission to hbase supper user String[] superUsers = zkw.getConfiguration().getStrings(Superusers.SUPERUSER_CONF_KEY); String hbaseUser = null; try { hbaseUser = UserGroupInformation.getCurrentUser().getShortUserName(); } catch (IOException e) { LOG.debug("Could not acquire current User.", e); } if (superUsers != null) { List<String> groups = new ArrayList<>(); for (String user : superUsers) { if (AuthUtil.isGroupPrincipal(user)) { // TODO: Set node ACL for groups when ZK supports this feature groups.add(user); } else { if(!user.equals(hbaseUser)) { acls.add(new ACL(Perms.ALL, new Id("sasl", user))); } } } if (!groups.isEmpty()) { LOG.warn("Znode ACL setting for group " + groups + " is skipped, ZooKeeper doesn't support this feature presently."); } } // Certain znodes are accessed directly by the client, // so they must be readable by non-authenticated clients if (zkw.znodePaths.isClientReadable(node)) { acls.addAll(Ids.CREATOR_ALL_ACL); acls.addAll(Ids.READ_ACL_UNSAFE); } else { acls.addAll(Ids.CREATOR_ALL_ACL); } return acls; } else { return Ids.OPEN_ACL_UNSAFE; } }