IMPALA-6650: Add fine-grained DROP privilege

Add support for executing DROP statements by granting DROP privilege.

These are the new GRANT/REVOKE statements introduced at server,
database, and table scopes.

GRANT DROP on SERVER svr TO ROLE testrole;
GRANT DROP on DATABASE db TO ROLE testrole;
GRANT DROP on TABLE tbl TO ROLE testrole;

REVOKE DROP on SERVER svr FROM ROLE testrole;
REVOKE DROP on DATABASE db FROM ROLE testrole;
REVOKE DROP on TABLE tbl FROM ROLE testrole;

Testing:
- Added new front-end tests
- Ran front-end tests

Cherry-picks: not for 2.x

Change-Id: Iea1dfb0b117cb1725e9656b9a79a9aebee82b5e4
Reviewed-on: http://gerrit.cloudera.org:8080/9911
Reviewed-by: Alex Behm <alex.b...@cloudera.com>
Tested-by: Impala Public Jenkins


Project: http://git-wip-us.apache.org/repos/asf/impala/repo
Commit: http://git-wip-us.apache.org/repos/asf/impala/commit/c9f4fdc6
Tree: http://git-wip-us.apache.org/repos/asf/impala/tree/c9f4fdc6
Diff: http://git-wip-us.apache.org/repos/asf/impala/diff/c9f4fdc6

Branch: refs/heads/master
Commit: c9f4fdc6bc7145bb3fcfe88f15bbdf77656cdab5
Parents: 75e1bd1
Author: Fredy Wijaya <fwij...@cloudera.com>
Authored: Tue Apr 3 10:58:23 2018 -0500
Committer: Impala Public Jenkins <impala-public-jenk...@gerrit.cloudera.org>
Committed: Wed Apr 4 22:05:20 2018 +0000

----------------------------------------------------------------------
 common/thrift/CatalogObjects.thrift             |   3 +-
 fe/.gitignore                                   |   3 +
 fe/src/main/cup/sql-parser.cup                  |   2 +
 .../impala/analysis/DropFunctionStmt.java       |   7 +-
 .../apache/impala/analysis/PrivilegeSpec.java   |   7 +-
 .../authorization/AuthorizationChecker.java     |   6 +-
 .../apache/impala/authorization/Privilege.java  |   3 +-
 .../impala/analysis/AnalyzeAuthStmtsTest.java   |  18 ++-
 .../impala/analysis/AuthorizationTest.java      | 128 +++++++++++++++++--
 .../org/apache/impala/analysis/ParserTest.java  |   6 +
 fe/src/test/resources/authz-policy.ini.template |   8 +-
 11 files changed, 159 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/impala/blob/c9f4fdc6/common/thrift/CatalogObjects.thrift
----------------------------------------------------------------------
diff --git a/common/thrift/CatalogObjects.thrift 
b/common/thrift/CatalogObjects.thrift
index 703e701..ecd27dc 100644
--- a/common/thrift/CatalogObjects.thrift
+++ b/common/thrift/CatalogObjects.thrift
@@ -470,7 +470,8 @@ enum TPrivilegeLevel {
   SELECT,
   REFRESH,
   CREATE,
-  ALTER
+  ALTER,
+  DROP
 }
 
 // Represents a privilege in an authorization policy. Privileges contain the 
level

http://git-wip-us.apache.org/repos/asf/impala/blob/c9f4fdc6/fe/.gitignore
----------------------------------------------------------------------
diff --git a/fe/.gitignore b/fe/.gitignore
index 6a1675d..11a5e9d 100644
--- a/fe/.gitignore
+++ b/fe/.gitignore
@@ -33,6 +33,9 @@ src/test/resources/authz-policy.ini
 # Generated minicluster config
 src/test/resources/minicluster-conf.xml
 
+# Generated hive-log4j2.properties file
+src/test/resources/hive-log4j2.properties
+
 # Generated thrift files
 generated-sources
 

http://git-wip-us.apache.org/repos/asf/impala/blob/c9f4fdc6/fe/src/main/cup/sql-parser.cup
----------------------------------------------------------------------
diff --git a/fe/src/main/cup/sql-parser.cup b/fe/src/main/cup/sql-parser.cup
index 4d6abfd..999ed16 100644
--- a/fe/src/main/cup/sql-parser.cup
+++ b/fe/src/main/cup/sql-parser.cup
@@ -966,6 +966,8 @@ privilege ::=
   {: RESULT = TPrivilegeLevel.CREATE; :}
   | KW_ALTER
   {: RESULT = TPrivilegeLevel.ALTER; :}
