You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by sh...@apache.org on 2013/09/07 00:36:19 UTC

git commit: SENTRY-1: use default on HiveServer2 fails with invalid privileges exception (Prasad Mujumdar via Shreepadma Venugopalan)

Updated Branches:
  refs/heads/master c98ac0c37 -> ecc85161f


SENTRY-1: use default on HiveServer2 fails with invalid privileges exception (Prasad Mujumdar via Shreepadma Venugopalan)


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

Branch: refs/heads/master
Commit: ecc85161f73e11da54dba35822f284083a1c57de
Parents: c98ac0c
Author: Shreepadma Venugopalan <sh...@apache.org>
Authored: Fri Sep 6 15:35:42 2013 -0700
Committer: Shreepadma Venugopalan <sh...@apache.org>
Committed: Fri Sep 6 15:35:42 2013 -0700

----------------------------------------------------------------------
 .../org/apache/sentry/provider/file/Roles.java  |  16 +-
 .../file/AbstractTestSimplePolicyEngine.java    |  22 ++-
 .../tests/e2e/TestPerDBConfiguration.java       | 173 +++++++++++++++++++
 3 files changed, 207 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/ecc85161/sentry-provider/sentry-provider-file/src/main/java/org/apache/sentry/provider/file/Roles.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-file/src/main/java/org/apache/sentry/provider/file/Roles.java b/sentry-provider/sentry-provider-file/src/main/java/org/apache/sentry/provider/file/Roles.java
index 556be01..924c2cc 100644
--- a/sentry-provider/sentry-provider-file/src/main/java/org/apache/sentry/provider/file/Roles.java
+++ b/sentry-provider/sentry-provider-file/src/main/java/org/apache/sentry/provider/file/Roles.java
@@ -16,15 +16,17 @@
  */
 package org.apache.sentry.provider.file;
 
+import java.util.Map.Entry;
+
 import javax.annotation.Nullable;
 
