SENTRY-2500: CREATE on server does not provide HMS server side read authorization for get_all_tables(database_name)
diff --git a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/MetastoreAuthzObjectFilter.java b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/MetastoreAuthzObjectFilter.java
index 178780e..e64d1a5 100644
--- a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/MetastoreAuthzObjectFilter.java
+++ b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/MetastoreAuthzObjectFilter.java
@@ -55,7 +55,7 @@
}
- private final HiveAuthzPrivileges LIST_DATABASES_PRIVILEGES = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
+ private static final HiveAuthzPrivileges LIST_DATABASES_PRIVILEGES = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
.addInputObjectPriviledge(
AuthorizableType.Column,
EnumSet.of(
@@ -67,12 +67,12 @@
.setOperationType(HiveOperationType.QUERY)
.build();
- private final HiveAuthzPrivileges LIST_TABLES_PRIVILEGES = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
+ private static final HiveAuthzPrivileges LIST_TABLES_PRIVILEGES = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
.addInputObjectPriviledge(
AuthorizableType.Column,
EnumSet.of(
DBModelAction.SELECT, DBModelAction.INSERT, DBModelAction.ALTER,
- DBModelAction.DROP, DBModelAction.INDEX, DBModelAction.LOCK))
+ DBModelAction.CREATE, DBModelAction.DROP, DBModelAction.INDEX, DBModelAction.LOCK))
.setOperationScope(HiveOperationScope.TABLE)
.setOperationType(
HiveAuthzPrivileges.HiveOperationType.INFO)
@@ -92,6 +92,22 @@
}
/**
+ * Return the required privileges for listing databases on a server
+ * @return the required privileges for authorizing listing databases on a server
+ */
+ public static HiveAuthzPrivileges getListDatabasesPrivileges() {
+ return LIST_DATABASES_PRIVILEGES;
+ }
+
+ /**
+ * Return the required privileges for listing tables in a database
+ * @return the required privileges for authorizing listing tables in a database
+ */
+ public static HiveAuthzPrivileges getListTablePrivileges() {
+ return LIST_TABLES_PRIVILEGES;
+ }
+
+ /**
* Filter a list of {@code dbNames} objects based on the authorization privileges of {@code subject}.
*
* @param username The username to request authorization from.
diff --git a/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/authz/TestMetastoreAuthzObjectFilter.java b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/authz/TestMetastoreAuthzObjectFilter.java
index 3ca89be..2fff9c4 100644
--- a/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/authz/TestMetastoreAuthzObjectFilter.java
+++ b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/authz/TestMetastoreAuthzObjectFilter.java
@@ -78,28 +78,28 @@
}
};
- private final HiveAuthzPrivileges LIST_DATABASES_PRIVILEGES = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
- .addInputObjectPriviledge(
- AuthorizableType.Column,
- EnumSet.of(
- DBModelAction.SELECT, DBModelAction.INSERT, DBModelAction.ALTER,
- DBModelAction.CREATE, DBModelAction.DROP, DBModelAction.INDEX,
- DBModelAction.LOCK))
- .addInputObjectPriviledge(AuthorizableType.URI, EnumSet.of(DBModelAction.SELECT))
- .setOperationScope(HiveOperationScope.CONNECT)
- .setOperationType(HiveOperationType.QUERY)
- .build();
+ public static final HiveAuthzPrivileges LIST_DATABASES_PRIVILEGES = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
+ .addInputObjectPriviledge(
+ AuthorizableType.Column,
+ EnumSet.of(
+ DBModelAction.SELECT, DBModelAction.INSERT, DBModelAction.ALTER,
+ DBModelAction.CREATE, DBModelAction.DROP, DBModelAction.INDEX,
+ DBModelAction.LOCK))
+ .addInputObjectPriviledge(AuthorizableType.URI, EnumSet.of(DBModelAction.SELECT))
+ .setOperationScope(HiveOperationScope.CONNECT)
+ .setOperationType(HiveOperationType.QUERY)
+ .build();
- private final HiveAuthzPrivileges LIST_TABLES_PRIVILEGES = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
- .addInputObjectPriviledge(
- AuthorizableType.Column,
- EnumSet.of(
- DBModelAction.SELECT, DBModelAction.INSERT, DBModelAction.ALTER,
- DBModelAction.DROP, DBModelAction.INDEX, DBModelAction.LOCK))
- .setOperationScope(HiveOperationScope.TABLE)
- .setOperationType(
- HiveAuthzPrivileges.HiveOperationType.INFO)
- .build();
+ public static final HiveAuthzPrivileges LIST_TABLES_PRIVILEGES = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
+ .addInputObjectPriviledge(
+ AuthorizableType.Column,
+ EnumSet.of(
+ DBModelAction.SELECT, DBModelAction.INSERT, DBModelAction.ALTER,
+ DBModelAction.CREATE, DBModelAction.DROP, DBModelAction.INDEX, DBModelAction.LOCK))
+ .setOperationScope(HiveOperationScope.TABLE)
+ .setOperationType(
+ HiveAuthzPrivileges.HiveOperationType.INFO)
+ .build();
/**
* Internal class used by AssertJ extract() method to extract the object name of
diff --git a/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/metastore/TestSentryMetaStoreFilterHook.java b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/metastore/TestSentryMetaStoreFilterHook.java
index 1f7148b..a498f98 100644
--- a/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/metastore/TestSentryMetaStoreFilterHook.java
+++ b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/metastore/TestSentryMetaStoreFilterHook.java
@@ -54,28 +54,26 @@
// Mock the HiveAuthzBinding to avoid making real connections to a Sentry server
private HiveAuthzBinding mockBinding = Mockito.mock(HiveAuthzBinding.class);
private final HiveAuthzPrivileges LIST_DATABASES_PRIVILEGES = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
- .addInputObjectPriviledge(
- AuthorizableType.Column,
- EnumSet.of(
- DBModelAction.SELECT, DBModelAction.INSERT, DBModelAction.ALTER,
- DBModelAction.CREATE, DBModelAction.DROP, DBModelAction.INDEX,
- DBModelAction.LOCK))
- .addInputObjectPriviledge(AuthorizableType.URI, EnumSet.of(DBModelAction.SELECT))
- .setOperationScope(HiveOperationScope.CONNECT)
- .setOperationType(HiveOperationType.QUERY)
- .build();
-
+ .addInputObjectPriviledge(
+ AuthorizableType.Column,
+ EnumSet.of(
+ DBModelAction.SELECT, DBModelAction.INSERT, DBModelAction.ALTER,
+ DBModelAction.CREATE, DBModelAction.DROP, DBModelAction.INDEX,
+ DBModelAction.LOCK))
+ .addInputObjectPriviledge(AuthorizableType.URI, EnumSet.of(DBModelAction.SELECT))
+ .setOperationScope(HiveOperationScope.CONNECT)
+ .setOperationType(HiveOperationType.QUERY)
+ .build();
private final HiveAuthzPrivileges LIST_TABLES_PRIVILEGES = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
- .addInputObjectPriviledge(
- AuthorizableType.Column,
- EnumSet.of(
- DBModelAction.SELECT, DBModelAction.INSERT, DBModelAction.ALTER,
- DBModelAction.DROP, DBModelAction.INDEX, DBModelAction.LOCK))
- .setOperationScope(HiveOperationScope.TABLE)
- .setOperationType(
- HiveAuthzPrivileges.HiveOperationType.INFO)
- .build();
-
+ .addInputObjectPriviledge(
+ AuthorizableType.Column,
+ EnumSet.of(
+ DBModelAction.SELECT, DBModelAction.INSERT, DBModelAction.ALTER,
+ DBModelAction.CREATE, DBModelAction.DROP, DBModelAction.INDEX, DBModelAction.LOCK))
+ .setOperationScope(HiveOperationScope.TABLE)
+ .setOperationType(
+ HiveAuthzPrivileges.HiveOperationType.INFO)
+ .build();
private HiveAuthzConf authzConf = new HiveAuthzConf();
private final Server SERVER1 = new Server("server1");
@@ -187,7 +185,7 @@
SentryMetaStoreFilterHook filterHook = new SentryMetaStoreFilterHook(null, authzConf,
getMockBinding(USER1));
- // Verify that only db2 is returned by the filter
+ // Verify that only t2 is returned by the filter
restrictTablesNamesOnBinding(USER1, DB1, Arrays.asList("t1", "t3"));
assertThat(filterHook.filterTableNames(DB1, Arrays.asList("t1", "t2", "t3"))).containsExactly("t2");
assertThat(filterHook.filterTables(Arrays.asList(
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
index d63957a..cc0465a 100644
--- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
@@ -108,10 +108,12 @@
USER2_1 = StaticUserGroup.USER2_1,
USER3_1 = StaticUserGroup.USER3_1,
USER4_1 = StaticUserGroup.USER4_1,
+ USER5_1 = StaticUserGroup.USER5_1,
USERGROUP1 = StaticUserGroup.USERGROUP1,
USERGROUP2 = StaticUserGroup.USERGROUP2,
USERGROUP3 = StaticUserGroup.USERGROUP3,
USERGROUP4 = StaticUserGroup.USERGROUP4,
+ USERGROUP5 = StaticUserGroup.USERGROUP5,
GROUP1_ROLE = "group1_role",
DB1 = "db_1",
DB2 = "db_2",
@@ -137,6 +139,7 @@
protected static boolean enableHiveConcurrency = false;
protected static boolean enableAuthorizingObjectStore = true;
protected static boolean enableAuthorizeReadMetaData = false;
+ protected static boolean enableFilter = false;
// indicate if the database need to be clear for every test case in one test class
protected static boolean clearDbPerTest = true;
@@ -289,6 +292,12 @@
properties.put(HiveConf.ConfVars.METASTORE_RAW_STORE_IMPL.varname, ConfVars.METASTORE_RAW_STORE_IMPL.defaultStrVal);
}
+ if (enableFilter) {
+ properties.put(ConfVars.METASTORE_FILTER_HOOK.varname, "org.apache.sentry.binding.metastore.SentryMetaStoreFilterHook");
+ } else {
+ properties.put(ConfVars.METASTORE_FILTER_HOOK.varname, ConfVars.METASTORE_FILTER_HOOK.defaultStrVal);
+ }
+
if (enableAuthorizeReadMetaData) {
properties.put("senry.metastore.read.authorization.enabled", "true");
} else {
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/StaticUserGroup.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/StaticUserGroup.java
index 8306e95..c7e941b 100644
--- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/StaticUserGroup.java
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/StaticUserGroup.java
@@ -27,11 +27,13 @@
USER2_1 = "user2_1",
USER3_1 = "user3_1",
USER4_1 = "user4_1",
+ USER5_1 = "user5_1",
HIVE = "hive",
USERGROUP1 = "user_group1",
USERGROUP2 = "user_group2",
USERGROUP3 = "user_group3",
- USERGROUP4 = "user_group4";
+ USERGROUP4 = "user_group4",
+ USERGROUP5 = "user_group5";
private static final Map<String, String> staticMapping;
static {
@@ -46,6 +48,7 @@
staticMapping.put(USER2_1, USERGROUP2);
staticMapping.put(USER3_1, USERGROUP3);
staticMapping.put(USER4_1, USERGROUP4);
+ staticMapping.put(USER5_1, USERGROUP5);
}
public static Map<String, String> getStaticMapping(){
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestShowMetadataPrivileges.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestShowMetadataPrivileges.java
index 88e697b..6a88d0b 100644
--- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestShowMetadataPrivileges.java
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestShowMetadataPrivileges.java
@@ -49,7 +49,7 @@
return Arrays.asList(new Object[][] {
{ null, NOT_ALLOWED }, // Means no privileges
{ DBModelAction.ALL, ALLOWED },
- { DBModelAction.CREATE, NOT_ALLOWED },
+ { DBModelAction.CREATE, ALLOWED },
{ DBModelAction.SELECT, ALLOWED },
{ DBModelAction.INSERT, ALLOWED },
{ DBModelAction.ALTER, ALLOWED },
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/AbstractMetastoreTestWithStaticConfiguration.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/AbstractMetastoreTestWithStaticConfiguration.java
index f1600c5..2a321fd 100644
--- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/AbstractMetastoreTestWithStaticConfiguration.java
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/AbstractMetastoreTestWithStaticConfiguration.java
@@ -221,6 +221,18 @@
client.dropDatabase(dbName, true, true, true);
}
+ public void dropAllMetastoreDBIfExists(HiveMetaStoreClient client, boolean dropDefault) throws Exception {
+ List<String> dbNames = client.getAllDatabases();
+
+ for (String dbName : dbNames) {
+ if (!dropDefault && dbName.equalsIgnoreCase("default")) {
+ continue;
+ }
+
+ client.dropDatabase(dbName, true, true, true);
+ }
+ }
+
public void execHiveSQLwithOverlay(final String sqlStmt,
final String userName, Map<String, String> overLay) throws Exception {
final HiveConf hiveConf = new HiveConf();
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/TestMetastoreEndToEnd.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/TestMetastoreEndToEnd.java
index 6327f16..cb201bb 100644
--- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/TestMetastoreEndToEnd.java
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/metastore/TestMetastoreEndToEnd.java
@@ -25,10 +25,15 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import org.apache.hadoop.hive.metastore.api.Database;
+import org.apache.hadoop.security.UserGroupInformation;
import org.junit.Assert;
import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
@@ -56,12 +61,15 @@
private PolicyFile policyFile;
private File dataFile;
private static final String dbName = "db_1";
+ private static final String dbName2 = "db_2";
private static final String db_all_role = "all_db1";
private static final String uri_role = "uri_role";
private static final String tab1_all_role = "tab1_all_role";
private static final String tab1_read_role = "tab1_read_role";
private static final String tab2_all_role = "tab2_all_role";
private static final String tab2_read_role = "tab2_read_role";
+ private static final String server_create_role = "server_create_role";
+ private static final String db2_all_role = "db2_all_role";
private static final String tabName1 = "tab1";
private static final String tabName2 = "tab2";
private static final String tabName3 = "tab3";
@@ -71,6 +79,7 @@
setMetastoreListener = false;
enableAuthorizingObjectStore = false;
enableAuthorizeReadMetaData = true;
+ enableFilter = true;
AbstractMetastoreTestWithStaticConfiguration.setupTestStaticConfiguration();
}
@@ -99,6 +108,9 @@
.addRolesToGroup(USERGROUP2, tab2_all_role)
.addRolesToGroup(USERGROUP3, tab1_read_role)
.addRolesToGroup(USERGROUP3, tab2_read_role)
+ .addRolesToGroup(USERGROUP4, tab1_all_role)
+ .addRolesToGroup(USERGROUP4, db2_all_role)
+ .addRolesToGroup(USERGROUP5, server_create_role)
.addPermissionsToRole(db_all_role, "server=server1->db=" + dbName)
.addPermissionsToRole("read_db_role",
"server=server1->db=" + dbName + "->action=SELECT")
@@ -110,6 +122,9 @@
"server=server1->db=" + dbName + "->table=" + tabName1 + "->action=SELECT")
.addPermissionsToRole(tab2_read_role,
"server=server1->db=" + dbName + "->table=" + tabName2 + "->action=SELECT")
+ .addPermissionsToRole(db2_all_role,
+ "server=server1->db=" + dbName2 + "->action=ALL")
+ .addPermissionsToRole(server_create_role, "server=server1" + "->action=CREATE")
.setUserGroupMapping(StaticUserGroup.getStaticMapping());
writePolicyFile(policyFile);
}
@@ -681,6 +696,122 @@
client.close();
}
+ private void verifyReturnedList(HashSet<String> expectedSet, List<String> actualList) {
+ assertThat(expectedSet.size()).isEqualTo(actualList.size());
+
+ for (String actualItem : actualList) {
+ assertThat(expectedSet).contains(actualItem);
+ }
+ }
+
+ private void verifyReturnedList(HashSet<String> expectedSet, List<String> actualList, boolean strict) {
+
+ // expectedSet and actualList contain same items, but may differ in order
+ if (strict ) {
+ verifyReturnedList(expectedSet, actualList);
+ return;
+ }
+
+ // check all items in expectedSet are in actualList, but actualList may contain extra items
+ for (String actualItem : actualList) {
+ if (expectedSet.contains(actualItem)) {
+ expectedSet.remove(actualItem);
+ }
+ }
+
+ assertThat(expectedSet.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void testListDatabases() throws Exception {
+ List<String> dbNames;
+ HashSet<String> allDatabaseNames = new HashSet<>(Arrays.asList("default", dbName, dbName2));
+
+ // Create databases and verify the admin can list the database names
+ final HiveMetaStoreClient client = context.getMetaStoreClient(ADMIN1);
+ dropAllMetastoreDBIfExists(client, false);
+ createMetastoreDB(client, dbName);
+ createMetastoreDB(client, dbName2);
+ UserGroupInformation clientUgi = UserGroupInformation.createRemoteUser(ADMIN1);
+ dbNames = clientUgi.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client.getAllDatabases();
+ }
+ });
+ assertThat(dbNames).isNotNull();
+ verifyReturnedList(allDatabaseNames, dbNames, true);
+ client.close();
+
+ // Verify a user with ALL privileges on a database can get its name
+ // and cannot get database name that has no privilege on
+ // USER1_1 has ALL at dbName
+ final HiveMetaStoreClient client_USER1_1 = context.getMetaStoreClient(USER1_1);
+ UserGroupInformation clientUgi_USER1_1 = UserGroupInformation.createRemoteUser(USER1_1);
+ dbNames = clientUgi_USER1_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER1_1.getAllDatabases();
+ }
+ });
+ assertThat(dbNames).isNotNull();
+ verifyReturnedList(new HashSet<>(Arrays.asList("default", dbName)), dbNames, true);
+ client_USER1_1.close();
+
+ // USER2_1 has SELECT at dbName
+ final HiveMetaStoreClient client_USER2_1 = context.getMetaStoreClient(USER2_1);
+ UserGroupInformation clientUgi_USER2_1 = UserGroupInformation.createRemoteUser(USER2_1);
+ dbNames = clientUgi_USER2_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER2_1.getAllDatabases();
+ }
+ });
+ assertThat(dbNames).isNotNull();
+ verifyReturnedList(new HashSet<>(Arrays.asList("default", dbName)), dbNames, true);
+ //assertThat(dbNames.get(0)).isEqualToIgnoringCase(dbName);
+ client.close();
+
+ // USER3_1 has SELECT at dbName.tabName1 and dbName.tabName2
+ final HiveMetaStoreClient client_USER3_1 = context.getMetaStoreClient(USER3_1);
+ UserGroupInformation clientUgi_USER3_1 = UserGroupInformation.createRemoteUser(USER3_1);
+ dbNames = clientUgi_USER3_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER3_1.getAllDatabases();
+ }
+ });
+ assertThat(dbNames).isNotNull();
+ verifyReturnedList(new HashSet<>(Arrays.asList("default", dbName)), dbNames,true);
+ client.close();
+
+ // USER4_1 has ALL at dbName.tabName1 and dbName2
+ final HiveMetaStoreClient client_USER4_1 = context.getMetaStoreClient(USER4_1);
+ UserGroupInformation clientUgi_USER4_1 = UserGroupInformation.createRemoteUser(USER4_1);
+ dbNames = clientUgi_USER4_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER4_1.getAllDatabases();
+ }
+ });
+ assertThat(dbNames).isNotNull();
+ verifyReturnedList(allDatabaseNames, dbNames, true);
+ client.close();
+
+ // USER5_1 has CREATE at server
+ final HiveMetaStoreClient client_USER5_1 = context.getMetaStoreClient(USER5_1);
+ UserGroupInformation clientUgi_USER5_1 = UserGroupInformation.createRemoteUser(USER5_1);
+ dbNames = clientUgi_USER5_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER5_1.getAllDatabases();
+ }
+ });
+ assertThat(dbNames).isNotNull();
+ verifyReturnedList(allDatabaseNames, dbNames, true);
+ client.close();
+ }
+
@Test
public void testReadTable() throws Exception {
Table tbl;
@@ -723,4 +854,154 @@
}
client.close();
}
+
+ @Test
+ public void testListTables() throws Exception {
+ List<String> tableNames;
+ HashSet<String> expectedTableNames = new HashSet<>(Arrays.asList(tabName1, tabName2));
+
+ // Create databases and verify the admin can list the database names
+ final HiveMetaStoreClient client = context.getMetaStoreClient(ADMIN1);
+ dropMetastoreDBIfExists(client, dbName);
+ createMetastoreDB(client, dbName);
+ createMetastoreTable(client, dbName, tabName1,
+ Lists.newArrayList(new FieldSchema("col1", "int", "")));
+ createMetastoreTable(client, dbName, tabName2,
+ Lists.newArrayList(new FieldSchema("col1", "int", "")));
+ createMetastoreTable(client, dbName, tabName3,
+ Lists.newArrayList(new FieldSchema("col1", "int", "")));
+ UserGroupInformation clientUgi = UserGroupInformation.createRemoteUser(ADMIN1);
+ tableNames = clientUgi.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client.getAllTables(dbName);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(3);
+
+ dropMetastoreDBIfExists(client, dbName2);
+ createMetastoreDB(client, dbName2);
+ createMetastoreTable(client, dbName2, tabName1,
+ Lists.newArrayList(new FieldSchema("col1", "int", "")));
+ createMetastoreTable(client, dbName2, tabName2,
+ Lists.newArrayList(new FieldSchema("col1", "int", "")));
+ tableNames = clientUgi.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client.getAllTables(dbName2);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(2);
+ client.close();
+
+ // Verify a user with ALL privileges on a database can get its name
+ // and cannot get database name that has no privilege on
+ // USER1_1 has ALL on dbName
+ final HiveMetaStoreClient client_USER1_1 = context.getMetaStoreClient(USER1_1);
+ UserGroupInformation clientUgi_USER1_1 = UserGroupInformation.createRemoteUser(USER1_1);
+ tableNames = clientUgi_USER1_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER1_1.getAllTables(dbName);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(3);
+ tableNames = clientUgi_USER1_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER1_1.getAllTables(dbName2);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(0);
+
+ // USER2_1 has SELECT on dbName
+ final HiveMetaStoreClient client_USER2_1 = context.getMetaStoreClient(USER2_1);
+ UserGroupInformation clientUgi_USER2_1 = UserGroupInformation.createRemoteUser(USER2_1);
+ tableNames = clientUgi_USER2_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER2_1.getAllTables(dbName);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(3);
+ tableNames = clientUgi_USER2_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER2_1.getAllTables(dbName2);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(0);
+
+ // USER3_1 has SELECT on dbName.tabName1 and dbName.tabName2
+ final HiveMetaStoreClient client_USER3_1 = context.getMetaStoreClient(USER3_1);
+ UserGroupInformation clientUgi_USER3_1 = UserGroupInformation.createRemoteUser(USER3_1);
+ tableNames = clientUgi_USER3_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER3_1.getAllTables(dbName);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(2);
+ assertThat(expectedTableNames).contains(tableNames.get(0));
+ assertThat(expectedTableNames).contains(tableNames.get(1));
+ tableNames = clientUgi_USER3_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER3_1.getAllTables(dbName2);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(0);
+ client.close();
+
+ // USER4_1 ALL on dbName.tabName1 and dbName2
+ final HiveMetaStoreClient client_USER4_1 = context.getMetaStoreClient(USER4_1);
+ UserGroupInformation clientUgi_USER4_1 = UserGroupInformation.createRemoteUser(USER4_1);
+ tableNames = clientUgi_USER4_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER4_1.getAllTables(dbName);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(1); // only has access to tabName1 and tabName2
+ assertThat(tableNames.get(0)).isEqualToIgnoringCase(tabName1);
+ tableNames = clientUgi_USER4_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER4_1.getAllTables(dbName2);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(2);
+ client.close();
+
+ // USER5_1 CREATE on server
+ final HiveMetaStoreClient client_USER5_1 = context.getMetaStoreClient(USER5_1);
+ UserGroupInformation clientUgi_USER5_1 = UserGroupInformation.createRemoteUser(USER5_1);
+ tableNames = clientUgi_USER5_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER5_1.getAllTables(dbName);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(3);
+ tableNames = clientUgi_USER5_1.doAs(new PrivilegedExceptionAction<List<String>>() {
+ @Override
+ public List<String> run() throws Exception {
+ return client_USER5_1.getAllTables(dbName2);
+ }
+ });
+ assertThat(tableNames).isNotNull();
+ assertThat(tableNames.size()).isEqualTo(2);
+ client.close();
+ }
}