This is an automated email from the ASF dual-hosted git repository. arodoni pushed a commit to branch 2.x in repository https://gitbox.apache.org/repos/asf/impala.git
commit e75a5b1f3faf371b75ae980b2ae511ec55b44057 Author: Fredy Wijaya <fwij...@cloudera.com> AuthorDate: Tue May 1 14:00:14 2018 -0500 IMPALA-6802 (part 2): Clean up authorization tests The second part of this patch is to rewrite the following authorization tests: - insert - truncate - load - use Testing: - Added new authorization tests - Ran all front-end tests Cherry-picks: not for 2.x Change-Id: Ica5bfd2f12bf0cc8ebe78464a523a7805366f67b Reviewed-on: http://gerrit.cloudera.org:8080/10269 Reviewed-by: Alex Behm <alex.b...@cloudera.com> Tested-by: Impala Public Jenkins <impala-public-jenk...@cloudera.com> Reviewed-on: http://gerrit.cloudera.org:8080/12709 Reviewed-by: Fredy Wijaya <fwij...@cloudera.com> --- .../impala/analysis/AuthorizationTestV2.java | 305 +++++++++++++++++++-- 1 file changed, 282 insertions(+), 23 deletions(-) diff --git a/fe/src/test/java/org/apache/impala/analysis/AuthorizationTestV2.java b/fe/src/test/java/org/apache/impala/analysis/AuthorizationTestV2.java index a46196a..9845368 100644 --- a/fe/src/test/java/org/apache/impala/analysis/AuthorizationTestV2.java +++ b/fe/src/test/java/org/apache/impala/analysis/AuthorizationTestV2.java @@ -18,7 +18,6 @@ package org.apache.impala.analysis; import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; import org.apache.impala.analysis.AnalysisContext.AnalysisResult; import org.apache.impala.authorization.AuthorizationConfig; @@ -91,7 +90,7 @@ public class AuthorizationTestV2 extends FrontendTestBase { @Test public void testPrivilegeRequests() throws ImpalaException { // Select * - Set<String> expectedPrivileges = Sets.newHashSet( + Set<String> expectedAuthorizables = Sets.newHashSet( "functional.alltypes", "functional.alltypes.id", "functional.alltypes.bool_col", @@ -107,29 +106,63 @@ public class AuthorizationTestV2 extends FrontendTestBase { "functional.alltypes.year", "functional.alltypes.month" ); - verifyPrivilegeReqs("select * from functional.alltypes", expectedPrivileges); - verifyPrivilegeReqs("select alltypes.* from functional.alltypes", expectedPrivileges); + verifyPrivilegeReqs("select * from functional.alltypes", expectedAuthorizables); + verifyPrivilegeReqs("select alltypes.* from functional.alltypes", expectedAuthorizables); verifyPrivilegeReqs(createAnalysisCtx("functional"), "select * from alltypes", - expectedPrivileges); + expectedAuthorizables); verifyPrivilegeReqs(createAnalysisCtx("functional"), - "select alltypes.* from alltypes", expectedPrivileges); - verifyPrivilegeReqs("select a.* from functional.alltypes a", expectedPrivileges); + "select alltypes.* from alltypes", expectedAuthorizables); + verifyPrivilegeReqs("select a.* from functional.alltypes a", expectedAuthorizables); // Select a specific column. - expectedPrivileges = Sets.newHashSet( + expectedAuthorizables = Sets.newHashSet( "functional.alltypes", "functional.alltypes.id" ); - verifyPrivilegeReqs("select id from functional.alltypes", expectedPrivileges); + verifyPrivilegeReqs("select id from functional.alltypes", expectedAuthorizables); verifyPrivilegeReqs("select alltypes.id from functional.alltypes", - expectedPrivileges); + expectedAuthorizables); verifyPrivilegeReqs(createAnalysisCtx("functional"), - "select alltypes.id from alltypes", expectedPrivileges); + "select alltypes.id from alltypes", expectedAuthorizables); verifyPrivilegeReqs(createAnalysisCtx("functional"), "select id from alltypes", - expectedPrivileges); + expectedAuthorizables); verifyPrivilegeReqs("select alltypes.id from functional.alltypes", - expectedPrivileges); - verifyPrivilegeReqs("select a.id from functional.alltypes a", expectedPrivileges); + expectedAuthorizables); + verifyPrivilegeReqs("select a.id from functional.alltypes a", expectedAuthorizables); + + // Insert. + expectedAuthorizables = Sets.newHashSet("functional.alltypes"); + verifyPrivilegeReqs("insert into functional.alltypes(id) partition(month, year) " + + "values(1, 1, 2018)", expectedAuthorizables); + verifyPrivilegeReqs(createAnalysisCtx("functional"), "insert into alltypes(id) " + + "partition(month, year) values(1, 1, 2018)", expectedAuthorizables); + + // Insert with constant select. + expectedAuthorizables = Sets.newHashSet("functional.zipcode_incomes"); + verifyPrivilegeReqs("insert into functional.zipcode_incomes(id) select '123'", + expectedAuthorizables); + verifyPrivilegeReqs(createAnalysisCtx("functional"), + "insert into zipcode_incomes(id) select '123'", expectedAuthorizables); + + // Truncate. + expectedAuthorizables = Sets.newHashSet("functional.alltypes"); + verifyPrivilegeReqs("truncate table functional.alltypes", expectedAuthorizables); + verifyPrivilegeReqs(createAnalysisCtx("functional"), + "truncate table alltypes", expectedAuthorizables); + + // Load + expectedAuthorizables = Sets.newHashSet( + "functional.alltypes", + "hdfs://localhost:20500/test-warehouse/tpch.lineitem" + ); + verifyPrivilegeReqs("load data inpath " + + "'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " + + "into table functional.alltypes partition(month=10, year=2009)", + expectedAuthorizables); + verifyPrivilegeReqs(createAnalysisCtx("functional"), "load data inpath " + + "'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " + + "into table alltypes partition(month=10, year=2009)", + expectedAuthorizables); } @Test @@ -370,10 +403,241 @@ public class AuthorizationTestV2 extends FrontendTestBase { TPrivilegeLevel.SELECT))); } + @Test + public void testInsert() throws ImpalaException { + // Basic insert into a table. + authorize("insert into functional.zipcode_incomes(id) values('123')") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.INSERT)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.INSERT)) + .ok(onTable("functional", "zipcode_incomes", TPrivilegeLevel.ALL)) + .ok(onTable("functional", "zipcode_incomes", TPrivilegeLevel.INSERT)) + .error(insertError("functional.zipcode_incomes")) + .error(insertError("functional.zipcode_incomes"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT))) + .error(insertError("functional.zipcode_incomes"), onDatabase("functional", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT))) + .error(insertError("functional.zipcode_incomes"), onTable("functional", + "zipcode_incomes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT))); + + // Insert with select on a target table. + authorize("insert into functional.alltypes partition(month, year) " + + "select * from functional.alltypestiny where id < 100") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL), + onTable("functional", "alltypestiny", TPrivilegeLevel.ALL)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT), + onTable("functional", "alltypestiny", TPrivilegeLevel.SELECT)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT), + onColumn("functional", "alltypestiny", new String[]{"id", "bool_col", + "tinyint_col", "smallint_col", "int_col", "bigint_col", "float_col", + "double_col", "date_string_col", "string_col", "timestamp_col", "year", + "month"}, TPrivilegeLevel.SELECT)) + .error(selectError("functional.alltypestiny")) + .error(selectError("functional.alltypestiny"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))) + .error(selectError("functional.alltypestiny"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))) + .error(insertError("functional.alltypes"), onTable("functional", + "alltypestiny", TPrivilegeLevel.SELECT), onTable("functional", + "alltypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT))) + .error(selectError("functional.alltypestiny"), onTable("functional", + "alltypestiny", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT)), + onTable("functional", "alltypes", TPrivilegeLevel.INSERT)); + + // Insert with select on a target view. + // Column-level privileges on views are not currently supported. + authorize("insert into functional.alltypes partition(month, year) " + + "select * from functional.alltypes_view where id < 100") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL), + onTable("functional", "alltypes_view", TPrivilegeLevel.ALL)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT), + onTable("functional", "alltypes_view", TPrivilegeLevel.SELECT)) + .error(selectError("functional.alltypes_view")) + .error(selectError("functional.alltypes_view"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))) + .error(selectError("functional.alltypes_view"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))) + .error(insertError("functional.alltypes"), onTable("functional", + "alltypes_view", TPrivilegeLevel.SELECT), onTable("functional", + "alltypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT))) + .error(selectError("functional.alltypes_view"), onTable("functional", + "alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT)), + onTable("functional", "alltypes", TPrivilegeLevel.INSERT)); + + // Insert with inline view. + authorize("insert into functional.alltypes partition(month, year) " + + "select b.* from functional.alltypesagg a join (select * from " + + "functional.alltypestiny) b on (a.int_col = b.int_col)") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL), + onTable("functional", "alltypesagg", TPrivilegeLevel.ALL), + onTable("functional", "alltypestiny", TPrivilegeLevel.ALL)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT), + onTable("functional", "alltypesagg", TPrivilegeLevel.SELECT), + onTable("functional", "alltypestiny", TPrivilegeLevel.SELECT)) + .error(selectError("functional.alltypesagg")) + .error(selectError("functional.alltypesagg"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))) + .error(selectError("functional.alltypesagg"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT, TPrivilegeLevel.SELECT))) + .error(insertError("functional.alltypes"), onTable("functional", + "alltypesagg", TPrivilegeLevel.SELECT), onTable("functional", + "alltypestiny", TPrivilegeLevel.SELECT), onTable("functional", + "alltypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT))) + .error(selectError("functional.alltypesagg"), onTable("functional", + "alltypesagg", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT)), + onTable("functional", "alltypestiny", TPrivilegeLevel.SELECT), + onTable("functional", "alltypes", TPrivilegeLevel.INSERT)) + .error(selectError("functional.alltypestiny"), onTable("functional", + "alltypesagg", TPrivilegeLevel.SELECT), onTable("functional", + "alltypestiny", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT)), + onTable("functional", "alltypes", TPrivilegeLevel.INSERT)); + + // Inserting into a view is not allowed. + authorize("insert into functional.alltypes_view(id) values(123)") + .error(insertError("functional.alltypes_view")); + + // Inserting into a non-existent database. + authorize("insert into nodb.alltypes(id) values(1)") + .error(insertError("nodb.alltypes")); + + // Inserting into a non-existent table. + authorize("insert into functional.notbl(id) values(1)") + .error(insertError("functional.notbl")); + } + + @Test + public void testUseDb() throws ImpalaException { + AuthzTest test = authorize("use functional"); + for (TPrivilegeLevel privilege : TPrivilegeLevel.values()) { + test.ok(onServer(privilege)) + .ok(onDatabase("functional", privilege)) + .ok(onTable("functional", "alltypes", privilege)) + .ok(onColumn("functional", "alltypes", "id", privilege)); + } + test.error(accessError("functional.*.*")); + + // Accessing default database should always be allowed. + authorize("use default").ok(); + + // Accessing system database should always be allowed. + authorize("use _impala_builtins").ok(); + + // Use a non-existent database. + authorize("use nodb").error(accessError("nodb.*.*")); + } + + @Test + public void testTruncate() throws ImpalaException { + // Truncate a table. + authorize("truncate table functional.alltypes") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.INSERT)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.INSERT)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT)) + .error(insertError("functional.alltypes")) + .error(insertError("functional.alltypes"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT))) + .error(insertError("functional.alltypes"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT))) + .error(insertError("functional.alltypes"), onTable("functional", "alltypes", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.INSERT))); + + // Truncate a non-existent database. + authorize("truncate table nodb.alltypes") + .error(insertError("nodb.alltypes")); + + // Truncate a non-existent table. + authorize("truncate table functional.notbl") + .error(insertError("functional.notbl")); + + // Truncating a view is not supported. + authorize("truncate table functional.alltypes_view") + .error(insertError("functional.alltypes_view")); + } + + @Test + public void testLoad() throws ImpalaException { + // Load into a table. + authorize("load data inpath 'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " + + "into table functional.alltypes partition(month=10, year=2009)") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL), + onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem", + TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.INSERT), + onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem", + TPrivilegeLevel.ALL)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL), + onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem", + TPrivilegeLevel.ALL)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.INSERT), + onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem", + TPrivilegeLevel.ALL)) + .error(insertError("functional.alltypes")) + .error(accessError("hdfs://localhost:20500/test-warehouse/tpch.lineitem"), + onDatabase("functional", TPrivilegeLevel.INSERT)) + .error(accessError("hdfs://localhost:20500/test-warehouse/tpch.lineitem"), + onTable("functional", "alltypes", TPrivilegeLevel.INSERT)) + .error(insertError("functional.alltypes"), + onUri("hdfs://localhost:20500/test-warehouse/tpch.lineitem", + TPrivilegeLevel.ALL)); + + // Load from non-existent URI. + authorize("load data inpath 'hdfs://localhost:20500/test-warehouse/nouri' " + + "into table functional.alltypes partition(month=10, year=2009)") + .error(insertError("functional.alltypes")) + .error(accessError("hdfs://localhost:20500/test-warehouse/nouri"), + onDatabase("functional", TPrivilegeLevel.INSERT)) + .error(accessError("hdfs://localhost:20500/test-warehouse/nouri"), + onTable("functional", "alltypes", TPrivilegeLevel.INSERT)); + + // Load into non-existent database. + authorize("load data inpath 'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " + + "into table nodb.alltypes partition(month=10, year=2009)") + .error(insertError("nodb.alltypes")) + .error(insertError("nodb.alltypes"), onUri( + "hdfs://localhost:20500/test-warehouse/tpch.nouri", TPrivilegeLevel.ALL)); + + // Load into non-existent table. + authorize("load data inpath 'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " + + "into table functional.notbl partition(month=10, year=2009)") + .error(insertError("functional.notbl")) + .error(insertError("functional.notbl"), onUri( + "hdfs://localhost:20500/test-warehouse/tpch.nouri", TPrivilegeLevel.ALL)); + + // Load into a view is not supported. + authorize("load data inpath 'hdfs://localhost:20500/test-warehouse/tpch.lineitem' " + + "into table functional.alltypes_view") + .error(insertError("functional.alltypes_view")); + } + private static String selectError(String object) { return "User '%s' does not have privileges to execute 'SELECT' on: " + object; } + private static String insertError(String object) { + return "User '%s' does not have privileges to execute 'INSERT' on: " + object; + } + + private static String accessError(String object) { + return "User '%s' does not have privileges to access: " + object; + } + private static TPrivilegeLevel[] allExcept(TPrivilegeLevel... excludedPrivLevels) { HashSet<TPrivilegeLevel> excludedSet = Sets.newHashSet(excludedPrivLevels); List<TPrivilegeLevel> privLevels = new ArrayList<>(); @@ -624,15 +888,10 @@ public class AuthorizationTestV2 extends FrontendTestBase { private void verifyPrivilegeReqs(AnalysisContext ctx, String stmt, Set<String> expectedPrivilegeNames) throws ImpalaException { AnalysisResult analysisResult = parseAndAnalyze(stmt, ctx, frontend_); - ImmutableList<PrivilegeRequest> privilegeReqs = - analysisResult.getAnalyzer().getPrivilegeReqs(); - - assertEquals(expectedPrivilegeNames.size(), privilegeReqs.size()); - - for (PrivilegeRequest privilegeReq : privilegeReqs) { - assertTrue(String.format("Privilege on %s should not exist.", - privilegeReq.getName()), - expectedPrivilegeNames.contains(privilegeReq.getName())); + Set<String> actualPrivilegeNames = Sets.newHashSet(); + for (PrivilegeRequest privReq : analysisResult.getAnalyzer().getPrivilegeReqs()) { + actualPrivilegeNames.add(privReq.getName()); } + assertEquals(expectedPrivilegeNames, actualPrivilegeNames); } }