You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by sd...@apache.org on 2015/11/05 02:44:37 UTC
[09/25] incubator-sentry git commit: SENTRY-881: Allow some metadata
operations with column-level privileges ( Lenni Kuff,
Reviewed by: Sravya Tirukkovalur)
SENTRY-881: Allow some metadata operations with column-level privileges ( Lenni Kuff, Reviewed by: Sravya Tirukkovalur)
Project: http://git-wip-us.apache.org/repos/asf/incubator-sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-sentry/commit/b8868509
Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/b8868509
Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/b8868509
Branch: refs/heads/hive_plugin_v2
Commit: b8868509bef1102eaaefefdbbdf602fa28601983
Parents: 788cf74
Author: Sravya Tirukkovalur <sr...@cloudera.com>
Authored: Mon Sep 14 17:15:56 2015 -0700
Committer: Sun Dapeng <sd...@apache.org>
Committed: Mon Nov 2 16:36:17 2015 +0800
----------------------------------------------------------------------
.../binding/hive/HiveAuthzBindingHook.java | 28 +++++++-
.../hive/authz/HiveAuthzPrivilegesMap.java | 5 +-
.../e2e/dbprovider/TestColumnEndToEnd.java | 68 +++++++++++++++++++-
.../e2e/hive/TestMetadataObjectRetrieval.java | 26 +++++++-
4 files changed, 118 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/b8868509/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 fd801a4..18b8a8f 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
@@ -70,6 +70,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
@@ -85,6 +86,13 @@ public class HiveAuthzBindingHook extends AbstractSemanticAnalyzerHook {
private Table currOutTab = null;
private Database currOutDB = null;
+ // True if this is a basic DESCRIBE <table> operation. False for other DESCRIBE variants
+ // like DESCRIBE [FORMATTED|EXTENDED]. Required because Hive treats these stmts as the same
+ // HiveOperationType, but we want to enforces different privileges on each statement.
+ // Basic DESCRIBE <table> is allowed with only column-level privs, while the variants
+ // require table-level privileges.
+ public boolean isDescTableBasic = false;
+
public HiveAuthzBindingHook() throws Exception {
SessionState session = SessionState.get();
if(session == null) {
@@ -247,6 +255,12 @@ public class HiveAuthzBindingHook extends AbstractSemanticAnalyzerHook {
String dbName = BaseSemanticAnalyzer.unescapeIdentifier(ast.getChild(1).getChild(0).getChild(0).getText());
currDB = new Database(dbName);
break;
+ case HiveParser.TOK_DESCTABLE:
+ currDB = getCanonicalDb();
+ // For DESCRIBE FORMATTED/EXTENDED ast will have an additional child node with value
+ // "FORMATTED/EXTENDED".
+ isDescTableBasic = (ast.getChildCount() == 1);
+ break;
default:
currDB = getCanonicalDb();
break;
@@ -434,6 +448,14 @@ public class HiveAuthzBindingHook extends AbstractSemanticAnalyzerHook {
LOG.debug("context.getOutputs() = " + context.getOutputs());
}
+ // Workaround to allow DESCRIBE <table> to be executed with only column-level privileges, while
+ // still authorizing DESCRIBE [EXTENDED|FORMATTED] as table-level.
+ // This is done by treating DESCRIBE <table> the same as SHOW COLUMNS, which only requires column
+ // level privs.
+ if (isDescTableBasic) {
+ stmtAuthObject = HiveAuthzPrivilegesMap.getHiveAuthzPrivileges(HiveOperation.SHOWCOLUMNS);
+ }
+
switch (stmtAuthObject.getOperationScope()) {
case SERVER :
@@ -478,6 +500,8 @@ public class HiveAuthzBindingHook extends AbstractSemanticAnalyzerHook {
inputHierarchy.add(externalAuthorizableHierarchy);
}
+
+
// workaround for DDL statements
// Capture the table name in pre-analyze and include that in the output entity list
if (currOutTab != null) {
@@ -735,7 +759,7 @@ public class HiveAuthzBindingHook extends AbstractSemanticAnalyzerHook {
throws SemanticException {
List<FieldSchema> filteredResult = new ArrayList<FieldSchema>();
Subject subject = new Subject(userName);
- HiveAuthzPrivileges ColumnMetaDataPrivilege =
+ HiveAuthzPrivileges columnMetaDataPrivilege =
HiveAuthzPrivilegesMap.getHiveAuthzPrivileges(HiveOperation.SHOWCOLUMNS);
Database database = new Database(dbName);
@@ -752,7 +776,7 @@ public class HiveAuthzBindingHook extends AbstractSemanticAnalyzerHook {
inputHierarchy.add(externalAuthorizableHierarchy);
try {
- hiveAuthzBinding.authorize(operation, ColumnMetaDataPrivilege, subject,
+ hiveAuthzBinding.authorize(operation, columnMetaDataPrivilege, subject,
inputHierarchy, outputHierarchy);
filteredResult.add(col);
} catch (AuthorizationException e) {
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/b8868509/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 e721555..d35b09d 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
@@ -140,7 +140,8 @@ public class HiveAuthzPrivilegesMap {
setOperationType(HiveOperationType.INFO).
build();
- HiveAuthzPrivileges ColumnMetaDataPrivilege = new HiveAuthzPrivileges.AuthzPrivilegeBuilder().
+ // Metadata statements which only require column-level privileges.
+ HiveAuthzPrivileges columnMetaDataPrivilege = new HiveAuthzPrivileges.AuthzPrivilegeBuilder().
addInputObjectPriviledge(AuthorizableType.Column, EnumSet.of(DBModelAction.SELECT, DBModelAction.INSERT)).
setOperationScope(HiveOperationScope.COLUMN).
setOperationType(HiveOperationType.INFO).
@@ -262,7 +263,7 @@ public class HiveAuthzPrivilegesMap {
hiveAuthzStmtPrivMap.put(HiveOperation.DROPFUNCTION, functionPrivilege);
// SHOWCOLUMNS
- hiveAuthzStmtPrivMap.put(HiveOperation.SHOWCOLUMNS, ColumnMetaDataPrivilege);
+ hiveAuthzStmtPrivMap.put(HiveOperation.SHOWCOLUMNS, columnMetaDataPrivilege);
// SHOWDATABASES
// SHOWTABLES
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/b8868509/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestColumnEndToEnd.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestColumnEndToEnd.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestColumnEndToEnd.java
index 718a736..343048d 100644
--- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestColumnEndToEnd.java
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestColumnEndToEnd.java
@@ -17,8 +17,7 @@
package org.apache.sentry.tests.e2e.dbprovider;
-import static junit.framework.Assert.fail;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import java.io.File;
import java.io.FileOutputStream;
@@ -32,12 +31,12 @@ import java.util.List;
import org.apache.sentry.provider.db.SentryAccessDeniedException;
import org.apache.sentry.provider.file.PolicyFile;
import org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.google.common.io.Resources;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -91,6 +90,68 @@ public class TestColumnEndToEnd extends AbstractTestWithStaticConfiguration {
}
@Test
+ public void testDescribeTbl() throws Exception {
+ Connection connection = context.createConnection(ADMIN1);
+ Statement statement = context.createStatement(connection);
+ statement.execute("CREATE TABLE IF NOT EXISTS t1 (c1 string, c2 string)");
+ statement.execute("CREATE TABLE t2 (c1 string, c2 string)");
+ statement.execute("CREATE ROLE user_role1");
+ statement.execute("GRANT SELECT (c1) ON TABLE t1 TO ROLE user_role1");
+ statement.execute("GRANT ROLE user_role1 TO GROUP " + USERGROUP1);
+ statement.close();
+ connection.close();
+
+ connection = context.createConnection(USER1_1);
+ statement = context.createStatement(connection);
+
+ // Expect that DESCRIBE table works with only column-level privileges, but other
+ // DESCRIBE variants like DESCRIBE FORMATTED fail. Note that if a user has privileges
+ // on any column they can describe all columns.
+ ResultSet rs = statement.executeQuery("DESCRIBE t1");
+ assertTrue(rs.next());
+ assertEquals("c1", rs.getString(1));
+ assertEquals("string", rs.getString(2));
+ assertTrue(rs.next());
+ assertEquals("c2", rs.getString(1));
+ assertEquals("string", rs.getString(2));
+
+ statement.executeQuery("DESCRIBE t1 c1");
+ statement.executeQuery("DESCRIBE t1 c2");
+
+ try {
+ statement.executeQuery("DESCRIBE t2");
+ fail("Expected DESCRIBE to fail on t2");
+ } catch (SQLException e) {
+ context.verifyAuthzException(e);
+ }
+
+ try {
+ statement.executeQuery("DESCRIBE FORMATTED t1");
+ fail("Expected DESCRIBE FORMATTED to fail");
+ } catch (SQLException e) {
+ context.verifyAuthzException(e);
+ }
+
+ try {
+ statement.executeQuery("DESCRIBE EXTENDED t1");
+ fail("Expected DESCRIBE EXTENDED to fail");
+ } catch (SQLException e) {
+ context.verifyAuthzException(e);
+ }
+ statement.close();
+ connection.close();
+
+ // Cleanup
+ connection = context.createConnection(ADMIN1);
+ statement = context.createStatement(connection);
+ statement.execute("DROP TABLE t1");
+ statement.execute("DROP TABLE t2");
+ statement.execute("DROP ROLE user_role1");
+ statement.close();
+ connection.close();
+ }
+
+ @Test
public void testNegative() throws Exception {
Connection connection = context.createConnection(ADMIN1);
Statement statement = context.createStatement(connection);
@@ -205,6 +266,7 @@ public class TestColumnEndToEnd extends AbstractTestWithStaticConfiguration {
statement = context.createStatement(connection);
statement.execute("use " + DB1);
statement.execute("SELECT c1 FROM t1");
+ statement.execute("DESCRIBE t1");
// 2.1 user_role2 select c1,c2 on t1
connection = context.createConnection(USER2_1);
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/b8868509/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java
index 71e3af2..1415647 100644
--- a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java
@@ -66,7 +66,7 @@ public class TestMetadataObjectRetrieval extends AbstractTestWithStaticConfigura
* show create table table
* show tblproperties table
*
- * The table is assumed to have two colums under_col int and value string.
+ * The table is assumed to have two columns under_col int and value string.
*/
private void positiveDescribeShowTests(String user, String db, String table) throws Exception {
Connection connection = context.createConnection(user);
@@ -91,6 +91,27 @@ public class TestMetadataObjectRetrieval extends AbstractTestWithStaticConfigura
assertTrue("describe table fail", rs.getString(1).trim().equals("value"));
assertTrue("describe table fail", rs.getString(2).trim().equals("string"));
+ rs = statement.executeQuery("DESCRIBE EXTENDED " + table);
+ assertTrue(rs.next());
+ assertTrue(rs.getString(1), rs.getString(1).contains("under_col"));
+ assertTrue(rs.getString(2), rs.getString(2).contains("int"));
+ assertTrue(rs.next());
+ assertTrue(rs.getString(1), rs.getString(1).contains("value"));
+ assertTrue(rs.getString(2), rs.getString(2).contains("string"));
+ assertTrue(rs.next());
+
+ rs = statement.executeQuery("DESCRIBE FORMATTED " + table);
+ // Skip the header
+ assertTrue(rs.next());
+ assertTrue(rs.next());
+ assertTrue(rs.next());
+ assertTrue(rs.getString(1), rs.getString(1).contains("under_col"));
+ assertTrue(rs.getString(2), rs.getString(2).contains("int"));
+ assertTrue(rs.next());
+ assertTrue(rs.getString(1), rs.getString(1).contains("value"));
+ assertTrue(rs.getString(2), rs.getString(2).contains("string"));
+ assertTrue(rs.next());
+
rs = statement.executeQuery("SHOW COLUMNS FROM " + table);
assertTrue(rs.next());
assertTrue("show columns from fail", rs.getString(1).trim().equals("under_col"));
@@ -120,9 +141,10 @@ public class TestMetadataObjectRetrieval extends AbstractTestWithStaticConfigura
Connection connection = context.createConnection(user);
Statement statement = context.createStatement(connection);
statement.execute("USE " + db);
- context.assertAuthzException(statement, "DESCRIBE " + table);
context.assertAuthzException(statement, "DESCRIBE " + table + " under_col");
context.assertAuthzException(statement, "DESCRIBE " + table + " value");
+ context.assertAuthzException(statement, "DESCRIBE FORMATTED " + table);
+ context.assertAuthzException(statement, "DESCRIBE EXTENDED " + table);
context.assertAuthzException(statement, "SHOW COLUMNS FROM " + table);
context.assertAuthzException(statement, "SHOW CREATE TABLE " + table);
context.assertAuthzException(statement, "SHOW TBLPROPERTIES " + table);