/** * 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(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())); } } } return newCache; }
public boolean matchPermission( User user, byte[] table, byte[] family, byte[] qualifier, TablePermission.Action action) { PermissionCache<TablePermission> tablePerms = tableCache.get(table); if (tablePerms != null) { List<TablePermission> userPerms = tablePerms.getUser(user.getShortName()); if (userPerms != null) { for (TablePermission p : userPerms) { if (p.matchesFamilyQualifier(table, family, qualifier, action)) { return true; } } } String[] groups = user.getGroupNames(); if (groups != null) { for (String group : groups) { List<TablePermission> groupPerms = tablePerms.getGroup(group); if (groupPerms != null) { for (TablePermission p : groupPerms) { if (p.matchesFamilyQualifier(table, family, qualifier, action)) { return true; } } } } } } return false; }
private Path createStagingDir(Path baseDir, User user, TableName tableName) throws IOException { String tblName = tableName.getNameAsString().replace(":", "_"); String randomDir = user.getShortName() + "__" + tblName + "__" + (new BigInteger(RANDOM_WIDTH, random).toString(RANDOM_RADIX)); return createStagingDir(baseDir, user, randomDir); }
@Test public void testCreateWithCorrectOwner() throws Exception { // Create a test user final User testUser = User.createUserForTesting(TEST_UTIL.getConfiguration(), "TestUser", new String[0]); // Grant the test user the ability to create tables SecureTestUtil.grantGlobal(TEST_UTIL, testUser.getShortName(), Action.CREATE); verifyAllowed( new AccessTestAction() { @Override public Object run() throws Exception { HTableDescriptor desc = new HTableDescriptor(TEST_TABLE.getTableName()); desc.addFamily(new HColumnDescriptor(TEST_FAMILY)); try (Connection connection = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration(), testUser)) { try (Admin admin = connection.getAdmin()) { admin.createTable(desc); } } return null; } }, testUser); TEST_UTIL.waitTableEnabled(TEST_TABLE.getTableName()); // Verify that owner permissions have been granted to the test user on the // table just created List<TablePermission> perms = AccessControlLists.getTablePermissions(conf, TEST_TABLE.getTableName()) .get(testUser.getShortName()); assertNotNull(perms); assertFalse(perms.isEmpty()); // Should be RWXCA assertTrue(perms.get(0).implies(Permission.Action.READ)); assertTrue(perms.get(0).implies(Permission.Action.WRITE)); assertTrue(perms.get(0).implies(Permission.Action.EXEC)); assertTrue(perms.get(0).implies(Permission.Action.CREATE)); assertTrue(perms.get(0).implies(Permission.Action.ADMIN)); }
private User getActiveUser() { User user = RequestContext.getRequestUser(); if (!RequestContext.isInRequestContext()) { return null; } // this is for testing if (userProvider.isHadoopSecurityEnabled() && "simple".equalsIgnoreCase(conf.get(User.HBASE_SECURITY_CONF_KEY))) { return User.createUserForTesting(conf, user.getShortName(), new String[] {}); } return user; }
public boolean authorize( User user, byte[] table, byte[] family, byte[] qualifier, Permission.Action action) { if (authorizeUser(user.getShortName(), table, family, qualifier, action)) { return true; } String[] groups = user.getGroupNames(); if (groups != null) { for (String group : groups) { if (authorizeGroup(group, table, family, action)) { return true; } } } return false; }
@Override public void whoAmI( RpcController controller, AuthenticationProtos.WhoAmIRequest request, RpcCallback<AuthenticationProtos.WhoAmIResponse> done) { User requestUser = RequestContext.getRequestUser(); AuthenticationProtos.WhoAmIResponse.Builder response = AuthenticationProtos.WhoAmIResponse.newBuilder(); if (requestUser != null) { response.setUsername(requestUser.getShortName()); AuthenticationMethod method = requestUser.getUGI().getAuthenticationMethod(); if (method != null) { response.setAuthMethod(method.name()); } } done.run(response.build()); }
/** * Authorize a global permission based on ACLs for the given user and the user's groups. * * @param user * @param action * @return */ public boolean authorize(User user, Permission.Action action) { if (user == null) { return false; } if (authorize(globalCache.getUser(user.getShortName()), action)) { return true; } String[] groups = user.getGroupNames(); if (groups != null) { for (String group : groups) { if (authorize(globalCache.getGroup(group), action)) { return true; } } } return false; }
public boolean authorize(User user, byte[] table, KeyValue kv, TablePermission.Action action) { PermissionCache<TablePermission> tablePerms = tableCache.get(table); if (tablePerms != null) { List<TablePermission> userPerms = tablePerms.getUser(user.getShortName()); if (authorize(userPerms, table, kv, action)) { return true; } String[] groupNames = user.getGroupNames(); if (groupNames != null) { for (String group : groupNames) { List<TablePermission> groupPerms = tablePerms.getGroup(group); if (authorize(groupPerms, table, kv, action)) { return true; } } } } return false; }
/** * Take a snapshot based on the enabled/disabled state of the table. * * @param snapshot * @throws HBaseSnapshotException when a snapshot specific exception occurs. * @throws IOException when some sort of generic IO exception occurs. */ public void takeSnapshot(SnapshotDescription snapshot) throws IOException { // check to see if we already completed the snapshot if (isSnapshotCompleted(snapshot)) { throw new SnapshotExistsException( "Snapshot '" + snapshot.getName() + "' already stored on the filesystem.", ProtobufUtil.createSnapshotDesc(snapshot)); } LOG.debug("No existing snapshot, attempting snapshot..."); // stop tracking "abandoned" handlers cleanupSentinels(); // check to see if the table exists HTableDescriptor desc = null; try { desc = master.getTableDescriptors().get(TableName.valueOf(snapshot.getTable())); } catch (FileNotFoundException e) { String msg = "Table:" + snapshot.getTable() + " info doesn't exist!"; LOG.error(msg); throw new SnapshotCreationException(msg, e, ProtobufUtil.createSnapshotDesc(snapshot)); } catch (IOException e) { throw new SnapshotCreationException( "Error while geting table description for table " + snapshot.getTable(), e, ProtobufUtil.createSnapshotDesc(snapshot)); } if (desc == null) { throw new SnapshotCreationException( "Table '" + snapshot.getTable() + "' doesn't exist, can't take snapshot.", ProtobufUtil.createSnapshotDesc(snapshot)); } SnapshotDescription.Builder builder = snapshot.toBuilder(); // if not specified, set the snapshot format if (!snapshot.hasVersion()) { builder.setVersion(SnapshotDescriptionUtils.SNAPSHOT_LAYOUT_VERSION); } User user = RpcServer.getRequestUser(); if (User.isHBaseSecurityEnabled(master.getConfiguration()) && user != null) { builder.setOwner(user.getShortName()); } snapshot = builder.build(); // call pre coproc hook MasterCoprocessorHost cpHost = master.getMasterCoprocessorHost(); if (cpHost != null) { cpHost.preSnapshot(snapshot, desc); } // if the table is enabled, then have the RS run actually the snapshot work TableName snapshotTable = TableName.valueOf(snapshot.getTable()); if (master.getTableStateManager().isTableState(snapshotTable, TableState.State.ENABLED)) { LOG.debug("Table enabled, starting distributed snapshot."); snapshotEnabledTable(snapshot); LOG.debug("Started snapshot: " + ClientSnapshotDescriptionUtils.toString(snapshot)); } // For disabled table, snapshot is created by the master else if (master.getTableStateManager().isTableState(snapshotTable, TableState.State.DISABLED)) { LOG.debug("Table is disabled, running snapshot entirely on master."); snapshotDisabledTable(snapshot); LOG.debug("Started snapshot: " + ClientSnapshotDescriptionUtils.toString(snapshot)); } else { LOG.error( "Can't snapshot table '" + snapshot.getTable() + "', isn't open or closed, we don't know what to do!"); TablePartiallyOpenException tpoe = new TablePartiallyOpenException(snapshot.getTable() + " isn't fully open."); throw new SnapshotCreationException( "Table is not entirely open or closed", tpoe, ProtobufUtil.createSnapshotDesc(snapshot)); } // call post coproc hook if (cpHost != null) { cpHost.postSnapshot(snapshot, desc); } }
@BeforeClass public static void beforeClass() throws Exception { conf = UTIL.getConfiguration(); enableSecurity(conf); SUPERUSER = User.createUserForTesting(conf, "admin", new String[] {"supergroup"}); // Users with global permissions USER_GLOBAL_ADMIN = User.createUserForTesting(conf, "global_admin", new String[0]); USER_GLOBAL_CREATE = User.createUserForTesting(conf, "global_create", new String[0]); USER_GLOBAL_WRITE = User.createUserForTesting(conf, "global_write", new String[0]); USER_GLOBAL_READ = User.createUserForTesting(conf, "global_read", new String[0]); USER_GLOBAL_EXEC = User.createUserForTesting(conf, "global_exec", new String[0]); USER_NS_ADMIN = User.createUserForTesting(conf, "namespace_admin", new String[0]); USER_NS_CREATE = User.createUserForTesting(conf, "namespace_create", new String[0]); USER_NS_WRITE = User.createUserForTesting(conf, "namespace_write", new String[0]); USER_NS_READ = User.createUserForTesting(conf, "namespace_read", new String[0]); USER_NS_EXEC = User.createUserForTesting(conf, "namespace_exec", new String[0]); USER_TABLE_CREATE = User.createUserForTesting(conf, "table_create", new String[0]); USER_TABLE_WRITE = User.createUserForTesting(conf, "table_write", new String[0]); USER_GROUP_ADMIN = User.createUserForTesting(conf, "user_group_admin", new String[] {GROUP_ADMIN}); USER_GROUP_NS_ADMIN = User.createUserForTesting(conf, "user_group_ns_admin", new String[] {GROUP_NS_ADMIN}); USER_GROUP_CREATE = User.createUserForTesting(conf, "user_group_create", new String[] {GROUP_CREATE}); USER_GROUP_READ = User.createUserForTesting(conf, "user_group_read", new String[] {GROUP_READ}); USER_GROUP_WRITE = User.createUserForTesting(conf, "user_group_write", new String[] {GROUP_WRITE}); // TODO: other table perms UTIL.startMiniCluster(); // Wait for the ACL table to become available UTIL.waitTableAvailable(AccessControlLists.ACL_TABLE_NAME.getName(), 30 * 1000); ACCESS_CONTROLLER = (AccessController) UTIL.getMiniHBaseCluster() .getMaster() .getRegionServerCoprocessorHost() .findCoprocessor(AccessController.class.getName()); UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE).build()); UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE2).build()); // grants on global grantGlobal(UTIL, USER_GLOBAL_ADMIN.getShortName(), Permission.Action.ADMIN); grantGlobal(UTIL, USER_GLOBAL_CREATE.getShortName(), Permission.Action.CREATE); grantGlobal(UTIL, USER_GLOBAL_WRITE.getShortName(), Permission.Action.WRITE); grantGlobal(UTIL, USER_GLOBAL_READ.getShortName(), Permission.Action.READ); grantGlobal(UTIL, USER_GLOBAL_EXEC.getShortName(), Permission.Action.EXEC); // grants on namespace grantOnNamespace(UTIL, USER_NS_ADMIN.getShortName(), TEST_NAMESPACE, Permission.Action.ADMIN); grantOnNamespace(UTIL, USER_NS_CREATE.getShortName(), TEST_NAMESPACE, Permission.Action.CREATE); grantOnNamespace(UTIL, USER_NS_WRITE.getShortName(), TEST_NAMESPACE, Permission.Action.WRITE); grantOnNamespace(UTIL, USER_NS_READ.getShortName(), TEST_NAMESPACE, Permission.Action.READ); grantOnNamespace(UTIL, USER_NS_EXEC.getShortName(), TEST_NAMESPACE, Permission.Action.EXEC); grantOnNamespace(UTIL, toGroupEntry(GROUP_NS_ADMIN), TEST_NAMESPACE, Permission.Action.ADMIN); grantOnNamespace(UTIL, USER_NS_ADMIN.getShortName(), TEST_NAMESPACE2, Permission.Action.ADMIN); grantGlobal(UTIL, toGroupEntry(GROUP_ADMIN), Permission.Action.ADMIN); grantGlobal(UTIL, toGroupEntry(GROUP_CREATE), Permission.Action.CREATE); grantGlobal(UTIL, toGroupEntry(GROUP_READ), Permission.Action.READ); grantGlobal(UTIL, toGroupEntry(GROUP_WRITE), Permission.Action.WRITE); }
@Test public void testACLTableAccess() throws Exception { final Configuration conf = TEST_UTIL.getConfiguration(); // Superuser User superUser = User.createUserForTesting(conf, "admin", new String[] {"supergroup"}); // Global users User globalRead = User.createUserForTesting(conf, "globalRead", new String[0]); User globalWrite = User.createUserForTesting(conf, "globalWrite", new String[0]); User globalCreate = User.createUserForTesting(conf, "globalCreate", new String[0]); User globalAdmin = User.createUserForTesting(conf, "globalAdmin", new String[0]); SecureTestUtil.grantGlobal(TEST_UTIL, globalRead.getShortName(), Action.READ); SecureTestUtil.grantGlobal(TEST_UTIL, globalWrite.getShortName(), Action.WRITE); SecureTestUtil.grantGlobal(TEST_UTIL, globalCreate.getShortName(), Action.CREATE); SecureTestUtil.grantGlobal(TEST_UTIL, globalAdmin.getShortName(), Action.ADMIN); // Namespace users User nsRead = User.createUserForTesting(conf, "nsRead", new String[0]); User nsWrite = User.createUserForTesting(conf, "nsWrite", new String[0]); User nsCreate = User.createUserForTesting(conf, "nsCreate", new String[0]); User nsAdmin = User.createUserForTesting(conf, "nsAdmin", new String[0]); SecureTestUtil.grantOnNamespace( TEST_UTIL, nsRead.getShortName(), TEST_TABLE.getTableName().getNamespaceAsString(), Action.READ); SecureTestUtil.grantOnNamespace( TEST_UTIL, nsWrite.getShortName(), TEST_TABLE.getTableName().getNamespaceAsString(), Action.WRITE); SecureTestUtil.grantOnNamespace( TEST_UTIL, nsCreate.getShortName(), TEST_TABLE.getTableName().getNamespaceAsString(), Action.CREATE); SecureTestUtil.grantOnNamespace( TEST_UTIL, nsAdmin.getShortName(), TEST_TABLE.getTableName().getNamespaceAsString(), Action.ADMIN); // Table users User tableRead = User.createUserForTesting(conf, "tableRead", new String[0]); User tableWrite = User.createUserForTesting(conf, "tableWrite", new String[0]); User tableCreate = User.createUserForTesting(conf, "tableCreate", new String[0]); User tableAdmin = User.createUserForTesting(conf, "tableAdmin", new String[0]); SecureTestUtil.grantOnTable( TEST_UTIL, tableRead.getShortName(), TEST_TABLE.getTableName(), null, null, Action.READ); SecureTestUtil.grantOnTable( TEST_UTIL, tableWrite.getShortName(), TEST_TABLE.getTableName(), null, null, Action.WRITE); SecureTestUtil.grantOnTable( TEST_UTIL, tableCreate.getShortName(), TEST_TABLE.getTableName(), null, null, Action.CREATE); SecureTestUtil.grantOnTable( TEST_UTIL, tableAdmin.getShortName(), TEST_TABLE.getTableName(), null, null, Action.ADMIN); // Write tests AccessTestAction writeAction = new AccessTestAction() { @Override public Object run() throws Exception { try (Connection conn = ConnectionFactory.createConnection(conf); Table t = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) { t.put( new Put(TEST_ROW) .add(AccessControlLists.ACL_LIST_FAMILY, TEST_QUALIFIER, TEST_VALUE)); return null; } finally { } } }; // All writes to ACL table denied except for GLOBAL WRITE permission and superuser verifyDenied(writeAction, globalAdmin, globalCreate, globalRead); verifyDenied(writeAction, nsAdmin, nsCreate, nsRead, nsWrite); verifyDenied(writeAction, tableAdmin, tableCreate, tableRead, tableWrite); verifyAllowed(writeAction, superUser, globalWrite); // Read tests AccessTestAction scanAction = new AccessTestAction() { @Override public Object run() throws Exception { try (Connection conn = ConnectionFactory.createConnection(conf); Table t = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) { ResultScanner s = t.getScanner(new Scan()); try { for (Result r = s.next(); r != null; r = s.next()) { // do nothing } } finally { s.close(); } return null; } } }; // All reads from ACL table denied except for GLOBAL READ and superuser verifyDenied(scanAction, globalAdmin, globalCreate, globalWrite); verifyDenied(scanAction, nsCreate, nsAdmin, nsRead, nsWrite); verifyDenied(scanAction, tableCreate, tableAdmin, tableRead, tableWrite); verifyAllowed(scanAction, superUser, globalRead); }