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();
+ }
+}