+  | KW_DROP
+  {: RESULT = TPrivilegeLevel.DROP; :}
   | KW_ALL
   {: RESULT = TPrivilegeLevel.ALL; :}
   ;

http://git-wip-us.apache.org/repos/asf/impala/blob/c9f4fdc6/fe/src/main/java/org/apache/impala/analysis/DropFunctionStmt.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/analysis/DropFunctionStmt.java 
b/fe/src/main/java/org/apache/impala/analysis/DropFunctionStmt.java
index b82b9d2..86e90c0 100644
--- a/fe/src/main/java/org/apache/impala/analysis/DropFunctionStmt.java
+++ b/fe/src/main/java/org/apache/impala/analysis/DropFunctionStmt.java
@@ -85,13 +85,10 @@ public class DropFunctionStmt extends StatementBase {
           false);
     }
 
-    // For now, if authorization is enabled, the user needs ALL on the server
-    // to drop functions.
-    // TODO: this is not the right granularity but acceptable for now.
     analyzer.registerPrivReq(new PrivilegeRequest(
-        new AuthorizeableFn(desc_.dbName(), desc_.signatureString()), 
Privilege.ALL));
+        new AuthorizeableFn(desc_.dbName(), desc_.signatureString()), 
Privilege.DROP));
 
-    Db db =  analyzer.getDb(desc_.dbName(), Privilege.DROP, false);
+    Db db =  analyzer.getDb(desc_.dbName(), false);
     if (db == null && !ifExists_) {
       throw new AnalysisException(Analyzer.DB_DOES_NOT_EXIST_ERROR_MSG + 
desc_.dbName());
     }

