Repository: incubator-sentry
Updated Branches:
  refs/heads/master 0b5ff1054 -> 3d6d69e09


SENTRY-742: Add describe, show/compute stats tests for column level privileges 
( Anne yu, 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/3d6d69e0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/3d6d69e0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/3d6d69e0

Branch: refs/heads/master
Commit: 3d6d69e09435ccef39e5868318cff08aa3bf22a7
Parents: 0b5ff10
Author: Sravya Tirukkovalur <sra...@cloudera.com>
Authored: Fri Nov 6 10:27:28 2015 -0800
Committer: Sravya Tirukkovalur <sra...@cloudera.com>
Committed: Fri Nov 6 10:27:28 2015 -0800

----------------------------------------------------------------------
 .../TestDbColumnLevelMetaDataOps.java           | 317 +++++++++++++++++++
 1 file changed, 317 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/3d6d69e0/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbColumnLevelMetaDataOps.java
----------------------------------------------------------------------
diff --git 
a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbColumnLevelMetaDataOps.java
 
b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbColumnLevelMetaDataOps.java
new file mode 100644
index 0000000..fba883c
--- /dev/null
+++ 
b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestDbColumnLevelMetaDataOps.java
@@ -0,0 +1,317 @@
+/*
+ * 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.dbprovider;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import org.apache.hive.service.cli.HiveSQLException;
+import org.apache.hadoop.hive.ql.parse.SemanticException;
+import org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration;
+import org.apache.sentry.tests.e2e.hive.PrivilegeResultSet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Contains tests for meta data operations with column level privileges
+ */
+public class TestDbColumnLevelMetaDataOps extends 
AbstractTestWithStaticConfiguration {
+  private static final Logger LOGGER = LoggerFactory.
+          getLogger(TestDbColumnLevelMetaDataOps.class);
+
+  private static final String TEST_COL_METADATA_OPS_DB = 
"test_col_metadata_ops_db";
+  private static final String TEST_COL_METADATA_OPS_TB = 
"test_col_metadata_ops_tb";
+  private static final String TEST_COL_METADATA_OPS_ROLE = 
"test_col_metadata_ops_role";
+
+  @BeforeClass
+  public static void setupTestStaticConfiguration() throws Exception{
+    LOGGER.info("TestColumnEndToEnd setupTestStaticConfiguration");
+    useSentryService = true;
+    AbstractTestWithStaticConfiguration.setupTestStaticConfiguration();
+  }
+
+  @Override
+  @Before
+  public void setup() throws Exception {
+    super.setupAdmin();
+    super.setup();
+    createTestData();
+  }
+
+  /**
+   * Create test database, table and role
+   * and grant column level privilege
+   * @throws Exception
+   */
+  private void createTestData() throws Exception {
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("CREATE DATABASE " + TEST_COL_METADATA_OPS_DB);
+    statement.execute("USE " + TEST_COL_METADATA_OPS_DB);
+    statement.execute("CREATE TABLE " + TEST_COL_METADATA_OPS_TB
+            + " (privileged STRING, unprivileged INT) partitioned by 
(privileged_par STRING, unprivileged_par INT)");
+    statement.execute("INSERT INTO TABLE " + TEST_COL_METADATA_OPS_TB
+            + " PARTITION(privileged_par = 'privileged_par', unprivileged_par 
= 1) VALUES ('test1', 1)");
+    statement.execute("CREATE ROLE " + TEST_COL_METADATA_OPS_ROLE);
+    statement.execute("GRANT SELECT(privileged) ON TABLE " + 
TEST_COL_METADATA_OPS_TB + " TO ROLE " + TEST_COL_METADATA_OPS_ROLE);
+    statement.execute("GRANT ROLE " + TEST_COL_METADATA_OPS_ROLE + " TO GROUP 
" + USERGROUP1);
+
+    PrivilegeResultSet prset = new PrivilegeResultSet(statement, "SHOW GRANT 
ROLE "
+            + TEST_COL_METADATA_OPS_ROLE + " ON DATABASE " + 
TEST_COL_METADATA_OPS_DB);
+    LOGGER.info("SHOW GRANT : " + prset.toString());
+    prset.verifyResultSetColumn("table", TEST_COL_METADATA_OPS_TB);
+    prset.verifyResultSetColumn("column", "privileged");
+    prset.verifyResultSetColumn("privilege", "select");
+
+    statement.close();
+    connection.close();
+  }
+
+  private ResultSet executeQueryWithLog(Statement statement, String query) 
throws Exception {
+    ResultSet rs;
+    try {
+      LOGGER.info("Running " + query);
+      rs = statement.executeQuery(query);
+      return rs;
+    } catch (HiveSQLException ex) {
+      LOGGER.error("Privilege exception occurs when running : " + query);
+      throw ex;
+    }
+  }
+
+  private void validateColumnMetaData(String query, String colMetaField, 
String user,
+                                      String privileged, String unprivileged) 
throws Exception {
+    Connection conneciton = context.createConnection(user);
+    Statement statement = context.createStatement(conneciton);
+    statement.execute("USE " + TEST_COL_METADATA_OPS_DB);
+    ResultSet rs = executeQueryWithLog(statement, query);
+    boolean found = false;
+    while (rs.next()) {
+      String val = rs.getString(colMetaField);
+      // Relax validation for now:
+      // user with any select privilege can perform metadata operations,
+      // even though it might show some columns which he doesn't have 
privileges
+      //assertFalse("column unprivileged shouldn't be shown in result",
+      //        val.equalsIgnoreCase("unprivileged"));
+      if (val.equalsIgnoreCase("unprivileged")) {
+        LOGGER.warn("column unprivileged related metadata info is not disabled 
from result");
+      }
+      if (val.toLowerCase().contains(privileged)) {
+        LOGGER.info("detected privileged column information: " + privileged);
+        found = true;
+      } else if (val.toLowerCase().contains(unprivileged)) {
+        LOGGER.warn("detected unexpected column information: " + unprivileged);
+      }
+    }
+    rs.close();
+    statement.close();
+    conneciton.close();
+    assertTrue("failed to detect column privileged from result", found);
+  }
+
+  private void validateColumnMetaData(String query, String colMetaField, 
String user) throws Exception {
+    validateColumnMetaData(query, colMetaField, user, "privileged", 
"unprivileged");
+  }
+
+  private void validateSemanticException(String query, String user) throws 
Exception {
+    Connection conneciton = context.createConnection(user);
+    Statement statement = context.createStatement(conneciton);
+    try {
+      LOGGER.info("Running " + query);
+      statement.execute(query);
+      fail("failed to throw SemanticException");
+    } catch (Exception ex) {
+      String err = "SemanticException No valid privileges";
+      assertTrue("failed to detect " + err,
+              ex.getMessage().contains("SemanticException No valid 
privileges"));
+    }
+    statement.close();
+    conneciton.close();
+  }
+
+  /**
+   * Test with column level privilege
+   * user can NOT "show table extended"
+   */
+  @Test
+  public void testShowExtended() throws Exception {
+    String query = "SHOW TABLE EXTENDED IN " + TEST_COL_METADATA_OPS_DB
+            + " like '" + TEST_COL_METADATA_OPS_TB + "'";
+    // with column level privileges, user can not do show extended
+    validateSemanticException(query, USER1_1);
+    // negative test, without any privileges, user can not do it also
+    validateSemanticException(query, USER2_1);
+  }
+
+  /**
+   * Test with column level privileges,
+   * user can list all columns for now
+   */
+  @Test
+  public void testShowColumns() throws Exception {
+    String query = "SHOW COLUMNS IN " + TEST_COL_METADATA_OPS_DB + "." + 
TEST_COL_METADATA_OPS_TB;
+    // with column level privileges, user can show columns
+    validateColumnMetaData(query, "field", USER1_1);
+    // without column/table level privileges, any user can NOT show columns
+    validateSemanticException(query, USER2_1);
+  }
+
+  /**
+   * Test SHOW TBLPROPERTIES requires table level privileges
+   * @throws Exception
+   */
+  @Test
+  public void testShowProperties() throws Exception {
+    String query = "SHOW TBLPROPERTIES " + TEST_COL_METADATA_OPS_DB + "." + 
TEST_COL_METADATA_OPS_TB;
+    validateSemanticException(query, USER1_1);
+    validateSemanticException(query, USER2_1);
+  }
+
+  /**
+   * Test with column level select privilege,
+   * user can do "describe table"
+   */
+  @Test
+  public void testDescribeTable() throws Exception {
+    String query = "DESCRIBE " + TEST_COL_METADATA_OPS_DB + "." + 
TEST_COL_METADATA_OPS_TB;
+    // with column level privilege, user can describe table, but columns are 
not filtered for now
+    validateColumnMetaData(query, "col_name", USER1_1);
+    // without column/table level privileges, any user can NOT describe table
+    validateSemanticException(query, USER2_1);
+
+    // only with table level privileges user can describe extended/formatted
+    query = "DESCRIBE EXTENDED " + TEST_COL_METADATA_OPS_DB + "." + 
TEST_COL_METADATA_OPS_TB;
+    validateSemanticException(query, USER1_1);
+    validateSemanticException(query, USER2_1);
+
+    query = "DESCRIBE EXTENDED " + TEST_COL_METADATA_OPS_DB + "." + 
TEST_COL_METADATA_OPS_TB + " s";
+    validateSemanticException(query, USER1_1);
+    validateSemanticException(query, USER2_1);
+
+    query = "DESCRIBE FORMATTED " + TEST_COL_METADATA_OPS_DB + "." + 
TEST_COL_METADATA_OPS_TB;
+    validateSemanticException(query, USER1_1);
+    validateSemanticException(query, USER2_1);
+
+    query = "DESCRIBE FORMATTED " + TEST_COL_METADATA_OPS_DB + "." + 
TEST_COL_METADATA_OPS_TB + " s";
+    validateSemanticException(query, USER1_1);
+    validateSemanticException(query, USER2_1);
+  }
+
+  /**
+   * Test with column level select privilege,
+   * user can only do "explain select column";
+   * any other select requires table level privileges
+   * @throws Exception
+   */
+  @Ignore("After fix SENTRY-849, should enable this test")
+  @Test
+  public void testExplainSelect() throws Exception {
+    String query = "EXPLAIN SELECT privileged FROM " + 
TEST_COL_METADATA_OPS_DB + "." + TEST_COL_METADATA_OPS_TB;
+    // With column level privilege, user can explain select column
+    validateColumnMetaData(query, "Explain", USER1_1);
+    // Without column/table level privilege, user can NOT explain select column
+    validateSemanticException(query, USER2_1);
+
+    // user can NOT explain select unprivileged column
+    query = "EXPLAIN SELECT unprivileged FROM " + TEST_COL_METADATA_OPS_DB + 
"." + TEST_COL_METADATA_OPS_TB;
+    validateSemanticException(query, USER1_1);
+    validateSemanticException(query, USER2_1);
+
+    query = "EXPLAIN SELECT * FROM " + TEST_COL_METADATA_OPS_DB + "." + 
TEST_COL_METADATA_OPS_TB;
+    validateSemanticException(query, USER1_1);
+    validateSemanticException(query, USER2_1);
+
+    query = "EXPLAIN SELECT count(*) FROM " + TEST_COL_METADATA_OPS_DB + "." + 
TEST_COL_METADATA_OPS_TB;
+    validateSemanticException(query, USER1_1);
+    validateSemanticException(query, USER2_1);
+
+    query = "EXPLAIN SELECT * FROM (SELECT privileged AS c FROM " +
+            TEST_COL_METADATA_OPS_DB + "." + TEST_COL_METADATA_OPS_TB + " 
union all select unprivileged as c from "
+            + TEST_COL_METADATA_OPS_DB + "." + TEST_COL_METADATA_OPS_TB + ") 
subq1 order by c";
+    validateSemanticException(query, USER1_1);
+    validateSemanticException(query, USER2_1);
+  }
+
+  /**
+   * Test if add a new column and grant privilege,
+   * test user can immediately has metadata access to this column
+   */
+  @Test
+  public void testShowNewColumn() throws Exception {
+    String colName = "newcol";
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE " + TEST_COL_METADATA_OPS_DB);
+    statement.execute("ALTER TABLE " + TEST_COL_METADATA_OPS_TB + " ADD 
COLUMNS (" + colName + " STRING)");
+    statement.execute("GRANT SELECT(" + colName + ") ON TABLE " + 
TEST_COL_METADATA_OPS_TB + " TO ROLE " + TEST_COL_METADATA_OPS_ROLE);
+    statement.close();
+    connection.close();
+
+    Connection newconn = context.createConnection(ADMIN1);
+    Statement newstmt = context.createStatement(newconn);
+    newstmt.execute("USE " + TEST_COL_METADATA_OPS_DB);
+    ResultSet rs = executeQueryWithLog(newstmt, "SHOW COLUMNS IN " + 
TEST_COL_METADATA_OPS_TB);
+    boolean found = false;
+    while (rs.next() && !found) {
+      String val = rs.getString("field");
+      LOGGER.info("found " + val);
+      if (val.equalsIgnoreCase(colName)) {
+        found = true;
+      }
+    }
+    assertTrue("Failed to show " + colName, found);
+    rs.close();
+    newstmt.close();
+    newconn.close();
+  }
+
+  /**
+   * Grant user column level privileges, show partitions
+   * should list user's granted columns
+   * @throws Exception
+   */
+  @Ignore("After fix SENTRY-898, turn on this test")
+  @Test
+  public void testShowPartitions() throws Exception {
+    final String PAR_ROLE_NAME = TEST_COL_METADATA_OPS_ROLE + "_2";
+
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE " + TEST_COL_METADATA_OPS_DB);
+    statement.execute("CREATE ROLE " + PAR_ROLE_NAME);
+    statement.execute("GRANT SELECT(privileged_par) ON TABLE " + 
TEST_COL_METADATA_OPS_TB + " TO ROLE " + PAR_ROLE_NAME);
+    statement.execute("GRANT ROLE " + PAR_ROLE_NAME + " TO GROUP " + 
USERGROUP1);
+    statement.close();
+    connection.close();
+
+    String query = "SHOW PARTITIONS " + TEST_COL_METADATA_OPS_DB + "." + 
TEST_COL_METADATA_OPS_TB;
+    validateColumnMetaData(query, "partition", USER1_1, "privileged_par", 
"unprivileged_par");
+  }
+
+}

Reply via email to