@Test public void testSuperIsSuper() throws Exception { ZooKeeper zk = createClient(); try { zk.create("/digest_read", null, Arrays.asList(new ACL(Perms.READ, otherDigestUser)), CreateMode.PERSISTENT); zk.create("/digest_read/sub", null, Arrays.asList(new ACL(Perms.READ, otherDigestUser)), CreateMode.PERSISTENT); zk.create("/sasl_read", null, Arrays.asList(new ACL(Perms.READ, otherSaslUser)), CreateMode.PERSISTENT); zk.create("/sasl_read/sub", null, Arrays.asList(new ACL(Perms.READ, otherSaslUser)), CreateMode.PERSISTENT); zk.delete("/digest_read/sub", -1); zk.delete("/digest_read", -1); zk.delete("/sasl_read/sub", -1); zk.delete("/sasl_read", -1); //If the test failes it will most likely fail with a NoAuth exception before it ever gets to this assertion Assert.assertEquals(authFailed.get(), 0); } finally { zk.close(); } }
private boolean checkACLForSuperUsers(String[] superUsers, List<ACL> acls) { for (String user : superUsers) { boolean hasAccess = false; // TODO: Validate super group members also when ZK supports setting node ACL for groups. if (!user.startsWith(AuthUtil.GROUP_PREFIX)) { for (ACL acl : acls) { if (user.equals(acl.getId().getId())) { if (acl.getPerms() == Perms.ALL) { hasAccess = true; } else { if (LOG.isDebugEnabled()) { LOG.debug(String.format( "superuser '%s' does not have correct permissions: have 0x%x, want 0x%x", acl.getId().getId(), acl.getPerms(), Perms.ALL)); } } break; } } if (!hasAccess) { return false; } } } return true; }
/** * * @return */ public List<ACL> getCreateNodeAcls() { List<ACL> listAcls = new ArrayList<ACL>(3); try { Id id = new Id(PropertiesDynLoading.authScheme, DigestAuthenticationProvider.generateDigest(PropertiesDynLoading.accessKey)); ACL acl = new ACL(Perms.CREATE, id); listAcls.add(acl); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return Ids.OPEN_ACL_UNSAFE; } return listAcls; }
private boolean checkACLForSuperUsers(String[] superUsers, List<ACL> acls) { for (String user : superUsers) { boolean hasAccess = false; // TODO: Validate super group members also when ZK supports setting node ACL for groups. if (!AuthUtil.isGroupPrincipal(user)) { for (ACL acl : acls) { if (user.equals(acl.getId().getId())) { if (acl.getPerms() == Perms.ALL) { hasAccess = true; } else { if (LOG.isDebugEnabled()) { LOG.debug(String.format( "superuser '%s' does not have correct permissions: have 0x%x, want 0x%x", acl.getId().getId(), acl.getPerms(), Perms.ALL)); } } break; } } if (!hasAccess) { return false; } } } return true; }
@Test public void testRemoveSpecificPerms() { int perms = Perms.ALL; int remove = Perms.CREATE; int newPerms = ZKUtil.removeSpecificPerms(perms, remove); assertEquals("Removal failed", 0, newPerms & Perms.CREATE); }
private void assertZnodePerms(RecoverableZooKeeper zk, String znode, boolean expectedWorldReadable) throws KeeperException, InterruptedException { Stat stat = new Stat(); List<ACL> acls = zk.getZooKeeper().getACL(znode, stat); String[] superUsers = superUser == null ? null : superUser.split(","); LOG.info("Checking ACLs for znode znode:" + znode + " acls:" + acls); for (ACL acl : acls) { int perms = acl.getPerms(); Id id = acl.getId(); // We should only set at most 3 possible ACL for 3 Ids. One for everyone, one for superuser // and one for the hbase user if (Ids.ANYONE_ID_UNSAFE.equals(id)) { // everyone should be set only if we are expecting this znode to be world readable assertTrue(expectedWorldReadable); // assert that anyone can only read assertEquals(perms, Perms.READ); } else if (superUsers != null && ZooKeeperWatcher.isSuperUserId(superUsers, id)) { // assert that super user has all the permissions assertEquals(perms, Perms.ALL); } else if (new Id("sasl", masterPrincipal).equals(id)) { // hbase.master.kerberos.principal? assertEquals(perms, Perms.ALL); } else { fail("An ACL is found which is not expected for the znode:" + znode + " , ACL:" + acl); } } }
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")))); }
public List<ACL> getAdminAcls() { List<ACL> listAcls = new ArrayList<ACL>(3); try { Id id = new Id(PropertiesDynLoading.authScheme, DigestAuthenticationProvider.generateDigest(PropertiesDynLoading.accessKey)); ACL acl = new ACL(Perms.ALL, id); listAcls.add(acl); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return Ids.OPEN_ACL_UNSAFE; } return listAcls; }
@Test public void createNodeWithSpecificAccess() throws Exception { CreateOperation create = new CreateOperation(connection, "/four"); create.setData(testPayload.getBytes()); List<ACL> perms = Collections.singletonList(new ACL(Perms.CREATE, Ids.ANYONE_ID_UNSAFE)); create.setPermissions(perms); OperationResult<String> result = create.get(); assertEquals("/four", result.getResult()); verifyAccessControlList("/four", perms); }
private static ArrayList<ACL> createACL(ZooKeeperWatcher zkw, String node) { if (!node.startsWith(zkw.baseZNode)) { return Ids.OPEN_ACL_UNSAFE; } if (isSecureZooKeeper(zkw.getConfiguration())) { String superUser = zkw.getConfiguration().get("hbase.superuser"); ArrayList<ACL> acls = new ArrayList<ACL>(); // add permission to hbase supper user if (superUser != null) { acls.add(new ACL(Perms.ALL, new Id("auth", superUser))); } // Certain znodes are accessed directly by the client, // so they must be readable by non-authenticated clients if ((node.equals(zkw.baseZNode) == true) || (node.equals(zkw.metaServerZNode) == true) || (node.equals(zkw.getMasterAddressZNode()) == true) || (node.equals(zkw.clusterIdZNode) == true) || (node.equals(zkw.rsZNode) == true) || (node.equals(zkw.backupMasterAddressesZNode) == true) || (node.startsWith(zkw.assignmentZNode) == true) || (node.startsWith(zkw.tableZNode) == true)) { 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 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 SASLOwnerACLProvider(String principal) { this.saslACL = Collections.singletonList( new ACL(Perms.ALL, new Id("sasl", principal))); }
/** * 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; }