http://git-wip-us.apache.org/repos/asf/impala/blob/c9f4fdc6/fe/src/main/java/org/apache/impala/analysis/PrivilegeSpec.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/analysis/PrivilegeSpec.java 
b/fe/src/main/java/org/apache/impala/analysis/PrivilegeSpec.java
index b2652cc..ec292a2 100644
--- a/fe/src/main/java/org/apache/impala/analysis/PrivilegeSpec.java
+++ b/fe/src/main/java/org/apache/impala/analysis/PrivilegeSpec.java
@@ -191,9 +191,10 @@ public class PrivilegeSpec implements ParseNode {
         if (privilegeLevel_ != TPrivilegeLevel.ALL &&
             privilegeLevel_ != TPrivilegeLevel.REFRESH &&
             privilegeLevel_ != TPrivilegeLevel.CREATE &&
-            privilegeLevel_ != TPrivilegeLevel.ALTER) {
-          throw new AnalysisException("Only 'ALL', 'REFRESH', 'CREATE', or 
'ALTER' " +
-              "privilege may be applied at SERVER scope in privilege spec.");
+            privilegeLevel_ != TPrivilegeLevel.ALTER &&
+            privilegeLevel_ != TPrivilegeLevel.DROP) {
+          throw new AnalysisException("Only 'ALL', 'REFRESH', 'CREATE', 
'ALTER', or " +
+              "'DROP' privilege may be applied at SERVER scope in privilege 
spec.");
         }
         break;
       case DATABASE:

http://git-wip-us.apache.org/repos/asf/impala/blob/c9f4fdc6/fe/src/main/java/org/apache/impala/authorization/AuthorizationChecker.java
----------------------------------------------------------------------
diff --git 
a/fe/src/main/java/org/apache/impala/authorization/AuthorizationChecker.java 
b/fe/src/main/java/org/apache/impala/authorization/AuthorizationChecker.java
index 07bc4ad..9fcf020 100644
--- a/fe/src/main/java/org/apache/impala/authorization/AuthorizationChecker.java
+++ b/fe/src/main/java/org/apache/impala/authorization/AuthorizationChecker.java
@@ -105,13 +105,13 @@ public class AuthorizationChecker {
     Preconditions.checkNotNull(privilegeRequest);
 
     if (!hasAccess(user, privilegeRequest)) {
+      Privilege privilege = privilegeRequest.getPrivilege();
       if (privilegeRequest.getAuthorizeable() instanceof AuthorizeableFn) {
         throw new AuthorizationException(String.format(
-            "User '%s' does not have privileges to CREATE/DROP functions in: 
%s",
-            user.getName(), privilegeRequest.getName()));
+            "User '%s' does not have privileges to %s functions in: %s",
+            user.getName(), privilege, privilegeRequest.getName()));
       }
 
-      Privilege privilege = privilegeRequest.getPrivilege();
       if (EnumSet.of(Privilege.ANY, Privilege.ALL, Privilege.VIEW_METADATA)
           .contains(privilege)) {
         throw new AuthorizationException(String.format(

http://git-wip-us.apache.org/repos/asf/impala/blob/c9f4fdc6/fe/src/main/java/org/apache/impala/authorization/Privilege.java
----------------------------------------------------------------------
diff --git a/fe/src/main/java/org/apache/impala/authorization/Privilege.java 
b/fe/src/main/java/org/apache/impala/authorization/Privilege.java
index 558e4bd..59cc8d3 100644
--- a/fe/src/main/java/org/apache/impala/authorization/Privilege.java
+++ b/fe/src/main/java/org/apache/impala/authorization/Privilege.java
@@ -27,7 +27,7 @@ import org.apache.sentry.core.common.Action;
 public enum Privilege {
   ALL(SentryAction.ALL, false),
   ALTER(SentryAction.ALTER, false),
-  DROP(SentryAction.ALL, false),
+  DROP(SentryAction.DROP, false),
   CREATE(SentryAction.CREATE, false),
   INSERT(SentryAction.INSERT, false),
   SELECT(SentryAction.SELECT, false),
@@ -56,6 +56,7 @@ public enum Privilege {
     REFRESH("refresh"),
     CREATE("create"),
     ALTER("alter"),
+    DROP("drop"),
     ALL("*");
 
     private final String value;

http://git-wip-us.apache.org/repos/asf/impala/blob/c9f4fdc6/fe/src/test/java/org/apache/impala/analysis/AnalyzeAuthStmtsTest.java
----------------------------------------------------------------------
diff --git 
a/fe/src/test/java/org/apache/impala/analysis/AnalyzeAuthStmtsTest.java 
b/fe/src/test/java/org/apache/impala/analysis/AnalyzeAuthStmtsTest.java
index d1eae40..c56102f 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AnalyzeAuthStmtsTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AnalyzeAuthStmtsTest.java
@@ -165,8 +165,8 @@ public class AnalyzeAuthStmtsTest extends AnalyzerTest {
       AnalyzesOk(String.format("%s INSERT ON DATABASE functional %s myrole",
           formatArgs));
       AnalysisError(String.format("%s INSERT ON SERVER %s myrole", formatArgs),
-          "Only 'ALL', 'REFRESH', 'CREATE', or 'ALTER' privilege may be 
applied at " +
-          "SERVER scope in privilege spec.");
+          "Only 'ALL', 'REFRESH', 'CREATE', 'ALTER', or 'DROP' privilege may 
be " +
+          "applied at SERVER scope in privilege spec.");
       AnalysisError(String.format("%s INSERT ON URI 'hdfs:////abc//123' %s 
myrole",
           formatArgs), "Only 'ALL' privilege may be applied at URI scope in 
privilege " +
           "spec.");
@@ -181,8 +181,8 @@ public class AnalyzeAuthStmtsTest extends AnalyzerTest {
       AnalyzesOk(String.format("%s SELECT ON DATABASE functional %s myrole",
           formatArgs));
       AnalysisError(String.format("%s SELECT ON SERVER %s myrole", formatArgs),
-          "Only 'ALL', 'REFRESH', 'CREATE', or 'ALTER' privilege may be 
applied at " +
-          "SERVER scope in privilege spec.");
+          "Only 'ALL', 'REFRESH', 'CREATE', 'ALTER', or 'DROP' privilege may 
be " +
+          "applied at SERVER scope in privilege spec.");
       AnalysisError(String.format("%s SELECT ON URI 'hdfs:////abc//123' %s 
myrole",
           formatArgs), "Only 'ALL' privilege may be applied at URI scope in 
privilege " +
           "spec.");
@@ -255,6 +255,16 @@ public class AnalyzeAuthStmtsTest extends AnalyzerTest {
       AnalysisError(String.format(
           "%s ALTER ON URI 'hdfs:////abc/123' %s myrole", formatArgs),
           "Only 'ALL' privilege may be applied at URI scope in privilege 
spec.");
+
+      // DROP privilege
+      AnalyzesOk(String.format("%s DROP ON SERVER %s myrole", formatArgs));
+      AnalyzesOk(String.format("%s DROP ON SERVER server1 %s myrole", 
formatArgs));
+      AnalyzesOk(String.format("%s DROP ON DATABASE functional %s myrole", 
formatArgs));
+      AnalyzesOk(String.format(
+          "%s DROP ON TABLE functional.alltypes %s myrole", formatArgs));
+      AnalysisError(String.format(
+          "%s DROP ON URI 'hdfs:////abc/123' %s myrole", formatArgs),
+          "Only 'ALL' privilege may be applied at URI scope in privilege 
spec.");
     }
 
     AnalysisContext authDisabledCtx = createAuthDisabledAnalysisCtx();

http://git-wip-us.apache.org/repos/asf/impala/blob/c9f4fdc6/fe/src/test/java/org/apache/impala/analysis/AuthorizationTest.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/org/apache/impala/analysis/AuthorizationTest.java 
b/fe/src/test/java/org/apache/impala/analysis/AuthorizationTest.java
index 9085b78..a5173fb 100644
--- a/fe/src/test/java/org/apache/impala/analysis/AuthorizationTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/AuthorizationTest.java
@@ -40,6 +40,7 @@ import org.apache.impala.catalog.AuthorizationException;
 import org.apache.impala.catalog.Db;
 import org.apache.impala.catalog.ImpaladCatalog;
 import org.apache.impala.catalog.ScalarFunction;
+import org.apache.impala.catalog.ScalarType;
 import org.apache.impala.catalog.Type;
 import org.apache.impala.common.AnalysisException;
 import org.apache.impala.common.FrontendTestBase;
@@ -87,11 +88,11 @@ public class AuthorizationTest extends FrontendTestBase {
   //   ALL permission on 'tpch' database and 'newdb' database
   //   ALL permission on 'functional_seq_snap' database
   //   SELECT permissions on all tables in 'tpcds' database
-  //   SELECT, REFRESH permissions on 'functional.alltypesagg' (no INSERT 
permissions)
+  //   SELECT, REFRESH, DROP permissions on 'functional.alltypesagg'
   //   ALTER permissions on 'functional.alltypeserror'
-  //   SELECT permissions on 'functional.complex_view' (no INSERT permissions)
-  //   SELECT, REFRESH permissions on 'functional.view_view' (no INSERT 
permissions)
-  //   ALTER permission on 'functional.alltypes_view'
+  //   SELECT permissions on 'functional.complex_view'
+  //   SELECT, REFRESH permissions on 'functional.view_view'
+  //   ALTER, DROP permissions on 'functional.alltypes_view'
   //   SELECT permissions on columns ('id', 'int_col', and 'year') on
   //   'functional.alltypessmall' (no SELECT permissions on 
'functional.alltypessmall')
   //   SELECT permissions on columns ('id', 'int_struct_col', 
'struct_array_col',
@@ -105,7 +106,7 @@ public class AuthorizationTest extends FrontendTestBase {
   //   No permissions on database 'functional_rc'
   //   Only column level permissions in 'functional_avro':
   //     SELECT permissions on columns ('id') on 
'functional_avro.alltypessmall'
-  //   REFRESH, INSERT, CREATE, ALTER permissions on 'functional_text_lzo' 
database
+  //   REFRESH, INSERT, CREATE, ALTER, DROP permissions on 
'functional_text_lzo' database
   public final static String AUTHZ_POLICY_FILE = 
"/test-warehouse/authz-policy.ini";
   public final static User USER = new User(System.getProperty("user.name"));
 
@@ -267,6 +268,18 @@ public class AuthorizationTest extends FrontendTestBase {
     privilege.setTable_name("alltypesagg");
     sentryService.grantRolePrivilege(USER, roleName, privilege);
 
+    // drop_functional_alltypesagg
+    roleName = "drop_functional_alltypesagg";
+    sentryService.createRole(USER, roleName, true);
+    sentryService.grantRoleToGroup(USER, roleName, USER.getName());
+
+    privilege = new TPrivilege("", TPrivilegeLevel.DROP,
+        TPrivilegeScope.TABLE, false);
+    privilege.setServer_name("server1");
+    privilege.setDb_name("functional");
+    privilege.setTable_name("alltypesagg");
+    sentryService.grantRolePrivilege(USER, roleName, privilege);
+
     // refresh_functional_view_view
     roleName = "refresh_functional_view_view";
     sentryService.createRole(USER, roleName, true);
@@ -279,6 +292,18 @@ public class AuthorizationTest extends FrontendTestBase {
     privilege.setTable_name("view_view");
     sentryService.grantRolePrivilege(USER, roleName, privilege);
 
+    // drop_functional_alltypes_view
+    roleName = "drop_functional_alltypes_view";
+    sentryService.createRole(USER, roleName, true);
+    sentryService.grantRoleToGroup(USER, roleName, USER.getName());
+
+    privilege = new TPrivilege("", TPrivilegeLevel.DROP,
+        TPrivilegeScope.TABLE, false);
+    privilege.setServer_name("server1");
+    privilege.setDb_name("functional");
+    privilege.setTable_name("alltypes_view");
+    sentryService.grantRolePrivilege(USER, roleName, privilege);
+
     // insert_functional_text_lzo
     roleName = "insert_functional_text_lzo";
     sentryService.createRole(USER, roleName, true);
@@ -315,6 +340,18 @@ public class AuthorizationTest extends FrontendTestBase {
     privilege.setTable_name(AuthorizeableTable.ANY_TABLE_NAME);
     sentryService.grantRolePrivilege(USER, roleName, privilege);
 
+    // drop_functional_text_lzo
+    roleName = "drop_functional_text_lzo";
+    sentryService.createRole(USER, roleName, true);
+    sentryService.grantRoleToGroup(USER, roleName, USER.getName());
+
+    privilege = new TPrivilege("", TPrivilegeLevel.DROP, 
TPrivilegeScope.DATABASE,
+        false);
+    privilege.setServer_name("server1");
+    privilege.setDb_name("functional_text_lzo");
+    privilege.setTable_name(AuthorizeableTable.ANY_TABLE_NAME);
+    sentryService.grantRolePrivilege(USER, roleName, privilege);
+
     // alter_functional_alltypeserror
     roleName = "alter_functional_alltypeserror";
     sentryService.createRole(USER, roleName, true);
@@ -1244,6 +1281,15 @@ public class AuthorizationTest extends FrontendTestBase {
     AuthzOk("drop database if exists newdb");
     AuthzOk("drop database if exists newdb cascade");
     AuthzOk("drop database if exists newdb restrict");
+
+    // User has DROP privilege on functional_text_lzo database.
+    AuthzOk("drop database functional_text_lzo");
+    AuthzOk("drop database functional_text_lzo cascade");
+    AuthzOk("drop database functional_text_lzo restrict");
+    AuthzOk("drop database if exists functional_text_lzo");
+    AuthzOk("drop database if exists functional_text_lzo cascade");
+    AuthzOk("drop database if exists functional_text_lzo restrict");
+
     // User has permission, database does not exists, IF EXISTS not specified.
     try {
       AuthzOk("drop database newdb");
@@ -1294,6 +1340,9 @@ public class AuthorizationTest extends FrontendTestBase {
     AuthzOk("drop table tpch.lineitem");
     AuthzOk("drop table if exists tpch.lineitem");
 
+    // User has DROP privilege on functional.alltypesagg table.
+    AuthzOk("drop table functional.alltypesagg");
+
     // Drop table (user does not have permission).
     AuthzError("drop table functional.alltypes",
         "User '%s' does not have privileges to execute 'DROP' on: 
functional.alltypes");
@@ -1330,10 +1379,13 @@ public class AuthorizationTest extends FrontendTestBase 
{
     AuthzOk("drop view functional_seq_snap.alltypes_view");
     AuthzOk("drop view if exists functional_seq_snap.alltypes_view");
 
-    // Drop view (user does not have permission).
-    AuthzError("drop view functional.alltypes_view",
+    // User has DROP privilege on functional.alltypes_view view.
+    AuthzOk("drop view functional.alltypes_view");
+
+    // User does not have DROP privilege on functional.alltypes_view_sub view.
+    AuthzError("drop view functional.alltypes_view_sub",
         "User '%s' does not have privileges to execute 'DROP' on: 
functional.alltypes");
-    AuthzError("drop view if exists functional.alltypes_view",
+    AuthzError("drop view if exists functional.alltypes_view_sub",
         "User '%s' does not have privileges to execute 'DROP' on: 
functional.alltypes");
 
     // Drop view with unqualified table name.
@@ -2412,7 +2464,7 @@ public class AuthorizationTest extends FrontendTestBase {
 
     AuthzError(ctx, "create function f() returns int location " +
         "'/test-warehouse/libTestUdfs.so' symbol='NoArgs'",
-        "User '%s' does not have privileges to CREATE/DROP functions in: 
default.f()");
+        "User '%s' does not have privileges to CREATE functions in: 
default.f()");
 
     // User has ALL privilege on tpch database and ALL privilege on
     // /test-warehouse/libTestUdfs.so URI.
@@ -2421,19 +2473,31 @@ public class AuthorizationTest extends FrontendTestBase 
{
 
     AuthzError(ctx, "create function notdb.f() returns int location " +
         "'/test-warehouse/libTestUdfs.so' symbol='NoArgs'",
-        "User '%s' does not have privileges to CREATE/DROP functions in: 
notdb.f()");
+        "User '%s' does not have privileges to CREATE functions in: 
notdb.f()");
+
+    // User has DROP privilege on functional_text_lzo database.
+    try {
+      
ctx_.catalog.addFunction(ScalarFunction.createForTesting("functional_text_lzo",
+          "f", new ArrayList<Type>(), Type.INT, "/dummy", "dummy.class", null,
+          null, TFunctionBinaryType.NATIVE));
+      AuthzOk("drop function functional_text_lzo.f()");
+    } finally {
+      
ctx_.catalog.removeFunction(ScalarFunction.createForTesting("functional_text_lzo",
+          "f", new ArrayList<Type>(), Type.INT, "/dummy", "dummy.class", null,
+          null, TFunctionBinaryType.NATIVE));
+    }
 
     AuthzError(ctx, "drop function if exists f()",
-        "User '%s' does not have privileges to CREATE/DROP functions in: 
default.f()");
+        "User '%s' does not have privileges to DROP functions in: 
default.f()");
 
     AuthzError(ctx, "drop function notdb.f()",
-        "User '%s' does not have privileges to CREATE/DROP functions in: 
notdb.f()");
+        "User '%s' does not have privileges to DROP functions in: notdb.f()");
 
     // User does not have ALL privilege on SERVER and tries to create a 
function with
     // the same name as the built-in function.
     AuthzError(ctx, "create function sin(double) returns double location " +
         "'/test-warehouse/libTestUdfs.so' symbol='NoArgs'",
-        "User '%s' does not have privileges to CREATE/DROP functions in: " +
+        "User '%s' does not have privileges to CREATE functions in: " +
         "default.sin(DOUBLE)");
     // User tries to create a function in the system database.
     AuthzError(ctx, "create function _impala_builtins.sin(double) returns 
double " +
@@ -2446,7 +2510,7 @@ public class AuthorizationTest extends FrontendTestBase {
     AuthzError(ctx, "drop function _impala_builtins.sin(double)",
         "Cannot modify system database.");
     AuthzError(ctx, "drop function sin(double)",
-        "User '%s' does not have privileges to CREATE/DROP functions in: " +
+        "User '%s' does not have privileges to DROP functions in: " +
         "default.sin(DOUBLE)");
 
     // TODO: Add test support for dynamically changing privileges for
@@ -2737,6 +2801,42 @@ public class AuthorizationTest extends FrontendTestBase {
     }
   }
 
+  @Test
+  public void TestServerLevelDrop() throws ImpalaException {
+    // TODO: Add test support for dynamically changing privileges for
+    // file-based policy.
+    if (ctx_.authzConfig.isFileBasedPolicy()) return;
+
+    SentryPolicyService sentryService =
+        new SentryPolicyService(ctx_.authzConfig.getSentryConfig());
+
+    // User has DROP privilege on server.
+    String roleName = "drop_role";
+    try {
+      sentryService.createRole(USER, roleName, true);
+      TPrivilege privilege = new TPrivilege("", TPrivilegeLevel.DROP,
+          TPrivilegeScope.SERVER, false);
+      privilege.setServer_name("server1");
+      sentryService.grantRolePrivilege(USER, roleName, privilege);
+      sentryService.grantRoleToGroup(USER, roleName, USER.getName());
+      ctx_.catalog.reset();
+
+      AuthzOk("drop database functional");
+      AuthzOk("drop table functional.alltypes");
+      AuthzOk("drop view functional.alltypes_view_sub");
+      ctx_.catalog.addFunction(ScalarFunction.createForTesting("functional",
+          "f", new ArrayList<Type>(), Type.INT, "/dummy", "dummy.class", null,
+          null, TFunctionBinaryType.NATIVE));
+      AuthzOk("drop function functional.f()");
+    } finally {
+      sentryService.dropRole(USER, roleName, true);
+      ctx_.catalog.reset();
+      ctx_.catalog.addFunction(ScalarFunction.createForTesting("functional",
+          "f", new ArrayList<Type>(), Type.INT, "/dummy", "dummy.class", null,
+          null, TFunctionBinaryType.NATIVE));
+    }
+  }
+
   private void TestWithIncorrectConfig(AuthorizationConfig authzConfig, User 
user)
       throws ImpalaException {
     Frontend fe = new Frontend(authzConfig, ctx_.catalog);

http://git-wip-us.apache.org/repos/asf/impala/blob/c9f4fdc6/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
----------------------------------------------------------------------
diff --git a/fe/src/test/java/org/apache/impala/analysis/ParserTest.java 
b/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
index 3eab55e..ab0eb78 100644
--- a/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/ParserTest.java
@@ -3592,6 +3592,12 @@ public class ParserTest extends FrontendTestBase {
       ParsesOk(String.format("%s ALTER ON DATABASE foo %s myRole", formatStr));
       ParsesOk(String.format("%s ALTER ON TABLE foo %s myRole", formatStr));
 
+      // DROP privilege.
+      ParsesOk(String.format("%s DROP ON SERVER %s myRole", formatStr));
+      ParsesOk(String.format("%s DROP ON SERVER foo %s myRole", formatStr));
+      ParsesOk(String.format("%s DROP ON DATABASE foo %s myRole", formatStr));
+      ParsesOk(String.format("%s DROP ON TABLE foo %s myRole", formatStr));
+
       // Server scope does not accept a name.
       ParsesOk(String.format("%s ALL ON SERVER %s myRole", formatStr));
       ParsesOk(String.format("%s INSERT ON SERVER %s myRole", formatStr));

http://git-wip-us.apache.org/repos/asf/impala/blob/c9f4fdc6/fe/src/test/resources/authz-policy.ini.template
----------------------------------------------------------------------
diff --git a/fe/src/test/resources/authz-policy.ini.template 
b/fe/src/test/resources/authz-policy.ini.template
index 82b1060..26ed70b 100644
--- a/fe/src/test/resources/authz-policy.ini.template
+++ b/fe/src/test/resources/authz-policy.ini.template
@@ -29,7 +29,8 @@ ${USER} = all_tpch, all_newdb, all_functional_seq_snap, 
select_tpcds,\
           refresh_functional_view_view, insert_functional_text_lzo,\
           create_functional_text_lzo, alter_functional_text_lzo,\
           alter_functional_alltypeserror, alter_functional_alltypes_view,\
-          libtestudfs_uri
+          libtestudfs_uri, drop_functional_text_lzo, 
drop_functional_alltypesagg,\
+          drop_functional_alltypes_view
 auth_to_local_group = test_role
 server_admin = all_server
 
@@ -55,15 +56,20 @@ insert_parquet = 
server=server1->db=functional_parquet->table=*->action=insert
 refresh_functional_text_lzo = 
server=server1->db=functional_text_lzo->action=refresh
 refresh_functional_alltypesagg =\
     server=server1->db=functional->table=alltypesagg->action=refresh
+drop_functional_alltypesagg =\
+    server=server1->db=functional->table=alltypesagg->action=drop
 alter_functional_alltypeserror =\
     server=server1->db=functional->table=alltypeserror->action=alter
 refresh_functional_view_view =\
     server=server1->db=functional->table=view_view->action=refresh
+drop_functional_alltypes_view =\
+    server=server1->db=functional->table=alltypes_view->action=drop
 alter_functional_alltypes_view =\
     server=server1->db=functional->table=alltypes_view->action=alter
 insert_functional_text_lzo = 
server=server1->db=functional_text_lzo->action=insert
 create_functional_text_lzo = 
server=server1->db=functional_text_lzo->action=create
 alter_functionl_text_lzo = server=server1->db=functional_text_lzo->action=alter
+drop_functional_text_lzo = server=server1->db=functional_text_lzo->action=drop
 select_column_level_functional =\
     
server=server1->db=functional->table=alltypessmall->column=id->action=select,\
     
server=server1->db=functional->table=alltypessmall->column=int_col->action=select,\

Reply via email to