+import org.apache.sentry.core.Database;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.io.Resources;
 
 public class Roles {
   private static final Logger LOGGER = LoggerFactory
@@ -44,16 +46,24 @@ public class Roles {
   }
   public ImmutableSet<String> getRoles(@Nullable String database, String group, Boolean isURI) {
     ImmutableSet.Builder<String> resultBuilder = ImmutableSet.builder();
-    String allowURIPerDbFile = 
+    String allowURIPerDbFile =
         System.getProperty(SimplePolicyEngine.ACCESS_ALLOW_URI_PER_DB_POLICYFILE);
     Boolean consultPerDbRolesForURI = isURI && ("true".equalsIgnoreCase(allowURIPerDbFile));
 
-    if(database != null) {
+    // handle Database.ALL
+    if (Database.ALL.getName().equals(database)) {
+      for(Entry<String, ImmutableSetMultimap<String, String>> dbListEntry : perDatabaseRoles.entrySet()) {
+        if (dbListEntry.getValue().containsKey(group)) {
+          resultBuilder.addAll(dbListEntry.getValue().get(group));
+        }
+      }
+    } else if(database != null) {
       ImmutableSetMultimap<String, String> dbPolicies =  perDatabaseRoles.get(database);
       if(dbPolicies != null && dbPolicies.containsKey(group)) {
         resultBuilder.addAll(dbPolicies.get(group));
       }
     }
+
     if (consultPerDbRolesForURI) {
       for(String db:perDatabaseRoles.keySet()) {
         ImmutableSetMultimap<String, String> dbPolicies =  perDatabaseRoles.get(db);

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/ecc85161/sentry-provider/sentry-provider-file/src/test/java/org/apache/sentry/provider/file/AbstractTestSimplePolicyEngine.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-file/src/test/java/org/apache/sentry/provider/file/AbstractTestSimplePolicyEngine.java b/sentry-provider/sentry-provider-file/src/test/java/org/apache/sentry/provider/file/AbstractTestSimplePolicyEngine.java
index bfa2d68..5388b0f 100644
--- a/sentry-provider/sentry-provider-file/src/test/java/org/apache/sentry/provider/file/AbstractTestSimplePolicyEngine.java
+++ b/sentry-provider/sentry-provider-file/src/test/java/org/apache/sentry/provider/file/AbstractTestSimplePolicyEngine.java
@@ -27,7 +27,6 @@ import junit.framework.Assert;
 import org.apache.commons.io.FileUtils;
 import org.apache.sentry.core.Authorizable;
 import org.apache.sentry.core.Database;
-import org.apache.sentry.provider.file.PolicyEngine;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
@@ -136,6 +135,27 @@ public abstract class AbstractTestSimplePolicyEngine {
         .toString());
   }
 
+  @Test
+  public void testDbAll() throws Exception {
+    authorizables.add(new Database(Database.ALL.getName()));
+    Set<String> expected = Sets.newTreeSet(Sets
+        .newHashSet(PERM_SERVER1_JUNIOR_ANALYST_ALL,
+            PERM_SERVER1_CUSTOMERS_DB_CUSTOMERS_PARTIAL_SELECT));
+    Assert.assertEquals(expected.toString(),
+        new TreeSet<String>(policy.getPermissions(authorizables, list("jranalyst")).values())
+        .toString());
+  }
+
+  @Test
+  public void testDbAllforOtherGroup() throws Exception {
+    authorizables.add(new Database(Database.ALL.getName()));
+    Set<String> expected = Sets.newTreeSet(Sets.newHashSet(
+        PERM_SERVER1_OTHER_GROUP_DB_CUSTOMERS_SELECT));
+    Assert.assertEquals(expected.toString(),
+        new TreeSet<String>(policy.getPermissions(authorizables, list("other_group")).values())
+        .toString());
+  }
+
   private static List<String> list(String... values) {
     return Lists.newArrayList(values);
   }

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/ecc85161/sentry-tests/src/test/java/org/apache/sentry/tests/e2e/TestPerDBConfiguration.java
----------------------------------------------------------------------
diff --git a/sentry-tests/src/test/java/org/apache/sentry/tests/e2e/TestPerDBConfiguration.java b/sentry-tests/src/test/java/org/apache/sentry/tests/e2e/TestPerDBConfiguration.java
index b0523ab..7fb7f6c 100644
--- a/sentry-tests/src/test/java/org/apache/sentry/tests/e2e/TestPerDBConfiguration.java
+++ b/sentry-tests/src/test/java/org/apache/sentry/tests/e2e/TestPerDBConfiguration.java
@@ -408,6 +408,179 @@ public class TestPerDBConfiguration extends AbstractTestWithStaticLocalFS {
     System.setProperty(SimplePolicyEngine.ACCESS_ALLOW_URI_PER_DB_POLICYFILE, "false");
   }
 
+  /**
+   * Test 'use default' statement. It should work as long as the user as privilege to assess any object in system
+   * @throws Exception
+   */
+  @Test
+  public void testDefaultDb() throws Exception {
+    context = createContext();
+    File policyFile = context.getPolicyFile();
+    File dataDir = context.getDataDir();
+    //copy data file to test dir
+    File dataFile = new File(dataDir, MULTI_TYPE_DATA_FILE_NAME);
+    FileOutputStream to = new FileOutputStream(dataFile);
+    Resources.copy(Resources.getResource(MULTI_TYPE_DATA_FILE_NAME), to);
+    to.close();
+    //delete existing policy file; create new policy file
+    assertTrue("Could not delete " + policyFile, context.deletePolicyFile());
+
+    String[] policyFileContents = {
+        // groups : role -> group
+        "[groups]",
+        "admin = all_server",
+        "user_group1 = select_tbl1",
+        // roles: privileges -> role
+        "[roles]",
+        "all_server = server=server1",
+        "select_tbl1 = server=server1->db=db1->table=tbl1->action=select",
+        // users: users -> groups
+        "[users]",
+        "hive = admin",
+        "user_1 = user_group1",
+        "user_2 = user_group2",
+    };
+    context.makeNewPolicy(policyFileContents);
+
+    // setup db objects needed by the test
+    Connection connection = context.createConnection("hive", "hive");
+    Statement statement = context.createStatement(connection);
+
+    statement.execute("USE default");
+
+    statement.execute("DROP DATABASE IF EXISTS db1 CASCADE");
+    statement.execute("CREATE DATABASE db1");
+    statement.execute("USE db1");
+    statement.execute("CREATE TABLE tbl1(B INT, A STRING) " +
+                      " row format delimited fields terminated by '|'  stored as textfile");
+    statement.execute("DROP DATABASE IF EXISTS db2 CASCADE");
+    statement.close();
+    connection.close();
+
+    // user_1 should be able to access default
+    connection = context.createConnection("user_1", "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE default");
+    statement.close();
+    connection.close();
+
+    // user_2 should NOT be able to access default since it does have access to any other object
+    connection = context.createConnection("user_2", "password");
+    statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "USE default");
+    statement.close();
+    connection.close();
+
+  }
+
+  @Test
+  public void testDefaultDBwithDbPolicy() throws Exception {
+    context = createContext();
+    File policyFile = context.getPolicyFile();
+    File db2PolicyFile = new File(policyFile.getParent(), DB2_POLICY_FILE);
+    File defaultPolicyFile = new File(policyFile.getParent(), "default-policy-file.ini");
+    File dataDir = context.getDataDir();
+    //copy data file to test dir
+    File dataFile = new File(dataDir, MULTI_TYPE_DATA_FILE_NAME);
+    FileOutputStream to = new FileOutputStream(dataFile);
+    Resources.copy(Resources.getResource(MULTI_TYPE_DATA_FILE_NAME), to);
+    to.close();
+    //delete existing policy file; create new policy file
+    assertTrue("Could not delete " + policyFile, context.deletePolicyFile());
+    assertTrue("Could not delete " + db2PolicyFile,!db2PolicyFile.exists() || db2PolicyFile.delete());
+    assertTrue("Could not delete " + defaultPolicyFile,!defaultPolicyFile.exists() || defaultPolicyFile.delete());
+
+    String[] policyFileContents = {
+        // groups : role -> group
+        "[groups]",
+        "admin = all_server",
+        "user_group1 = select_tbl1",
+        "user_group2 = select_tbl2",
+        // roles: privileges -> role
+        "[roles]",
+        "all_server = server=server1",
+        "select_tbl1 = server=server1->db=db1->table=tbl1->action=select",
+        // users: users -> groups
+        "[users]",
+        "hive = admin",
+        "user_1 = user_group1",
+        "user_2 = user_group2",
+        "user_3 = user_group3",
+        "[databases]",
+        "db2 = " + db2PolicyFile.getPath(),
+        "default = " + defaultPolicyFile.getPath()
+    };
+    context.makeNewPolicy(policyFileContents);
+
+    String[] db2PolicyFileContents = {
+        "[groups]",
+        "user_group2 = select_tbl2",
+        "[roles]",
+        "select_tbl2 = server=server1->db=db2->table=tbl2->action=select"
+    };
+    Files.write(Joiner.on("\n").join(db2PolicyFileContents), db2PolicyFile, Charsets.UTF_8);
+
+    String[] defautlPolicyFileContents = {
+        "[groups]",
+        "user_group2 = select_def",
+        "[roles]",
+        "select_def = server=server1->db=default->table=dtab->action=select"
+    };
+    Files.write(Joiner.on("\n").join(defautlPolicyFileContents), defaultPolicyFile, Charsets.UTF_8);
+
+
+    // setup db objects needed by the test
+    Connection connection = context.createConnection("hive", "hive");
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE default");
+    statement.execute("CREATE TABLE dtab(B INT, A STRING) " +
+                      " row format delimited fields terminated by '|'  stored as textfile");
+
+    statement.execute("DROP DATABASE IF EXISTS db1 CASCADE");
+    statement.execute("DROP DATABASE IF EXISTS db2 CASCADE");
+    statement.execute("CREATE DATABASE db1");
+    statement.execute("USE db1");
+    statement.execute("CREATE TABLE tbl1(B INT, A STRING) " +
+                      " row format delimited fields terminated by '|'  stored as textfile");
+    statement.execute("DROP DATABASE IF EXISTS db2 CASCADE");
+    statement.execute("CREATE DATABASE db2");
+    statement.execute("USE db2");
+    statement.execute("CREATE TABLE tbl2(B INT, A STRING) " +
+                      " row format delimited fields terminated by '|'  stored as textfile");
+    statement.close();
+    connection.close();
+
+    // user_1 should be able to switch to default, but not the tables from default
+    connection = context.createConnection("user_1", "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE db1");
+    statement.execute("USE default");
+    context.assertAuthzException(statement, "SELECT * FROM dtab");
+    statement.execute("USE db1");
+    context.assertAuthzException(statement, "SELECT * FROM default.dtab");
+
+    statement.close();
+    connection.close();
+
+    // user_2 should be able to access default and select from default's tables
+    connection = context.createConnection("user_2", "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE db2");
+    statement.execute("USE default");
+    statement.execute("SELECT * FROM dtab");
+    statement.execute("USE db2");
+    statement.execute("SELECT * FROM default.dtab");
+    statement.close();
+    connection.close();
+
+    // user_3 should NOT be able to switch to default since it doesn't have access to any objects
+    connection = context.createConnection("user_3", "password");
+    statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "USE default");
+    statement.close();
+    connection.close();
+  }
+
   private void verifyCount(Statement statement, String query) throws SQLException {
     ResultSet resultSet = statement.executeQuery(query);
     int count = 0;