IMPALA-6802 (part 6): Clean up authorization tests This is the last part of the authorization test clean up.
This patch rewrites the following tests: - alter database - explain - comment on - function - alter table/view This patch also adds the following authorization tests: - update - upsert - delete The tests in AuthorizationTest.java that have been rewritten into AuthorizationStmtTest.java are removed. Cherry-picks: not for 2.x Change-Id: Id594ce09a821aef4a1debfdd61569a11defd1c55 Reviewed-on: http://gerrit.cloudera.org:8080/10841 Reviewed-by: Impala Public Jenkins <[email protected]> Tested-by: Impala Public Jenkins <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/impala/repo Commit: http://git-wip-us.apache.org/repos/asf/impala/commit/5c880e52 Tree: http://git-wip-us.apache.org/repos/asf/impala/tree/5c880e52 Diff: http://git-wip-us.apache.org/repos/asf/impala/diff/5c880e52 Branch: refs/heads/master Commit: 5c880e52bc82270588496817fbbf1fb62ad2ef0d Parents: 4ce2af9 Author: Fredy Wijaya <[email protected]> Authored: Wed Jun 27 12:59:20 2018 -0700 Committer: Impala Public Jenkins <[email protected]> Committed: Fri Jun 29 19:16:24 2018 +0000 ---------------------------------------------------------------------- .../impala/analysis/AuthorizationStmtTest.java | 595 +++++- .../impala/analysis/AuthorizationTest.java | 2016 ------------------ 2 files changed, 554 insertions(+), 2057 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/impala/blob/5c880e52/fe/src/test/java/org/apache/impala/analysis/AuthorizationStmtTest.java ---------------------------------------------------------------------- diff --git a/fe/src/test/java/org/apache/impala/analysis/AuthorizationStmtTest.java b/fe/src/test/java/org/apache/impala/analysis/AuthorizationStmtTest.java index 1d4c593..0a32fc9 100644 --- a/fe/src/test/java/org/apache/impala/analysis/AuthorizationStmtTest.java +++ b/fe/src/test/java/org/apache/impala/analysis/AuthorizationStmtTest.java @@ -297,6 +297,45 @@ public class AuthorizationStmtTest extends FrontendTestBase { verifyPrivilegeReqs("drop view functional.alltypes_view", expectedAuthorizables); verifyPrivilegeReqs(createAnalysisCtx("functional"), "drop view alltypes_view", expectedAuthorizables); + + // Update table. + expectedAuthorizables = Sets.newHashSet( + "functional_kudu.alltypes", + "functional_kudu.alltypes.id", + "functional_kudu.alltypes.int_col"); + verifyPrivilegeReqs("update functional_kudu.alltypes set int_col = 1", + expectedAuthorizables); + verifyPrivilegeReqs(createAnalysisCtx("functional_kudu"), + "update alltypes set int_col = 1", expectedAuthorizables); + + // Upsert table. + expectedAuthorizables = Sets.newHashSet("functional_kudu.alltypes"); + verifyPrivilegeReqs("upsert into table functional_kudu.alltypes(id, int_col) " + + "values(1, 1)", expectedAuthorizables); + verifyPrivilegeReqs(createAnalysisCtx("functional_kudu"), + "upsert into table alltypes(id, int_col) values(1, 1)", expectedAuthorizables); + + // Delete table. + expectedAuthorizables = Sets.newHashSet( + "functional_kudu.alltypes", + "functional_kudu.alltypes.id"); + verifyPrivilegeReqs("delete from functional_kudu.alltypes", expectedAuthorizables); + verifyPrivilegeReqs(createAnalysisCtx("functional_kudu"), "delete from alltypes", + expectedAuthorizables); + + // Alter table. + expectedAuthorizables = Sets.newHashSet("functional.alltypes"); + verifyPrivilegeReqs("alter table functional.alltypes add columns(c1 int)", + expectedAuthorizables); + verifyPrivilegeReqs(createAnalysisCtx("functional"), "alter table alltypes " + + "add columns(c1 int)", expectedAuthorizables); + + // Alter view. + expectedAuthorizables = Sets.newHashSet("functional.alltypes_view"); + verifyPrivilegeReqs("alter view functional.alltypes_view as select 1", + expectedAuthorizables); + verifyPrivilegeReqs(createAnalysisCtx("functional"), "alter view alltypes_view as " + + "select 1", expectedAuthorizables); } @Test @@ -403,6 +442,23 @@ public class AuthorizationStmtTest extends FrontendTestBase { onTable("functional_seq_snap", "subquery_view", allExcept( TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT))); + // Select a UDF. + ScalarFunction fn = addFunction("functional", "f"); + try { + authorize("select functional.f()") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(viewMetadataPrivileges())) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", viewMetadataPrivileges())) + .error(accessError("functional")) + .error(accessError("functional"), onServer(allExcept( + viewMetadataPrivileges()))) + .error(accessError("functional"), onDatabase("functional", allExcept( + viewMetadataPrivileges()))); + } finally { + removeFunction(fn); + } + // Select from non-existent database. authorize("select 1 from nodb.alltypes") .error(selectError("nodb.alltypes")); @@ -557,20 +613,24 @@ public class AuthorizationStmtTest extends FrontendTestBase { @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))); + for (AuthzTest test: new AuthzTest[]{ + authorize("insert into functional.zipcode_incomes(id) values('123')"), + // Explain insert. + authorize("explain insert into functional.zipcode_incomes(id) values('123')")}) { + test.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))); + } for (AuthzTest test: new AuthzTest[]{ // With clause with insert. @@ -1218,33 +1278,38 @@ public class AuthorizationStmtTest extends FrontendTestBase { } // CTAS. - authorize("create table functional.new_table as " + - "select int_col from functional.alltypes") - .ok(onServer(TPrivilegeLevel.ALL)) - .ok(onServer(TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT, - TPrivilegeLevel.SELECT)) - .ok(onDatabase("functional", TPrivilegeLevel.ALL)) - .ok(onDatabase("functional", TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT, - TPrivilegeLevel.SELECT)) - .ok(onDatabase("functional"), onDatabase("functional", TPrivilegeLevel.CREATE, - TPrivilegeLevel.INSERT), onTable("functional", "alltypes", - TPrivilegeLevel.SELECT)) - .ok(onDatabase("functional"), onDatabase("functional", TPrivilegeLevel.CREATE, - TPrivilegeLevel.INSERT), onColumn("functional", "alltypes", "int_col", - TPrivilegeLevel.ALL)) - .error(createError("functional.new_table")) - .error(createError("functional.new_table"), onServer(allExcept( - TPrivilegeLevel.ALL, TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT, - TPrivilegeLevel.SELECT))) - .error(createError("functional.new_table"), onDatabase("functional", allExcept( - TPrivilegeLevel.ALL, TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT, - TPrivilegeLevel.SELECT))) - .error(createError("functional.new_table"), onDatabase("functional", allExcept( - TPrivilegeLevel.ALL, TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT)), - onTable("functional", "alltypes", TPrivilegeLevel.SELECT)) - .error(selectError("functional.alltypes"), onDatabase("functional", - TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT), onTable("functional", - "alltypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT))); + for (AuthzTest test: new AuthzTest[]{ + authorize("create table functional.new_table as " + + "select int_col from functional.alltypes"), + // Explain CTAS. + authorize("explain create table functional.new_table as " + + "select int_col from functional.alltypes")}) { + test.ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT, + TPrivilegeLevel.SELECT)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT, + TPrivilegeLevel.SELECT)) + .ok(onDatabase("functional"), onDatabase("functional", TPrivilegeLevel.CREATE, + TPrivilegeLevel.INSERT), onTable("functional", "alltypes", + TPrivilegeLevel.SELECT)) + .ok(onDatabase("functional"), onDatabase("functional", TPrivilegeLevel.CREATE, + TPrivilegeLevel.INSERT), onColumn("functional", "alltypes", "int_col", + TPrivilegeLevel.ALL)) + .error(createError("functional.new_table")) + .error(createError("functional.new_table"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT, + TPrivilegeLevel.SELECT))) + .error(createError("functional.new_table"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT, + TPrivilegeLevel.SELECT))) + .error(createError("functional.new_table"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT)), + onTable("functional", "alltypes", TPrivilegeLevel.SELECT)) + .error(selectError("functional.alltypes"), onDatabase("functional", + TPrivilegeLevel.CREATE, TPrivilegeLevel.INSERT), onTable("functional", + "alltypes", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT))); + } // Table with a specific location. authorize("create table functional.new_table(i int) location " + @@ -1562,6 +1627,446 @@ public class AuthorizationStmtTest extends FrontendTestBase { .error(systemDbError(), onServer(TPrivilegeLevel.ALL)); } + @Test + public void testAlterTable() throws ImpalaException { + for (AuthzTest test: new AuthzTest[]{ + authorize("alter table functional.alltypes add columns(c1 int)"), + authorize("alter table functional.alltypes replace columns(c1 int)"), + authorize("alter table functional.alltypes change int_col c1 int"), + authorize("alter table functional.alltypes drop int_col"), + authorize("alter table functional.alltypes set fileformat parquet"), + authorize("alter table functional.alltypes set tblproperties('a'='b')"), + authorize("alter table functional.alltypes partition(year=2009) " + + "set tblproperties('a'='b')"), + authorize("alter table functional.alltypes set cached in 'testPool'"), + authorize("alter table functional.alltypes partition(year=2009) set cached " + + "in 'testPool'"), + authorize("alter table functional.alltypes sort by (id)"), + authorize("alter table functional.alltypes set column stats int_col " + + "('numNulls'='1')"), + authorize("alter table functional.alltypes recover partitions"), + authorize("alter table functional.alltypes set row format delimited fields " + + "terminated by ' '"), + authorize("alter table functional.alltypes partition(year=2009) set row format " + + "delimited fields terminated by ' '"), + authorize("alter table functional.alltypes add partition(year=1, month=1)"), + authorize("alter table functional.alltypes drop partition(" + + "year=2009, month=1)")}) { + test.ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.ALTER)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALTER)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.ALTER)) + .error(alterError("functional.alltypes")) + .error(alterError("functional.alltypes"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional.alltypes"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional.alltypes"), onTable("functional", "alltypes", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + } + + // Alter table rename. + authorize("alter table functional.alltypes rename to functional.new_table") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE)) + .ok(onDatabase("functional", TPrivilegeLevel.CREATE), onTable("functional", + "alltypes", TPrivilegeLevel.ALTER)) + .error(alterError("functional.alltypes")) + .error(alterError("functional.alltypes"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE))) + .error(alterError("functional.alltypes"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE))) + .error(alterError("functional.alltypes"), onDatabase("functional", + TPrivilegeLevel.CREATE), onTable("functional", "alltypes", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(createError("functional.new_table"), onDatabase("functional", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.CREATE)), + onTable("functional", "alltypes", TPrivilegeLevel.ALTER)); + + // Only for Kudu tables. + for (AuthzTest test: new AuthzTest[]{ + authorize("alter table functional_kudu.testtbl alter column " + + "name drop default"), + authorize("alter table functional_kudu.testtbl alter column name " + + "set default null"), + authorize("alter table functional_kudu.testtbl add range partition " + + "1 < values < 2"), + authorize("alter table functional_kudu.testtbl drop range partition " + + "1 < values < 2")}) { + test.ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.ALTER)) + .ok(onDatabase("functional_kudu", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional_kudu", TPrivilegeLevel.ALTER)) + .ok(onTable("functional_kudu", "testtbl", TPrivilegeLevel.ALL)) + .ok(onTable("functional_kudu", "testtbl", TPrivilegeLevel.ALTER)) + .error(alterError("functional_kudu.testtbl")) + .error(alterError("functional_kudu.testtbl"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional_kudu.testtbl"), onDatabase("functional_kudu", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional_kudu.testtbl"), onTable("functional_kudu", + "testtbl", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + } + + // Alter table set location. + for (AuthzTest test: new AuthzTest[] { + authorize("alter table functional.alltypes set location " + + "'hdfs://localhost:20500/test-warehouse/new_table'"), + authorize("alter table functional.alltypes partition(year=2009, month=1) " + + "set location 'hdfs://localhost:20500/test-warehouse/new_table'")}) { + test.ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.ALTER), onUri( + "hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL), onUri( + "hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALTER), onUri( + "hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL), onUri( + "hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.ALTER), onUri( + "hdfs://localhost:20500/test-warehouse/new_table", TPrivilegeLevel.ALL)) + .error(alterError("functional.alltypes")) + .error(alterError("functional.alltypes"), + onServer(allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER)), + onUri("hdfs://localhost:20500/test-warehouse/new_table")) + .error(alterError("functional.alltypes"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER)), + onUri("hdfs://localhost:20500/test-warehouse/new_table")) + .error(alterError("functional.alltypes"), onTable("functional", "alltypes", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER)), + onUri("hdfs://localhost:20500/test-warehouse/new_table")) + .error(accessError("hdfs://localhost:20500/test-warehouse/new_table"), + onDatabase("functional", TPrivilegeLevel.ALTER)) + .error(accessError("hdfs://localhost:20500/test-warehouse/new_table"), + onTable("functional", "alltypes", TPrivilegeLevel.ALTER)); + } + + // Database does not exist. + authorize("alter table nodb.alltypes add columns(c1 int)") + .error(alterError("nodb")) + .error(alterError("nodb"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + + // Table does not exist. + authorize("alter table functional.notbl add columns(c1 int)") + .error(alterError("functional.notbl")) + .error(alterError("functional.notbl"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional.notbl"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + } + + @Test + public void testAlterView() throws ImpalaException { + for (AuthzTest test: new AuthzTest[] { + authorize("alter view functional.alltypes_view as " + + "select int_col from functional.alltypes"), + authorize("alter view functional.alltypes_view(a) as " + + "select int_col from functional.alltypes")}) { + test.ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.ALTER), onTable("functional", "alltypes", + TPrivilegeLevel.SELECT)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER, + TPrivilegeLevel.SELECT)) + .ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALTER), + onTable("functional", "alltypes", TPrivilegeLevel.SELECT)) + .error(selectError("functional.alltypes")) + .error(selectError("functional.alltypes"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER, TPrivilegeLevel.SELECT))) + .error(selectError("functional.alltypes"), onDatabase("functional", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER, + TPrivilegeLevel.SELECT))) + .error(alterError("functional.alltypes_view"), onTable("functional", "alltypes", + TPrivilegeLevel.SELECT), onTable("functional", "alltypes_view", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(selectError("functional.alltypes"), onTable("functional", "alltypes", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT)), + onTable("functional", "alltypes_view", TPrivilegeLevel.ALTER)); + } + + // Alter view rename. + authorize("alter view functional.alltypes_view rename to functional.new_view") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE)) + .ok(onDatabase("functional", TPrivilegeLevel.CREATE), onTable("functional", + "alltypes_view", TPrivilegeLevel.ALTER)) + .error(alterError("functional.alltypes_view")) + .error(alterError("functional.alltypes_view"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE))) + .error(alterError("functional.alltypes_view"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER, TPrivilegeLevel.CREATE))) + .error(alterError("functional.alltypes_view"), onDatabase("functional", + TPrivilegeLevel.CREATE), onTable("functional", "alltypes_view", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(createError("functional.new_view"), onDatabase("functional", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.CREATE)), + onTable("functional", "alltypes_view", TPrivilegeLevel.ALTER)); + + // Alter view with constant select. + authorize("alter view functional.alltypes_view as select 1") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.ALTER)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALTER)) + .ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALL)) + .ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALTER)) + .error(alterError("functional.alltypes_view")) + .error(alterError("functional.alltypes_view"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional.alltypes_view"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional.alltypes_view"), onTable("functional", + "alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + + // Database does not exist. + authorize("alter view nodb.alltypes_view as select 1") + .error(alterError("nodb")) + .error(alterError("nodb"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + + // View does not exist. + authorize("alter view functional.noview as select 1") + .error(alterError("functional.noview")) + .error(alterError("functional.noview"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional.noview"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + } + + @Test + public void testAlterDatabase() throws ImpalaException { + for (String ownerType: new String[]{"user", "role"}) { + authorize(String.format("alter database functional set owner %s foo", ownerType)) + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.ALTER)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALTER)) + .error(alterError("functional")) + .error(alterError("functional"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + + // Database does not exist. + authorize(String.format("alter database nodb set owner %s foo", ownerType)) + .error(alterError("nodb")) + .error(alterError("nodb"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + } + } + + @Test + public void testUpdate() throws ImpalaException { + // Update is only supported on Kudu tables. + for (AuthzTest test: new AuthzTest[]{ + authorize("update functional_kudu.alltypes set int_col = 1"), + // Explain update. + authorize("explain update functional_kudu.alltypes set int_col = 1")}) { + test.ok(onServer(TPrivilegeLevel.ALL)) + .error(accessError("functional_kudu.alltypes")) + .error(accessError("functional_kudu.alltypes"), onServer(allExcept( + TPrivilegeLevel.ALL))); + } + + // Database does not exist. + authorize("update nodb.alltypes set int_col = 1") + .error(selectError("nodb")) + .error(selectError("nodb"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT))); + + // Table does not exist. + authorize("update functional_kudu.notbl set int_col = 1") + .error(selectError("functional_kudu.notbl")) + .error(selectError("functional_kudu.notbl"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT))) + .error(selectError("functional_kudu.notbl"), onDatabase("functional_kudu", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT))); + } + + @Test + public void testUpsert() throws ImpalaException { + // Upsert is only supported on Kudu tables. + for (AuthzTest test: new AuthzTest[]{ + authorize("upsert into table functional_kudu.testtbl(id, name) values(1, 'a')"), + // Upsert with clause. + authorize("with t1 as (select 1, 'a', 2) upsert into functional_kudu.testtbl " + + "select * from t1"), + // Explain upsert. + authorize("explain upsert into table functional_kudu.testtbl(id, name) " + + "values(1, 'a')")}) { + test.ok(onServer(TPrivilegeLevel.ALL)) + .error(accessError("functional_kudu.testtbl")) + .error(accessError("functional_kudu.testtbl"), onServer(allExcept( + TPrivilegeLevel.ALL))); + } + + // Upsert select. + authorize("upsert into table functional_kudu.testtbl(id) " + + "select int_col from functional.alltypes") + .ok(onServer(TPrivilegeLevel.ALL)) + .error(selectError("functional.alltypes")) + .error(accessError("functional_kudu.testtbl"), onServer(allExcept( + TPrivilegeLevel.ALL))); + + // Database does not exist. + authorize("upsert into table nodb.testtbl(id, name) values(1, 'a')") + .error(accessError("nodb.testtbl")) + .error(accessError("nodb.testtbl"), onServer(allExcept(TPrivilegeLevel.ALL))); + + // Table does not exist. + authorize("upsert into table functional_kudu.notbl(id, name) values(1, 'a')") + .error(accessError("functional_kudu.notbl")) + .error(accessError("functional_kudu.notbl"), onServer(allExcept( + TPrivilegeLevel.ALL))) + .error(accessError("functional_kudu.notbl"), onDatabase("functional_kudu", + allExcept(TPrivilegeLevel.ALL))); + } + + @Test + public void testDelete() throws ImpalaException { + // Delete is only supported on Kudu tables. + for (AuthzTest test: new AuthzTest[]{ + authorize("delete from functional_kudu.alltypes"), + authorize("explain delete from functional_kudu.alltypes")}) { + test.ok(onServer(TPrivilegeLevel.ALL)) + .error(accessError("functional_kudu.alltypes")) + .error(accessError("functional_kudu.alltypes"), onServer(allExcept( + TPrivilegeLevel.ALL))); + } + + // Database does not exist. + authorize("delete from nodb.alltypes") + .error(selectError("nodb")) + .error(selectError("nodb"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT))); + + // Table does not exist. + authorize("delete from functional_kudu.notbl") + .error(selectError("functional_kudu.notbl")) + .error(selectError("functional_kudu.notbl"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT))) + .error(selectError("functional_kudu.notbl"), onDatabase("functional_kudu", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.SELECT))); + } + + @Test + public void testCommentOn() throws ImpalaException { + // Comment on database. + authorize("comment on database functional is 'comment'") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.ALTER)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALTER)) + .error(alterError("functional")) + .error(alterError("functional"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + + // Comment on table. + authorize("comment on table functional.alltypes is 'comment'") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.ALTER)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALTER)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.ALL)) + .ok(onTable("functional", "alltypes", TPrivilegeLevel.ALTER)) + .error(alterError("functional.alltypes")) + .error(alterError("functional.alltypes"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional.alltypes"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional.alltypes"), onTable("functional", "alltypes", + allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + + // Comment on view. + authorize("comment on view functional.alltypes_view is 'comment'") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.ALTER)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALTER)) + .ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALL)) + .ok(onTable("functional", "alltypes_view", TPrivilegeLevel.ALTER)) + .error(alterError("functional.alltypes_view")) + .error(alterError("functional.alltypes_view"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional.alltypes_view"), onDatabase("functional", allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))) + .error(alterError("functional.alltypes_view"), onTable("functional", + "alltypes_view", allExcept(TPrivilegeLevel.ALL, TPrivilegeLevel.ALTER))); + } + + @Test + public void testFunction() throws ImpalaException { + // Create function. + authorize("create function functional.f() returns int location " + + "'/test-warehouse/libTestUdfs.so' symbol='NoArgs'") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.CREATE), onUri("/test-warehouse/libTestUdfs.so", + TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL), + onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.CREATE), + onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL)) + .error(createFunctionError("functional.f()")) + .error(accessError("hdfs://localhost:20500/test-warehouse/libTestUdfs.so"), + onServer(allExcept(TPrivilegeLevel.ALL))) + .error(createFunctionError("functional.f()"), + onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL)); + + // Create a function name that has the same name as built-in function is OK. + authorize("create function functional.sin() returns int location " + + "'/test-warehouse/libTestUdfs.so' symbol='NoArgs'") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.CREATE), onUri("/test-warehouse/libTestUdfs.so", + TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL), + onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.CREATE), + onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL)) + .error(createFunctionError("functional.sin()")) + .error(accessError("hdfs://localhost:20500/test-warehouse/libTestUdfs.so"), + onServer(allExcept(TPrivilegeLevel.ALL))) + .error(createFunctionError("functional.sin()"), + onUri("/test-warehouse/libTestUdfs.so", TPrivilegeLevel.ALL)); + + // Creating a function in the system database even with ALL privilege on SERVER is + // not allowed. + for (AuthzTest test: new AuthzTest[] { + authorize("create function _impala_builtins.sin() returns int location " + + "'/test-warehouse/libTestUdfs.so' symbol='NoArgs'"), + authorize("create function _impala_builtins.f() returns int location " + + "'/test-warehouse/libTestUdfs.so' symbol='NoArgs'")}) { + test.error(systemDbError(), onServer(TPrivilegeLevel.ALL)); + } + + ScalarFunction fn = addFunction("functional", "f"); + try { + authorize("drop function functional.f()") + .ok(onServer(TPrivilegeLevel.ALL)) + .ok(onServer(TPrivilegeLevel.DROP)) + .ok(onDatabase("functional", TPrivilegeLevel.ALL)) + .ok(onDatabase("functional", TPrivilegeLevel.DROP)) + .error(dropFunctionError("functional.f()")) + .error(dropFunctionError("functional.f()"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.DROP))); + + // Function does not exist but with if exists clause. + authorize("drop function if exists functional.g()") + .error(dropFunctionError("functional.g()")) + .error(dropFunctionError("functional.g()"), onServer(allExcept( + TPrivilegeLevel.ALL, TPrivilegeLevel.DROP))); + } finally { + removeFunction(fn); + } + } + // Convert TDescribeResult to list of strings. private static List<String> resultToStringList(TDescribeResult result) { List<String> list = new ArrayList<>(); @@ -1606,6 +2111,14 @@ public class AuthorizationStmtTest extends FrontendTestBase { return "Cannot modify system database."; } + private static String createFunctionError(String object) { + return "User '%s' does not have privileges to CREATE functions in: " + object; + } + + private static String dropFunctionError(String object) { + return "User '%s' does not have privileges to DROP functions in: " + object; + } + private ScalarFunction addFunction(String db, String fnName) { ScalarFunction fn = ScalarFunction.createForTesting(db, fnName, new ArrayList<Type>(), Type.INT, "/dummy", "dummy.class", null,
