You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by co...@apache.org on 2015/01/21 08:56:23 UTC

incubator-sentry git commit: SENTRY-494: UNLOCK TABLE is not allowed (Reviewed by:Prasad Mujumdar)

Repository: incubator-sentry
Updated Branches:
  refs/heads/master 56802bba0 -> 382a93318


SENTRY-494: UNLOCK TABLE is not allowed (Reviewed by:Prasad Mujumdar)


Project: http://git-wip-us.apache.org/repos/asf/incubator-sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-sentry/commit/382a9331
Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/382a9331
Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/382a9331

Branch: refs/heads/master
Commit: 382a93318fa78ceb0d43c0991af467710e8fe68b
Parents: 56802bb
Author: Ma Junjie <ju...@intel.com>
Authored: Wed Jan 21 15:38:22 2015 +0800
Committer: Ma Junjie <ju...@intel.com>
Committed: Wed Jan 21 15:38:22 2015 +0800

----------------------------------------------------------------------
 .../binding/hive/HiveAuthzBindingHook.java      |   3 +-
 .../hive/authz/HiveAuthzPrivilegesMap.java      |  16 +-
 .../AbstractTestWithStaticConfiguration.java    |  12 +-
 .../tests/e2e/hive/TestLockPrivileges.java      | 214 +++++++++++++++++++
 4 files changed, 237 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/382a9331/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/HiveAuthzBindingHook.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/HiveAuthzBindingHook.java b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/HiveAuthzBindingHook.java
