diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java index f571acf..b1de763 100644 --- hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java +++ hbase-client/src/main/java/org/apache/hadoop/hbase/security/access/AccessControlClient.java @@ -23,8 +23,6 @@ import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import org.apache.hadoop.hbase.classification.InterfaceAudience; -import org.apache.hadoop.hbase.classification.InterfaceStability; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HTableDescriptor; @@ -32,6 +30,8 @@ import org.apache.hadoop.hbase.MasterNotRunningException; import org.apache.hadoop.hbase.NamespaceDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.ZooKeeperConnectionException; +import org.apache.hadoop.hbase.classification.InterfaceAudience; +import org.apache.hadoop.hbase.classification.InterfaceStability; import org.apache.hadoop.hbase.client.HBaseAdmin; import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.client.coprocessor.Batch; @@ -47,6 +47,7 @@ import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GrantRespo import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeRequest; import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeResponse; import org.apache.hadoop.hbase.util.ByteStringer; +import org.apache.hadoop.hbase.util.Bytes; import com.google.protobuf.ByteString; @@ -222,14 +223,17 @@ public class AccessControlClient { BlockingInterface protocol = AccessControlProtos.AccessControlService.newBlockingStub(service); HTableDescriptor[] htds = null; - - if (tableRegex != null) { + + if (tableRegex == null) { + permList = ProtobufUtil.getUserPermissions(protocol); + } else if (tableRegex.charAt(0) == '@') { + String namespace = tableRegex.substring(1); + permList = ProtobufUtil.getUserPermissions(protocol, Bytes.toBytes(namespace)); + } else { htds = ha.listTables(Pattern.compile(tableRegex)); - for (HTableDescriptor hd: htds) { + for (HTableDescriptor hd : htds) { permList.addAll(ProtobufUtil.getUserPermissions(protocol, hd.getTableName())); } - } else { - permList = ProtobufUtil.getUserPermissions(protocol); } } finally { if (ht != null) { diff --git hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java index 046960e..edf591c 100644 --- hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java +++ hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestAccessController.java @@ -45,6 +45,7 @@ import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.LargeTests; import org.apache.hadoop.hbase.MiniHBaseCluster; +import org.apache.hadoop.hbase.NamespaceDescriptor; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.TableNotFoundException; @@ -76,6 +77,7 @@ import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.NoopRes import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.PingRequest; import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.PingResponse; import org.apache.hadoop.hbase.coprocessor.protobuf.generated.PingProtos.PingService; +import org.apache.hadoop.hbase.exceptions.HBaseException; import org.apache.hadoop.hbase.io.hfile.CacheConfig; import org.apache.hadoop.hbase.io.hfile.HFile; import org.apache.hadoop.hbase.io.hfile.HFileContext; @@ -96,7 +98,6 @@ import org.apache.hadoop.hbase.security.access.Permission.Action; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.JVMClusterUtil; import org.apache.hadoop.hbase.util.TestTableName; -import org.apache.hadoop.hbase.security.access.AccessControlClient; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.After; @@ -2158,4 +2159,21 @@ public class TestAccessController extends SecureTestUtil { verifyDenied(putWithReservedTag, USER_OWNER, USER_ADMIN, USER_CREATE, USER_RW, USER_RO); } + @Test + public void testGetNamespacePermission() throws Exception { + String namespace = "testNamespace"; + NamespaceDescriptor desc = NamespaceDescriptor.create(namespace).build(); + TEST_UTIL.getMiniHBaseCluster().getMaster().createNamespace(desc); + grantOnNamespace(TEST_UTIL, USER_NONE.getShortName(), namespace, Permission.Action.READ); + try { + List namespacePermissions = AccessControlClient.getUserPermissions(conf, + AccessControlLists.toNamespaceEntry(namespace)); + assertTrue(namespacePermissions != null); + assertTrue(namespacePermissions.size() == 1); + } catch (Throwable thw) { + throw new HBaseException(thw); + } + TEST_UTIL.getMiniHBaseCluster().getMaster().deleteNamespace(namespace); + } + } diff --git hbase-shell/src/main/ruby/hbase/security.rb hbase-shell/src/main/ruby/hbase/security.rb index 806d765..925188c 100644 --- hbase-shell/src/main/ruby/hbase/security.rb +++ hbase-shell/src/main/ruby/hbase/security.rb @@ -156,6 +156,11 @@ module Hbase count = 0 all_perms.each do |value| user_name = String.from_java_bytes(value.getUser) + if (isNamespace?(table_regex)) + namespace = table_regex[1...table_regex.length] + else + namespace = (value.getTableName != nil) ? value.getTableName.getNamespaceAsString() : '' + end table = (value.getTableName != nil) ? value.getTableName.getNameAsString() : '' family = (value.getFamily != nil) ? org.apache.hadoop.hbase.util.Bytes::toStringBinary(value.getFamily) : @@ -167,7 +172,7 @@ module Hbase action = org.apache.hadoop.hbase.security.access.Permission.new value.getActions if block_given? - yield(user_name, "#{table},#{family},#{qualifier}: #{action.to_s}") + yield(user_name, "#{namespace},#{table},#{family},#{qualifier}: #{action.to_s}") else res[user_name] ||= {} res[user_name][family + ":" +qualifier] = action