blob: e4c9b27571b2518f001cc4eb37a58e3b7d39c8af [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.hive;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Set;
import org.apache.sentry.binding.hive.authz.SentryConfigTool;
import org.apache.sentry.binding.hive.conf.HiveAuthzConf;
import org.apache.sentry.core.common.exception.SentryConfigurationException;
import org.apache.sentry.core.common.Subject;
import org.apache.sentry.core.common.utils.PolicyFile;
import org.junit.Before;
import org.junit.Test;
public class TestConfigTool extends AbstractTestWithStaticConfiguration {
private static final String DB2_POLICY_FILE = "db2-policy-file.ini";
private static String prefix;
private PolicyFile policyFile;
private SentryConfigTool configTool;
@Before
public void setup() throws Exception {
policyFile = PolicyFile.setAdminOnServer1(ADMINGROUP);
configTool = new SentryConfigTool();
String hiveServer2 = System.getProperty("sentry.e2etest.hiveServer2Type",
"InternalHiveServer2");
String policyOnHDFS = System.getProperty(
"sentry.e2etest.hive.policyOnHDFS", "true");
if (policyOnHDFS.trim().equalsIgnoreCase("true")
&& (hiveServer2.equals("UnmanagedHiveServer2"))) {
String policyLocation = System.getProperty(
"sentry.e2etest.hive.policy.location", "/user/hive/sentry");
prefix = "hdfs://" + policyLocation + "/";
} else {
prefix = "file://" + context.getPolicyFile().getParent() + "/";
}
}
/**
* Verify errors/warnings from malformed policy file
* @throws Exception
*/
@Test
public void testInvalidPolicy() throws Exception {
// policy file, missing insert_tab2 and select_tab3 role definition
policyFile
.addRolesToGroup(USERGROUP1, "select_tab1", "insert_tab2")
.addRolesToGroup(USERGROUP2, "select_tab3")
.addPermissionsToRole("select_tab1",
"server=server1->db=db1->table=tab1->action=select")
.setUserGroupMapping(StaticUserGroup.getStaticMapping());
policyFile.write(context.getPolicyFile());
configTool.setPolicyFile(context.getPolicyFile().getPath());
configTool.setupConfig();
try {
configTool.getSentryProvider().validateResource(true);
fail("Policy validation should fail for malformed policy");
} catch (SentryConfigurationException e) {
assertTrue(e
.getConfigWarnings()
.get(0)
.contains(
"Role select_tab3 for group " + USERGROUP2 + " does not exist"));
assertTrue(e
.getConfigWarnings()
.get(1)
.contains(
"Role insert_tab2 for group " + USERGROUP1 + " does not exist"));
}
}
/**
* Verify errors/warnings from malformed policy file with per-DB policy
* @throws Exception
*/
@Test
public void testInvalidPerDbPolicy() throws Exception {
PolicyFile db2PolicyFile = new PolicyFile();
File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(),
DB2_POLICY_FILE);
// invalid db2 policy file with missing roles
db2PolicyFile
.addRolesToGroup(USERGROUP2, "select_tbl2", "insert_db2_tab2")
.addPermissionsToRole("select_tbl2",
"server=server1->db=db2->table=tbl2->action=select")
.write(db2PolicyFileHandle);
policyFile
.addRolesToGroup(USERGROUP1, "select_tbl1")
.addRolesToGroup(USERGROUP2, "select_tbl3")
.addPermissionsToRole("select_tbl1",
"server=server1->db=db1->table=tbl1->action=select")
.addDatabase("db2", prefix + db2PolicyFileHandle.getName())
.setUserGroupMapping(StaticUserGroup.getStaticMapping())
.write(context.getPolicyFile());
configTool.setPolicyFile(context.getPolicyFile().getPath());
configTool.setupConfig();
try {
configTool.getSentryProvider().validateResource(true);
fail("Policy validation should fail for malformed policy");
} catch (SentryConfigurationException e) {
assertTrue(e
.getConfigWarnings()
.get(0)
.contains(
"Role select_tbl3 for group " + USERGROUP2 + " does not exist"));
assertTrue(e.getConfigWarnings().get(0)
.contains(context.getPolicyFile().getName()));
assertTrue(e
.getConfigWarnings()
.get(1)
.contains(
"Role insert_db2_tab2 for group " + USERGROUP2
+ " does not exist"));
assertTrue(e.getConfigWarnings().get(1)
.contains(db2PolicyFileHandle.getName()));
}
}
/**
* Validate user permissions listing
* @throws Exception
*/
@Test
public void testUserPermissions() throws Exception {
policyFile
.addRolesToGroup(USERGROUP1, "select_tab1", "insert_tab2")
.addRolesToGroup(USERGROUP2, "select_tab3")
.addRolesToGroup(USERGROUP3, "select_colA")
.addRolesToGroup(USERGROUP4, "select_colAB")
.addPermissionsToRole("select_tab1",
"server=server1->db=db1->table=tab1->action=select")
.addPermissionsToRole("insert_tab2",
"server=server1->db=db1->table=tab2->action=insert")
.addPermissionsToRole("select_tab3",
"server=server1->db=db1->table=tab3->action=select")
.addPermissionsToRole("select_colA",
"server=server1->db=db1->table=tab3->column=a->action=select")
.addPermissionsToRole("select_colAB",
"server=server1->db=db1->table=tab3->column=a->action=select")
.addPermissionsToRole("select_colAB",
"server=server1->db=db1->table=tab3->column=b->action=select")
.setUserGroupMapping(StaticUserGroup.getStaticMapping());
policyFile.write(context.getPolicyFile());
configTool.setPolicyFile(context.getPolicyFile().getPath());
configTool.setupConfig();
configTool.validatePolicy();
Set<String> permList = configTool.getSentryProvider()
.listPrivilegesForSubject(new Subject(USER1_1));
assertTrue(permList
.contains("server=server1->db=db1->table=tab1->action=select"));
assertTrue(permList
.contains("server=server1->db=db1->table=tab2->action=insert"));
permList = configTool.getSentryProvider().listPrivilegesForSubject(
new Subject(USER2_1));
assertTrue(permList
.contains("server=server1->db=db1->table=tab3->action=select"));
permList = configTool.getSentryProvider().listPrivilegesForSubject(
new Subject(USER3_1));
assertTrue(permList
.contains("server=server1->db=db1->table=tab3->column=a->action=select"));
permList = configTool.getSentryProvider().listPrivilegesForSubject(
new Subject(USER4_1));
assertTrue(permList
.contains("server=server1->db=db1->table=tab3->column=a->action=select"));
assertTrue(permList
.contains("server=server1->db=db1->table=tab3->column=b->action=select"));
permList = configTool.getSentryProvider().listPrivilegesForSubject(
new Subject(ADMIN1));
assertTrue(permList.contains("server=server1"));
}
/***
* Verify the mock compilation config setting forces query to abort
* @throws Exception
*/
@Test
public void testMockCompilation() throws Exception {
policyFile.setUserGroupMapping(StaticUserGroup.getStaticMapping());
policyFile.write(context.getPolicyFile());
// setup db objects needed by the test
Connection connection = context.createConnection(ADMIN1);
Statement statement = context.createStatement(connection);
statement.execute("DROP TABLE IF EXISTS tab1");
statement.execute("CREATE TABLE tab1(B INT, A STRING) "
+ " row format delimited fields terminated by '|' stored as textfile");
statement.execute("SELECT * FROM tab1");
statement.execute("SET " + HiveAuthzConf.HIVE_SENTRY_MOCK_COMPILATION
+ "=true");
try {
statement.execute("SELECT * FROM tab1");
fail("Query should fail with mock error config enabled");
} catch (SQLException e) {
assertTrue(e.getMessage().contains(HiveAuthzConf.HIVE_SENTRY_MOCK_ERROR));
}
statement.close();
}
/**
* verify missing permissions for query using remote query validation
* @throws Exception
*/
@Test
public void testQueryPermissions() throws Exception {
policyFile
.addRolesToGroup(USERGROUP1, "select_tab1", "insert_tab2")
.addRolesToGroup(USERGROUP2, "select_tab3")
.addRolesToGroup(USERGROUP3, "select_colAB")
.addRolesToGroup(USERGROUP4, "select_colA")
.addPermissionsToRole("select_tab1",
"server=server1->db=default->table=tab1->action=select")
.addPermissionsToRole("insert_tab2",
"server=server1->db=default->table=tab2->action=insert")
.addPermissionsToRole("select_tab3",
"server=server1->db=default->table=tab3->action=select")
.addPermissionsToRole("select_colA",
"server=server1->db=default->table=tab1->column=a->action=select")
.addPermissionsToRole("select_colAB",
"server=server1->db=default->table=tab1->column=a->action=select")
.addPermissionsToRole("select_colAB",
"server=server1->db=default->table=tab1->column=b->action=select")
.setUserGroupMapping(StaticUserGroup.getStaticMapping());
policyFile.write(context.getPolicyFile());
// setup db objects needed by the test
Connection connection = context.createConnection(ADMIN1);
Statement statement = context.createStatement(connection);
statement.execute("DROP TABLE IF EXISTS tab1");
statement.execute("DROP TABLE IF EXISTS tab2");
statement.execute("DROP TABLE IF EXISTS tab3");
statement.execute("CREATE TABLE tab1(b INT, a STRING) "
+ " row format delimited fields terminated by '|' stored as textfile");
statement.execute("CREATE TABLE tab2(b INT, a STRING) "
+ " row format delimited fields terminated by '|' stored as textfile");
statement.execute("CREATE TABLE tab3(b INT, a STRING) "
+ " row format delimited fields terminated by '|' stored as textfile");
statement.close();
connection.close();
configTool.setPolicyFile(context.getPolicyFile().getPath());
configTool.setJdbcURL(context.getConnectionURL());
configTool.setUser(USER1_1);
configTool.setupConfig();
ByteArrayOutputStream errBuffer = new ByteArrayOutputStream();
// user1_1 can query table1
configTool.setUser(USER1_1);
configTool.verifyRemoteQuery("SELECT COUNT(*) FROM tab1");
// user1_1 can't select from tab3
try {
System.setOut(new PrintStream(errBuffer));
configTool.setUser(USER1_1);
configTool.verifyRemoteQuery("SELECT COUNT(*) FROM tab3");
fail("Query should have failed with insufficient perms");
} catch (SQLException e) {
assertTrue(errBuffer.toString().contains(
"Server=server1->Db=default->Table=tab3->action=select"));
errBuffer.flush();
}
// user2_1 can select from tab3, but can't insert into tab2
try {
configTool.setUser(USER2_1);
configTool
.verifyRemoteQuery("INSERT OVERWRITE TABLE tab2 SELECT * FROM tab3");
fail("Query should have failed with insufficient perms");
} catch (SQLException e) {
assertTrue(errBuffer.toString().contains(
"Server=server1->Db=default->Table=tab2->action=insert"));
errBuffer.flush();
}
// user3_1 can select A from tab1, but can't select B from tab1
configTool.setUser(USER3_1);
configTool.verifyRemoteQuery("SELECT a FROM tab1");
configTool.verifyRemoteQuery("SELECT COUNT(a) FROM tab1");
configTool.verifyRemoteQuery("SELECT b FROM tab1");
configTool.verifyRemoteQuery("SELECT COUNT(b) FROM tab1");
configTool.verifyRemoteQuery("SELECT a,b FROM tab1");
// user4_1 can select A from tab1, but can't select B from tab1
configTool.setUser(USER4_1);
configTool.verifyRemoteQuery("SELECT a FROM tab1");
configTool.verifyRemoteQuery("SELECT COUNT(a) FROM tab1");
try {
configTool.setUser(USER4_1);
configTool
.verifyRemoteQuery("SELECT b FROM tab1");
fail("Query should have failed with insufficient perms");
} catch (SQLException e) {
assertTrue(errBuffer.toString().contains(
"Server=server1->Db=default->Table=tab1->Column=b->action=select"));
errBuffer.flush();
}
try {
configTool.setUser(USER4_1);
configTool
.verifyRemoteQuery("SELECT COUNT(b) FROM tab1");
fail("Query should have failed with insufficient perms");
} catch (SQLException e) {
assertTrue(errBuffer.toString().contains(
"Server=server1->Db=default->Table=tab1->Column=b->action=select"));
}
}
}