index 862c6a5..e311398 100644
--- a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/HiveAuthzBindingHook.java
+++ b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/HiveAuthzBindingHook.java
@@ -162,6 +162,8 @@ public class HiveAuthzBindingHook extends AbstractSemanticAnalyzerHook {
       case HiveParser.TOK_ALTERVIEW_RENAME:
       case HiveParser.TOK_CREATEINDEX:
       case HiveParser.TOK_DROPINDEX:
+      case HiveParser.TOK_LOCKTABLE:
+      case HiveParser.TOK_UNLOCKTABLE:
         currTab = extractTable((ASTNode)ast.getFirstChildWithType(HiveParser.TOK_TABNAME));
         currDB = extractDatabase((ASTNode) ast.getChild(0));
         break;
@@ -430,7 +432,6 @@ public class HiveAuthzBindingHook extends AbstractSemanticAnalyzerHook {
       }
 
       getInputHierarchyFromInputs(inputHierarchy, inputs);
-
       for (WriteEntity writeEntity: outputs) {
         if (filterWriteEntity(writeEntity)) {
           continue;

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/382a9331/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzPrivilegesMap.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzPrivilegesMap.java b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzPrivilegesMap.java
index 11c1a0f..99f1eb0 100644
--- a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzPrivilegesMap.java
+++ b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/HiveAuthzPrivilegesMap.java
@@ -21,7 +21,6 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.hadoop.hive.ql.plan.HiveOperation;
-import org.apache.sentry.binding.hive.authz.HiveAuthzPrivileges.HiveExtendedOperation;
 import org.apache.sentry.binding.hive.authz.HiveAuthzPrivileges.HiveOperationScope;
 import org.apache.sentry.binding.hive.authz.HiveAuthzPrivileges.HiveOperationType;
 import org.apache.sentry.core.model.db.DBModelAction;
@@ -161,12 +160,17 @@ public class HiveAuthzPrivilegesMap {
       setOperationType(HiveOperationType.INFO).
       build();
 
-    HiveAuthzPrivileges tableDMLPrivilege = new HiveAuthzPrivileges.AuthzPrivilegeBuilder().
-        addOutputObjectPriviledge(AuthorizableType.Table, EnumSet.of(DBModelAction.INSERT)).
+    HiveAuthzPrivileges tableLockPrivilege = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
+        .addInputObjectPriviledge(AuthorizableType.Table, EnumSet.of(DBModelAction.LOCK)).
         setOperationScope(HiveOperationScope.TABLE).
         setOperationType(HiveOperationType.DML).
         build();
 
+    HiveAuthzPrivileges dbLockPrivilege = new HiveAuthzPrivileges.AuthzPrivilegeBuilder()
+        .addInputObjectPriviledge(AuthorizableType.Db, EnumSet.of(DBModelAction.LOCK))
+        .setOperationScope(HiveOperationScope.DATABASE).setOperationType(HiveOperationType.DML)
+        .build();
+
     HiveAuthzPrivileges functionPrivilege = new HiveAuthzPrivileges.AuthzPrivilegeBuilder().
         addInputObjectPriviledge(AuthorizableType.URI, EnumSet.of(DBModelAction.ALL)).
         addOutputObjectPriviledge(AuthorizableType.URI, EnumSet.of(DBModelAction.ALL)).
@@ -257,8 +261,10 @@ public class HiveAuthzPrivilegesMap {
     hiveAuthzStmtPrivMap.put(HiveOperation.EXPORT, tableExportPrivilege);
     hiveAuthzStmtPrivMap.put(HiveOperation.IMPORT, dbImportPrivilege);
     hiveAuthzStmtPrivMap.put(HiveOperation.LOAD, tableLoadPrivilege);
-    hiveAuthzStmtPrivMap.put(HiveOperation.LOCKTABLE, tableDMLPrivilege);//TODO: Needs test case
-    hiveAuthzStmtPrivMap.put(HiveOperation.UNLOCKTABLE, tableDMLPrivilege);//TODO: Needs test case
+    hiveAuthzStmtPrivMap.put(HiveOperation.LOCKTABLE, tableLockPrivilege);
+    hiveAuthzStmtPrivMap.put(HiveOperation.UNLOCKTABLE, tableLockPrivilege);
+    hiveAuthzStmtPrivMap.put(HiveOperation.LOCKDB, dbLockPrivilege);
+    hiveAuthzStmtPrivMap.put(HiveOperation.UNLOCKDB, dbLockPrivilege);
     // CREATEROLE
     // DROPROLE
     // GRANT_PRIVILEGE

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/382a9331/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
index f8cc1d0..689f5a6 100644
--- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/AbstractTestWithStaticConfiguration.java
@@ -19,6 +19,7 @@ package org.apache.sentry.tests.e2e.hive;
 import static org.apache.sentry.provider.common.ProviderConstants.AUTHORIZABLE_SPLITTER;
 import static org.apache.sentry.provider.common.ProviderConstants.PRIVILEGE_PREFIX;
 import static org.apache.sentry.provider.common.ProviderConstants.ROLE_SPLITTER;
+import static org.junit.Assert.assertTrue;
 
 import java.io.File;
 import java.io.IOException;
@@ -60,7 +61,6 @@ import org.apache.sentry.tests.e2e.hive.hiveserver.HiveServerFactory;
 import org.apache.tools.ant.util.StringUtils;
 import org.junit.After;
 import org.junit.AfterClass;
-import static org.junit.Assert.assertTrue;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.slf4j.Logger;
@@ -113,7 +113,7 @@ public abstract class AbstractTestWithStaticConfiguration {
   protected static boolean useSentryService = false;
   protected static boolean setMetastoreListener = false;
   protected static String testServerType = null;
-
+  protected static boolean enableHiveConcurrency = false;
 
   protected static File baseDir;
   protected static File logDir;
@@ -224,6 +224,14 @@ public abstract class AbstractTestWithStaticConfiguration {
       setupSentryService();
     }
 
+    if (enableHiveConcurrency) {
+      properties.put(HiveConf.ConfVars.HIVE_SUPPORT_CONCURRENCY.varname, "true");
+      properties.put(HiveConf.ConfVars.HIVE_TXN_MANAGER.varname,
+          "org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager");
+      properties.put(HiveConf.ConfVars.HIVE_LOCK_MANAGER.varname,
+          "org.apache.hadoop.hive.ql.lockmgr.EmbeddedLockManager");
+    }
+
     hiveServer = create(properties, baseDir, confDir, logDir, policyURI, fileSystem);
     hiveServer.start();
     createContext();

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/382a9331/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestLockPrivileges.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestLockPrivileges.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestLockPrivileges.java
new file mode 100644
index 0000000..0e403d8
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestLockPrivileges.java
@@ -0,0 +1,214 @@
+/**
+ * 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.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestLockPrivileges extends AbstractTestWithStaticConfiguration {
+  private PolicyFile policyFile;
+  final String tableName = "tb1";
+
+  static Map<String, String> privileges = new HashMap<String, String>();
+  static {
+    privileges.put("all_db1_tb1", "server=server1->db=" + DB1 + "->table=tb1->action=all");
+    privileges.put("select_db1_tb1", "server=server1->db=" + DB1 + "->table=tb1->action=select");
+    privileges.put("insert_db1_tb1", "server=server1->db=" + DB1 + "->table=tb1->action=insert");
+    privileges.put("alter_db1_tb1", "server=server1->db=" + DB1 + "->table=tb1->action=alter");
+    privileges.put("lock_db1_tb1", "server=server1->db=" + DB1 + "->table=tb1->action=lock");
+
+    privileges.put("all_db1", "server=server1->db=" + DB1 + "->action=all");
+    privileges.put("select_db1", "server=server1->db=" + DB1 + "->action=select");
+    privileges.put("insert_db1", "server=server1->db=" + DB1 + "->action=insert");
+    privileges.put("alter_db1", "server=server1->db=" + DB1 + "->action=alter");
+    privileges.put("lock_db1", "server=server1->db=" + DB1 + "->action=lock");
+  }
+
+  @BeforeClass
+  public static void setHiveConcurrency() throws Exception {
+    enableHiveConcurrency = true;
+    setupTestStaticConfiguration();
+  }
+
+  private void adminCreate(String db, String table) throws Exception {
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE IF EXISTS " + db + " CASCADE");
+    statement.execute("CREATE DATABASE " + db);
+    if (table != null) {
+      statement.execute("CREATE table " + db + "." + table + " (a string)");
+    }
+    statement.close();
+    connection.close();
+  }
+
+  @Before
+  public void setup() throws Exception {
+    policyFile = PolicyFile.setAdminOnServer1(ADMINGROUP).setUserGroupMapping(
+        StaticUserGroup.getStaticMapping());
+    writePolicyFile(policyFile);
+  }
+
+  @Test
+  public void testLockDatabase() throws Exception {
+    String partialErrorMsgForNoPrivilege = "No valid privileges";
+    String assertErrorException = "The exception is not the same as the expectation.";
+    String assertExceptionThrown = "SQLException will be thrown.";
+
+    adminCreate(DB1, null);
+    policyFile.addPermissionsToRole("lock_db1", privileges.get("lock_db1"))
+        .addRolesToGroup(USERGROUP1, "lock_db1")
+        .addPermissionsToRole("insert_db1", privileges.get("insert_db1"))
+        .addRolesToGroup(USERGROUP2, "insert_db1")
+        .addPermissionsToRole("select_db1", privileges.get("select_db1"))
+        .addRolesToGroup(USERGROUP2, "select_db1")
+        .addPermissionsToRole("alter_db1", privileges.get("alter_db1"))
+        .addRolesToGroup(USERGROUP2, "alter_db1")
+        .addPermissionsToRole("all_db1", privileges.get("all_db1"))
+        .addRolesToGroup(USERGROUP3, "all_db1");
+    writePolicyFile(policyFile);
+
+    // user1 has lock privilege only
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("LOCK DATABASE db_1 SHARED");
+    try {
+      statement.execute("UNLOCK DATABASE db_1");
+      fail(assertExceptionThrown);
+    } catch (SQLException se) {
+      // Authorization is successful.
+      assertTrue(assertErrorException, se.getMessage().indexOf(partialErrorMsgForNoPrivilege) == -1);
+    }
+
+    // user2 has privileges with insert, select, alter, but has no lock privilege
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    try {
+      statement.execute("LOCK DATABASE db_1 SHARED");
+      fail(assertExceptionThrown);
+    } catch (SQLException se) {
+      // Authorization is failed, the error message include "No valid privileges"
+      assertTrue(assertErrorException, se.getMessage().indexOf(partialErrorMsgForNoPrivilege) > 0);
+    }
+    try {
+      statement.execute("UNLOCK DATABASE db_1");
+      fail(assertExceptionThrown);
+    } catch (SQLException se) {
+      // Authorization is failed, the error message include "No valid privileges"
+      assertTrue(assertErrorException, se.getMessage().indexOf(partialErrorMsgForNoPrivilege) > 0);
+    }
+
+    // user3 has All privilege
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("LOCK DATABASE db_1 SHARED");
+    try {
+      statement.execute("UNLOCK DATABASE db_1");
+      fail(assertExceptionThrown);
+    } catch (SQLException se) {
+      // Authorization is successful.
+      assertTrue(assertErrorException, se.getMessage().indexOf(partialErrorMsgForNoPrivilege) == -1);
+    }
+    statement.close();
+    connection.close();
+  }
+
+  @Test
+  public void testLockTable() throws Exception {
+    String partialErrorMsgForNoPrivilege = "No valid privileges";
+    String assertErrorException = "The exception is not the same as the expectation.";
+    String assertExceptionThrown = "SQLException will be thrown.";
+
+    adminCreate(DB1, tableName);
+    policyFile.addPermissionsToRole("lock_db1_tb1", privileges.get("lock_db1_tb1"))
+        .addRolesToGroup(USERGROUP1, "lock_db1_tb1")
+        .addPermissionsToRole("insert_db1_tb1", privileges.get("insert_db1_tb1"))
+        .addRolesToGroup(USERGROUP2, "insert_db1_tb1")
+        .addPermissionsToRole("select_db1_tb1", privileges.get("select_db1_tb1"))
+        .addRolesToGroup(USERGROUP2, "select_db1_tb1")
+        .addPermissionsToRole("alter_db1_tb1", privileges.get("alter_db1_tb1"))
+        .addRolesToGroup(USERGROUP2, "alter_db1_tb1")
+        .addPermissionsToRole("all_db1_tb1", privileges.get("all_db1_tb1"))
+        .addRolesToGroup(USERGROUP3, "all_db1_tb1");
+    writePolicyFile(policyFile);
+
+    // user1 has lock privilege only
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("LOCK TABLE tb1 SHARED");
+    try {
+      statement.execute("UNLOCK TABLE tb1");
+      fail(assertExceptionThrown);
+    } catch (SQLException se) {
+      // Authorization is successful.
+      assertTrue(assertErrorException, se.getMessage().indexOf(partialErrorMsgForNoPrivilege) == -1);
+    }
+
+    // user2 has privileges with insert, select, alter, but has no lock privilege
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    try {
+      statement.execute("LOCK TABLE tb1 SHARED");
+      fail(assertExceptionThrown);
+    } catch (SQLException se) {
+      // Authorization is failed, the error message include "No valid privileges"
+      assertTrue(assertErrorException,
+          se.getMessage().indexOf(partialErrorMsgForNoPrivilege) > 0);
+    }
+    try {
+      statement.execute("UNLOCK TABLE tb1");
+      fail(assertExceptionThrown);
+    } catch (SQLException se) {
+      // Authorization is failed, the error message include "No valid privileges"
+      assertTrue(assertErrorException,
+          se.getMessage().indexOf(partialErrorMsgForNoPrivilege) > 0);
+    }
+
+    // user3 has All privilege
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("LOCK TABLE tb1 SHARED");
+    try {
+      statement.execute("UNLOCK TABLE tb1");
+      fail(assertExceptionThrown);
+    } catch (SQLException se) {
+      // Authorization is successful.
+      assertTrue(assertErrorException, se.getMessage().indexOf(partialErrorMsgForNoPrivilege) == -1);
+    }
+    statement.close();
+    connection.close();
+  }
+}