blob: 345edc1951c520fd4218f93960d477db5bcc53ca [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sentry.tests.e2e.metastore;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
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;
import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
import org.apache.hadoop.hive.metastore.api.FieldSchema;
import org.apache.hadoop.hive.metastore.api.MetaException;
import org.apache.hadoop.hive.metastore.api.Partition;
import org.apache.hadoop.hive.metastore.api.Table;
import org.apache.sentry.provider.file.PolicyFile;
import org.apache.sentry.tests.e2e.hive.Context;
import org.apache.sentry.tests.e2e.hive.StaticUserGroup;
import org.apache.sentry.tests.e2e.hive.hiveserver.HiveServerFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Resources;
public class TestMetastoreEndToEnd extends
AbstractMetastoreTestWithStaticConfiguration {
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";
@BeforeClass
public static void setupTestStaticConfiguration() throws Exception {
setMetastoreListener = false;
enableAuthorizingObjectStore = false;
enableAuthorizeReadMetaData = true;
enableFilter = true;
AbstractMetastoreTestWithStaticConfiguration.setupTestStaticConfiguration();
}
@Override
@Before
public void setup() throws Exception {
policyFile = setAdminOnServer1(ADMINGROUP);
policyFile.setUserGroupMapping(StaticUserGroup.getStaticMapping());
writePolicyFile(policyFile);
super.setup();
dataFile = new File(dataDir, SINGLE_TYPE_DATA_FILE_NAME);
FileOutputStream to = new FileOutputStream(dataFile);
Resources.copy(Resources.getResource(SINGLE_TYPE_DATA_FILE_NAME), to);
to.close();
HiveMetaStoreClient client = context.getMetaStoreClient(ADMIN1);
client.dropDatabase(dbName, true, true, true);
createMetastoreDB(client, dbName);
client.close();
policyFile
.addRolesToGroup(USERGROUP1, db_all_role)
.addRolesToGroup(USERGROUP2, "read_db_role")
.addRolesToGroup(USERGROUP2, tab1_all_role)
.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")
.addPermissionsToRole(tab1_all_role,
"server=server1->db=" + dbName + "->table=" + tabName1)
.addPermissionsToRole(tab2_all_role,
"server=server1->db=" + dbName + "->table=" + tabName2)
.addPermissionsToRole(tab1_read_role,
"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);
}
@After
public void tearDown() throws Exception {
if (context != null) {
context.close();
}
}
/**
* Setup admin privileges for user ADMIN1 verify user can create DB and tables
* @throws Exception
*/
// @Test
// public void testServerPrivileges() throws Exception {
// String tabName = "tab1";
// HiveMetaStoreClient client = context.getMetaStoreClient(ADMIN1);
// client.dropDatabase(dbName, true, true, true);
//
// createMetastoreDB(client, dbName);
// createMetastoreTable(client, dbName, tabName,
// Lists.newArrayList(new FieldSchema("col1", "int", "")));
// assertEquals(1, client.getTables(dbName, tabName).size());
//
// AuthzPathsCache authzPathCache = new AuthzPathsCache(null, new String[]{"/"}, 0);
// SentryPolicyServiceClient sentryClient = new SentryServiceClientFactory().create(sentryConf);
// waitToCommit(authzPathCache, sentryClient);
// assertEquals("/%PREFIX[data%DIR[db_1.db%AUTHZ_OBJECT#db_1[tab1%AUTHZ_OBJECT#db_1.tab1[]]]]", authzPathCache.serializeAllPaths());
// client.dropTable(dbName, tabName);
// client.dropDatabase(dbName, true, true, true);
// waitToCommit(authzPathCache, sentryClient);
// assertEquals("/%PREFIX[]", authzPathCache.serializeAllPaths());
// }
//
// private void waitToCommit(AuthzPathsCache authzPathCache, SentryPolicyServiceClient sentryClient)
// throws Exception {
// SentryAuthzUpdate allUpdates = sentryClient.getAllUpdatesFrom(0, 0);
// for (HMSUpdate update : allUpdates.pathUpdates) {
// authzPathCache.handleUpdateNotification(update);
// }
// int counter = 0;
// while(!authzPathCache.areAllUpdatesCommited()) {
// Thread.sleep(200);
// counter++;
// if (counter > 10000) {
// fail("Updates taking too long to commit !!");
// }
// }
// }
/**
* verify non-admin user can not create or drop DB
* @throws Exception
*/
@Test
public void testNegativeServerPrivileges() throws Exception {
HiveMetaStoreClient client = context.getMetaStoreClient(USER1_1);
try {
createMetastoreDB(client, "fooDb");
fail("Creat db should have failed for non-admin user");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
try {
createMetastoreDB(client, "barDb");
fail("create db should have failed for non-admin user");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
}
/**
* Verify the user with DB permission can create table in that db Verify the
* user can't create table in DB where he doesn't have ALL permissions
* @throws Exception
*/
@Test
public void testTablePrivileges() throws Exception {
HiveMetaStoreClient client = context.getMetaStoreClient(ADMIN1);
createMetastoreTable(client, dbName, tabName1,
Lists.newArrayList(new FieldSchema("col1", "int", "")));
client.close();
client = context.getMetaStoreClient(USER1_1);
createMetastoreTable(client, dbName, tabName2,
Lists.newArrayList(new FieldSchema("col1", "int", "")));
assertEquals(1, client.getTables(dbName, tabName2).size());
client.dropTable(dbName, tabName1);
createMetastoreTable(client, dbName, tabName1,
Lists.newArrayList(new FieldSchema("col1", "int", "")));
client.close();
// group2 users can't create the table, but can drop it
client = context.getMetaStoreClient(USER2_1);
try {
createMetastoreTable(client, dbName, "barTab",
Lists.newArrayList(new FieldSchema("col1", "int", "")));
fail("Create table should have failed for non-privilege user");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
client.dropTable(dbName, tabName2);
client.close();
// group3 users can't create or drop it
client = context.getMetaStoreClient(USER3_1);
try {
createMetastoreTable(client, dbName, "barTab",
Lists.newArrayList(new FieldSchema("col1", "int", "")));
fail("Create table should have failed for non-privilege user");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
try {
client.dropTable(dbName, tabName1);
fail("drop table should have failed for non-privilege user");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
client.close();
}
/**
* Verify alter table privileges
* @throws Exception
*/
@Test
public void testAlterTablePrivileges() throws Exception {
HiveMetaStoreClient client = context.getMetaStoreClient(ADMIN1);
createMetastoreTable(client, dbName, tabName1,
Lists.newArrayList(new FieldSchema("col1", "int", "")));
client.close();
// verify group1 users with DDL privileges can alter tables in db_1
client = context.getMetaStoreClient(USER1_1);
Table metaTable2 = client.getTable(dbName, tabName1);
metaTable2.getSd().setCols(
Lists.newArrayList(new FieldSchema("col2", "double", "")));
client.alter_table(dbName, tabName1, metaTable2);
Table metaTable3 = client.getTable(dbName, tabName1);
assertEquals(metaTable2.getSd().getCols(), metaTable3.getSd().getCols());
// verify group1 users with DDL privileges can alter tables in db_1
client = context.getMetaStoreClient(USER2_1);
metaTable2 = client.getTable(dbName, tabName1);
metaTable2.getSd().setCols(
Lists.newArrayList(new FieldSchema("col3", "string", "")));
client.alter_table(dbName, tabName1, metaTable2);
metaTable3 = client.getTable(dbName, tabName1);
assertEquals(metaTable2.getSd().getCols(), metaTable3.getSd().getCols());
// verify group3 users can't alter tables in db_1
client = context.getMetaStoreClient(USER3_1);
metaTable2 = client.getTable(dbName, tabName1);
metaTable2.getSd().setCols(
Lists.newArrayList(new FieldSchema("col3", "string", "")));
try {
client.alter_table(dbName, tabName1, metaTable2);
fail("alter table should have failed for non-privilege user");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
client.close();
}
/**
* Verify alter view privileges
* @throws Exception
*/
@Test
public void testAlterViewPrivileges() throws Exception {
HiveMetaStoreClient client = context.getMetaStoreClient(ADMIN1);
createMetastoreView(client, dbName, tabName1,
Lists.newArrayList(new FieldSchema("col1", "int", "")));
client.close();
// verify group1 users with DDL privileges can alter tables in db_1
client = context.getMetaStoreClient(USER1_1);
Table metaView2 = client.getTable(dbName, tabName1);
metaView2.getSd().setCols(
Lists.newArrayList(new FieldSchema("col2", "double", "")));
client.alter_table(dbName, tabName1, metaView2);
Table metaView3 = client.getTable(dbName, tabName1);
assertEquals(metaView2.getSd().getCols(), metaView3.getSd().getCols());
client.close();
}
/**
* Verify add partition privileges
* @throws Exception
*/
@Test
public void testAddPartitionPrivileges() throws Exception {
ArrayList<String> partVals1 = Lists.newArrayList("part1");
ArrayList<String> partVals2 = Lists.newArrayList("part2");
ArrayList<String> partVals3 = Lists.newArrayList("part3");
ArrayList<String> partVals4 = Lists.newArrayList("part4");
// user with ALL on DB should be able to add partition
HiveMetaStoreClient client = context.getMetaStoreClient(USER1_1);
Table tbl1 = createMetastoreTableWithPartition(client, dbName, tabName1,
Lists.newArrayList(new FieldSchema("col1", "int", "")),
Lists.newArrayList(new FieldSchema("part_col1", "string", "")));
assertEquals(1, client.getTables(dbName, tabName1).size());
addPartition(client, dbName, tabName1, partVals1, tbl1);
addPartition(client, dbName, tabName1, partVals2, tbl1);
client.close();
// user with ALL on Table should be able to add partition
client = context.getMetaStoreClient(USER2_1);
tbl1 = client.getTable(dbName, tabName1);
addPartition(client, dbName, tabName1, partVals3, tbl1);
client.close();
// user without ALL on DB or Table should NOT be able to add partition
client = context.getMetaStoreClient(USER3_1);
tbl1 = client.getTable(dbName, tabName1);
try {
addPartition(client, dbName, tabName1, partVals4, tbl1);
fail("Add partition should have failed for non-admin user");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
client.close();
// user with ALL on DB should be able to drop partition
client = context.getMetaStoreClient(USER1_1);
tbl1 = client.getTable(dbName, tabName1);
client.dropPartition(dbName, tabName1, partVals1, true);
client.close();
// user with ALL on Table should be able to drop partition
client = context.getMetaStoreClient(USER2_1);
tbl1 = client.getTable(dbName, tabName1);
client.dropPartition(dbName, tabName1, partVals2, true);
client.close();
// user without ALL on DB or Table should NOT be able to drop partition
client = context.getMetaStoreClient(USER3_1);
try {
addPartition(client, dbName, tabName1, partVals3, tbl1);
fail("Drop partition should have failed for non-admin user");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
}
/**
* Verify URI privileges for alter table table
* @throws Exception
*/
@Test
public void testUriTablePrivileges() throws Exception {
String newPath1 = "fooTab1";
String newPath2 = "fooTab2";
String tabDir1 = hiveServer.getProperty(HiveServerFactory.WAREHOUSE_DIR)
+ File.separator + newPath1;
String tabDir2 = hiveServer.getProperty(HiveServerFactory.WAREHOUSE_DIR)
+ File.separator + newPath2;
policyFile.addRolesToGroup(USERGROUP1, uri_role)
.addRolesToGroup(USERGROUP2, uri_role)
.addRolesToGroup(USERGROUP3, db_all_role)
.addPermissionsToRole(uri_role, "server=server1->URI=" + tabDir1)
.addPermissionsToRole(uri_role, "server=server1->URI=" + tabDir2);
writePolicyFile(policyFile);
// user with URI privileges should be able to create table with that
// specific location
HiveMetaStoreClient client = context.getMetaStoreClient(USER1_1);
createMetastoreTableWithLocation(client, dbName, tabName1,
Lists.newArrayList(new FieldSchema("col1", "int", "")), tabDir1);
createMetastoreTableWithLocation(client, dbName, tabName2,
Lists.newArrayList(new FieldSchema("col1", "int", "")), tabDir2);
client.close();
// user without URI privileges should be NOT able to create table with that specific location
client = context.getMetaStoreClient(USER3_1);
try {
createMetastoreTableWithLocation(client, dbName, "fooTab",
Lists.newArrayList(new FieldSchema("col1", "int", "")), tabDir2);
fail("Create table with location should fail without URI privilege");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
client.close();
// user with URI privileges should be able to alter table to set that specific location
client = context.getMetaStoreClient(USER1_1);
Table metaTable1 = client.getTable(dbName, tabName1);
metaTable1.getSd().setLocation(tabDir2);
client.alter_table(dbName, tabName1, metaTable1);
client.close();
// user with URI privileges and table all should be able to alter table to
// set that specific location
client = context.getMetaStoreClient(USER2_1);
metaTable1 = client.getTable(dbName, tabName2);
metaTable1.getSd().setLocation(tabDir1);
client.alter_table(dbName, tabName2, metaTable1);
client.close();
// user without URI privileges should be NOT able to alter table to set that
// specific location
client = context.getMetaStoreClient(USER3_1);
Table metaTable2 = client.getTable(dbName, tabName2);
metaTable2.getSd().setLocation(tabDir2);
try {
client.alter_table(dbName, tabName2, metaTable2);
fail("Alter table with location should fail without URI privilege");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
client.close();
}
/**
* Verify URI privileges for alter table table
* @throws Exception
*/
@Test
public void testUriPartitionPrivileges() throws Exception {
String tabName1 = "tab1";
String newPath1 = "fooTab1";
String newPath2 = "fooTab2";
ArrayList<String> partVals1 = Lists.newArrayList("part1");
ArrayList<String> partVals2 = Lists.newArrayList("part2");
ArrayList<String> partVals3 = Lists.newArrayList("part2");
String tabDir1 = hiveServer.getProperty(HiveServerFactory.WAREHOUSE_DIR)
+ File.separator + newPath1;
String tabDir2 = hiveServer.getProperty(HiveServerFactory.WAREHOUSE_DIR)
+ File.separator + newPath2;
policyFile.addRolesToGroup(USERGROUP1, uri_role)
.addRolesToGroup(USERGROUP2, db_all_role)
.addPermissionsToRole(uri_role, "server=server1->URI=" + tabDir1)
.addPermissionsToRole(uri_role, "server=server1->URI=" + tabDir2);
writePolicyFile(policyFile);
// user with URI privileges should be able to alter partition to set that specific location
HiveMetaStoreClient client = context.getMetaStoreClient(USER1_1);
Table tbl1 = createMetastoreTableWithPartition(client, dbName,
tabName1, Lists.newArrayList(new FieldSchema("col1", "int", "")),
Lists.newArrayList(new FieldSchema("part_col1", "string", "")));
addPartition(client, dbName, tabName1, partVals1, tbl1);
addPartitionWithLocation(client, dbName, tabName1, partVals2, tbl1,
tabDir1);
client.close();
// user without URI privileges should be NOT able to alter partition to set
// that specific location
client = context.getMetaStoreClient(USER2_1);
try {
tbl1 = client.getTable(dbName, tabName1);
addPartitionWithLocation(client, dbName, tabName1, partVals3,
tbl1, tabDir2);
fail("Add partition with location should have failed");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
client.close();
}
/**
* Verify alter partion privileges
* TODO: We seem to have a bit inconsistency with Alter partition. It's only
* allowed with SERVER privilege. If we allow add/drop partition with DB
* level privilege, then this should also be at the same level.
* @throws Exception
*/
@Test
public void testAlterSetLocationPrivileges() throws Exception {
String newPath1 = "fooTab1";
ArrayList<String> partVals1 = Lists.newArrayList("part1");
ArrayList<String> partVals2 = Lists.newArrayList("part2");
String tabDir1 = hiveServer.getProperty(HiveServerFactory.WAREHOUSE_DIR)
+ File.separator + newPath1;
policyFile.addRolesToGroup(USERGROUP1, uri_role)
.addRolesToGroup(USERGROUP2, uri_role)
.addPermissionsToRole(uri_role, "server=server1->URI=" + tabDir1);
writePolicyFile(policyFile);
HiveMetaStoreClient client = context.getMetaStoreClient(ADMIN1);
Table tbl1 = createMetastoreTableWithPartition(client, dbName,
tabName1, Lists.newArrayList(new FieldSchema("col1", "int", "")),
Lists.newArrayList(new FieldSchema("part_col1", "string", "")));
addPartition(client, dbName, tabName1, partVals1, tbl1);
tbl1 = client.getTable(dbName, tabName1);
addPartition(client, dbName, tabName1, partVals2, tbl1);
client.close();
// user with DB and URI privileges should be able to alter partition set location
client = context.getMetaStoreClient(USER1_1);
Partition newPartition = client.getPartition(dbName, tabName1, partVals1);
newPartition.getSd().setLocation(tabDir1);
client.alter_partition(dbName, tabName1, newPartition, null);
client.close();
// user with Table and URI privileges should be able to alter partition set location
client = context.getMetaStoreClient(USER2_1);
newPartition = client.getPartition(dbName, tabName1, partVals2);
newPartition.getSd().setLocation(tabDir1);
client.alter_partition(dbName, tabName1, newPartition, null);
client.close();
policyFile.addRolesToGroup(USERGROUP3, db_all_role);
writePolicyFile(policyFile);
// user without URI privileges should not be able to alter partition set location
client = context.getMetaStoreClient(USER3_1);
newPartition = client.getPartition(dbName, tabName1, partVals2);
newPartition.getSd().setLocation(tabDir1);
try {
client.alter_partition(dbName, tabName1, newPartition, null);
fail("alter partition with location should have failed");
} catch (MetaException e) {
Context.verifyMetastoreAuthException(e);
}
client.close();
}
/**
* Verify data load into new partition using INSERT .. PARTITION statement
*/
@Test
public void testPartionInsert() throws Exception {
String partVal1 = "part1", partVal2 = "part2";
policyFile.addRolesToGroup(USERGROUP1, uri_role).addPermissionsToRole(
uri_role, "server=server1->uri=file://" + dataFile.getPath());
writePolicyFile(policyFile);
execHiveSQL("CREATE TABLE " + dbName + "." + tabName1
+ " (id int) PARTITIONED BY (part_col string)", USER1_1);
execHiveSQL("CREATE TABLE " + dbName + "." + tabName2 + " (id int)",
USER1_1);
execHiveSQL("LOAD DATA LOCAL INPATH '" + dataFile.getPath()
+ "' INTO TABLE " + dbName + "." + tabName2, USER1_1);
// verify that user with DB all can add partition using INSERT .. PARTITION
execHiveSQL("INSERT OVERWRITE TABLE " + dbName + "." + tabName1
+ " PARTITION (part_col='" + partVal1 + "') SELECT * FROM " + dbName
+ "." + tabName2, USER1_1);
verifyPartitionExists(dbName, tabName1, partVal1);
// verify that user with Table all can add partition using INSERT
execHiveSQL("INSERT OVERWRITE TABLE " + dbName + "." + tabName1
+ " PARTITION (part_col='" + partVal2 + "') SELECT * FROM " + dbName
+ "." + tabName2, USER2_1);
verifyPartitionExists(dbName, tabName1, partVal2);
// verify that user with Table all can add dynamic partition using INSERT
Map<String, String> dynamicInsertProperties = Maps.newHashMap();
dynamicInsertProperties.put(ConfVars.DYNAMICPARTITIONING.varname, "true");
dynamicInsertProperties.put(ConfVars.DYNAMICPARTITIONINGMODE.varname,
"nonstrict");
execHiveSQL("CREATE TABLE " + dbName + "." + tabName3
+ " (id int) PARTITIONED BY (part_col string)", USER1_1);
execHiveSQLwithOverlay("INSERT OVERWRITE TABLE " + dbName + "." + tabName3
+ " partition (part_col) SELECT id, part_col FROM "
+ dbName + "." + tabName1, USER1_1, dynamicInsertProperties);
}
@Test
public void testAddPartion() throws Exception {
String partVal1 = "part1", partVal2 = "part2";
String newPath1 = "fooTab1";
String tabDir1 = hiveServer.getProperty(HiveServerFactory.WAREHOUSE_DIR)
+ File.separator + newPath1;
//URI privilege required when "using location"
policyFile.addRolesToGroup(USERGROUP1, uri_role).addPermissionsToRole(
uri_role, "server=server1->URI=" + tabDir1);
writePolicyFile(policyFile);
execHiveSQL("DROP TABLE IF EXISTS " + dbName + "." + tabName1, USER1_1);
execHiveSQL("CREATE TABLE " + dbName + "." + tabName1
+ " (id int) PARTITIONED BY (part_col string)", USER1_1);
//User with all on table
execHiveSQL("ALTER TABLE " + dbName + "." + tabName1
+ " ADD PARTITION (part_col ='" + partVal1 + "')", USER1_1);
verifyPartitionExists(dbName, tabName1, partVal1);
execHiveSQL("ALTER TABLE " + dbName + "." + tabName1
+ " ADD PARTITION (part_col ='" + partVal2 + "') location '"
+ tabDir1 + "'", USER1_1);
verifyPartitionExists(dbName, tabName1, partVal2);
try {
execHiveSQL("ALTER TABLE " + dbName + "." + tabName1
+ " ADD PARTITION (part_col ='" + partVal2 + "') location '"
+ tabDir1 + "'", USER2_1);
fail("alter table should have failed due to URI privilege missed");
} catch (IOException e) {
// Expected error
}
}
@Test
public void testInsertInto() throws Exception {
String partVal1 = "part1";
writePolicyFile(policyFile);
execHiveSQL("DROP TABLE IF EXISTS " + dbName + "." + tabName1, USER1_1);
execHiveSQL("CREATE TABLE " + dbName + "." + tabName1
+ " (id int) PARTITIONED BY (part_col string)", USER1_1);
execHiveSQL("INSERT INTO " + dbName + "." + tabName1 +
" PARTITION(part_col ='" + partVal1 + "') select 1 from " + dbName + "." + tabName1, USER2_1);
verifyPartitionExists(dbName, tabName1, partVal1);
}
private void verifyPartitionExists(String dbName, String tabName,
String partVal) throws Exception {
HiveMetaStoreClient client = context.getMetaStoreClient(ADMIN1);
Partition newPartition = client.getPartition(dbName, tabName,
Lists.newArrayList(partVal));
Assert.assertNotNull(newPartition);
client.close();
}
@Test
public void testReadDatabase() throws Exception {
Database db;
HiveMetaStoreClient client;
// Create a database and verify the admin can read its metadata
client = context.getMetaStoreClient(ADMIN1);
dropMetastoreDBIfExists(client, dbName);
createMetastoreDB(client, dbName);
dropMetastoreDBIfExists(client, "db2");
createMetastoreDB(client, "db2");
db = client.getDatabase(dbName);
assertThat(db).isNotNull();
assertThat(db.getName()).isEqualTo(dbName);
db = client.getDatabase("db2");
assertThat(db).isNotNull();
assertThat(db.getName()).isEqualTo("db2");
client.close();
// Verify a user with ALL privileges can read the database metadata
client = context.getMetaStoreClient(USER1_1);
db = client.getDatabase(dbName);
assertThat(db).isNotNull();
assertThat(db.getName()).isEqualTo(dbName);
client.close();
// Verify a user without privileges cannot read the database metadata
client = context.getMetaStoreClient(USER1_1);
try {
client.getDatabase("db2");
fail("MetaException exepected because USER1_1 does not have privileges on 'db2'");
} catch (Exception e) {
assertThat(e).isInstanceOf(MetaException.class)
.hasMessageContaining("does not have privileges for DESCDATABASE");
}
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;
HiveMetaStoreClient client;
// Create a database and verify the admin can read its metadata
client = context.getMetaStoreClient(ADMIN1);
dropMetastoreDBIfExists(client, dbName);
createMetastoreDB(client, dbName);
createMetastoreTable(client, dbName, tabName1,
Lists.newArrayList(new FieldSchema("col1", "int", "")));
createMetastoreTable(client, dbName, "tbl1",
Lists.newArrayList(new FieldSchema("col1", "int", "")));
tbl = client.getTable(dbName, tabName1);
assertThat(tbl).isNotNull();
assertThat(tbl.getDbName()).isEqualTo(dbName);
assertThat(tbl.getTableName()).isEqualTo(tabName1);
tbl = client.getTable(dbName, "tbl1");
assertThat(tbl).isNotNull();
assertThat(tbl.getDbName()).isEqualTo(dbName);
assertThat(tbl.getTableName()).isEqualTo("tbl1");
client.close();
// Verify a user with ALL privileges can read the table metadata
client = context.getMetaStoreClient(USER3_1);
tbl = client.getTable(dbName, tabName1);
assertThat(tbl).isNotNull();
assertThat(tbl.getDbName()).isEqualTo(dbName);
assertThat(tbl.getTableName()).isEqualTo(tabName1);
client.close();
// Verify a user without privileges cannot read the table metadata
client = context.getMetaStoreClient(USER3_1);
try {
client.getTable(dbName, "tbl1");
fail("MetaException exepected because USER3_1 does not have privileges on 'tbl1'");
} catch (Exception e) {
assertThat(e).isInstanceOf(MetaException.class)
.hasMessageContaining("does not have privileges for DESCTABLE");
}
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", "")));
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", "")));
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);
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);
// 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);
// 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);
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);
// 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();
client_USER1_1.close();
client_USER2_1.close();
client_USER3_1.close();
client_USER4_1.close();
client_USER5_1.close();
}
}