sentry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From shreepa...@apache.org
Subject git commit: SENTRY-35: Create sentry-provider-policy-search module (Gregory Chanan via Shreepadma Venugopalan)
Date Wed, 16 Oct 2013 16:47:14 GMT
Updated Branches:
  refs/heads/master fe5fb70f6 -> 1824f7808


SENTRY-35: Create sentry-provider-policy-search module (Gregory Chanan 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/1824f780
Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/1824f780
Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/1824f780

Branch: refs/heads/master
Commit: 1824f780837c9e616af5b9e0ae4f1f82c46df6fa
Parents: fe5fb70
Author: Shreepadma Venugopalan <shreepadma@apache.org>
Authored: Tue Oct 15 17:25:04 2013 -0700
Committer: Shreepadma Venugopalan <shreepadma@apache.org>
Committed: Tue Oct 15 17:25:04 2013 -0700

----------------------------------------------------------------------
 .../sentry-provider-policy-search/pom.xml       |  20 +++
 .../search/SimpleSearchPolicyEngine.java        | 114 ++++++++++++
 .../search/AbstractTestSearchPolicyEngine.java  | 133 ++++++++++++++
 .../search/SearchPolicyFileBackend.java         |  26 +++
 ...SearchAuthorizationProviderGeneralCases.java | 179 +++++++++++++++++++
 ...SearchAuthorizationProviderSpecialCases.java |  81 +++++++++
 .../search/TestSearchPolicyEngineDFS.java       |  81 +++++++++
 .../search/TestSearchPolicyEngineLocalFS.java   |  43 +++++
 .../search/TestSearchPolicyNegative.java        | 111 ++++++++++++
 .../src/test/resources/log4j.properties         |  31 ++++
 .../src/test/resources/test-authz-provider.ini  |  31 ++++
 11 files changed, 850 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/1824f780/sentry-provider/sentry-provider-policy-search/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-policy-search/pom.xml b/sentry-provider/sentry-provider-policy-search/pom.xml
index 5156c2c..80db002 100644
--- a/sentry-provider/sentry-provider-policy-search/pom.xml
+++ b/sentry-provider/sentry-provider-policy-search/pom.xml
@@ -34,6 +34,15 @@ limitations under the License.
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-minicluster</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
     </dependency>
@@ -59,8 +68,19 @@ limitations under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.sentry</groupId>
+      <artifactId>sentry-provider-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sentry</groupId>
       <artifactId>sentry-provider-file</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.sentry</groupId>
+      <artifactId>sentry-provider-common</artifactId>
+      <scope>test</scope>
+      <type>test-jar</type>
+      <version>${project.version}</version>
+    </dependency>
   </dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/1824f780/sentry-provider/sentry-provider-policy-search/src/main/java/org/apache/sentry/provider/search/SimpleSearchPolicyEngine.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-policy-search/src/main/java/org/apache/sentry/provider/search/SimpleSearchPolicyEngine.java
b/sentry-provider/sentry-provider-policy-search/src/main/java/org/apache/sentry/provider/search/SimpleSearchPolicyEngine.java
new file mode 100644
index 0000000..7d37660
--- /dev/null
+++ b/sentry-provider/sentry-provider-policy-search/src/main/java/org/apache/sentry/provider/search/SimpleSearchPolicyEngine.java
@@ -0,0 +1,114 @@
+/*
+ * 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.provider.search;
+
+import javax.annotation.Nullable;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map.Entry;
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.provider.common.PermissionFactory;
+import org.apache.sentry.provider.common.PolicyEngine;
+import org.apache.sentry.provider.common.ProviderBackend;
+import org.apache.sentry.provider.common.Roles;
+import org.apache.sentry.provider.common.RoleValidator;
+import org.apache.sentry.provider.file.SimpleFileProviderBackend;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Lists;
+
+/**
+ * A PolicyEngine for a search service.
+ */
+public class SimpleSearchPolicyEngine implements PolicyEngine {
+
+  private static final Logger LOGGER = LoggerFactory
+      .getLogger(SimpleSearchPolicyEngine.class);
+
+  private ProviderBackend providerBackend;
+
+  public SimpleSearchPolicyEngine(ProviderBackend providerBackend) {
+    List<? extends RoleValidator> validators =
+      Lists.newArrayList(new CollectionRequiredInRole());
+    this.providerBackend = providerBackend;
+    this.providerBackend.process(validators);
+
+    if (!this.providerBackend.getRoles().getPerDatabaseRoles().isEmpty()) {
+      throw new ConfigurationException(
+        "SimpleSearchPolicyEngine does not support per-database roles, " +
+        "but per-database roles were specified.  Ignoring.");
+    }
+  }
+
+  /*
+   * Note: finalize is final because constructor throws exception, see:
+   * OBJ11-J.
+   */
+  public final void finalize() {
+    // do nothing
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public PermissionFactory getPermissionFactory() {
+    return new SearchWildcardPermission.SearchWildcardPermissionFactory();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ImmutableSetMultimap<String, String> getPermissions(List<? extends Authorizable>
authorizables, List<String> groups) {
+    if(LOGGER.isDebugEnabled()) {
+      LOGGER.debug("Getting permissions for {}", groups);
+    }
+    ImmutableSetMultimap.Builder<String, String> resultBuilder = ImmutableSetMultimap.builder();
+    for(String group : groups) {
+      resultBuilder.putAll(group, getSearchRoles(group,providerBackend.getRoles()));
+    }
+    ImmutableSetMultimap<String, String> result = resultBuilder.build();
+    if(LOGGER.isDebugEnabled()) {
+      LOGGER.debug("result = " + result);
+    }
+    return result;
+  }
+
+  private ImmutableSet<String> getSearchRoles(String group, Roles roles) {
+    ImmutableSetMultimap<String, String> globalRoles = roles.getGlobalRoles();
+    ImmutableSet.Builder<String> resultBuilder = ImmutableSet.builder();
+
+    if(globalRoles.containsKey(group)) {
+      resultBuilder.addAll(globalRoles.get(group));
+    }
+    ImmutableSet<String> result = resultBuilder.build();
+    if(LOGGER.isDebugEnabled()) {
+      LOGGER.debug("Group {}, Result {}",
+          new Object[]{ group, result});
+    }
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/1824f780/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/AbstractTestSearchPolicyEngine.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/AbstractTestSearchPolicyEngine.java
b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/AbstractTestSearchPolicyEngine.java
new file mode 100644
index 0000000..0583a51
--- /dev/null
+++ b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/AbstractTestSearchPolicyEngine.java
@@ -0,0 +1,133 @@
+/*
+ * 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.provider.search;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import junit.framework.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.core.model.search.Collection;
+import org.apache.sentry.provider.common.PolicyEngine;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
+
+public abstract class AbstractTestSearchPolicyEngine {
+  private static final String ANALYST_PURCHASES_UPDATE = "collection=purchases->action=update";
+  private static final String ANALYST_ANALYST1_ALL = "collection=analyst1";
+  private static final String ANALYST_JRANALYST1_ACTION_ALL = "collection=jranalyst1->action=*";
+  private static final String ANALYST_TMPCOLLECTION_UPDATE = "collection=tmpcollection->action=update";
+  private static final String ANALYST_TMPCOLLECTION_QUERY = "collection=tmpcollection->action=query";
+  private static final String JRANALYST_JRANALYST1_ALL = "collection=jranalyst1";
+  private static final String JRANALYST_PURCHASES_PARTIAL_QUERY = "collection=purchases_partial->action=query";
+  private static final String ADMIN_COLLECTION_ALL = "collection=*";
+
+  private PolicyEngine policy;
+  private static File baseDir;
+  private List<Authorizable> authorizables = Lists.newArrayList();
+
+  @BeforeClass
+  public static void setupClazz() throws IOException {
+    baseDir = Files.createTempDir();
+  }
+
+  @AfterClass
+  public static void teardownClazz() throws IOException {
+    if(baseDir != null) {
+      FileUtils.deleteQuietly(baseDir);
+    }
+  }
+
+  protected void setPolicy(PolicyEngine policy) {
+    this.policy = policy;
+  }
+  protected static File getBaseDir() {
+    return baseDir;
+  }
+  @Before
+  public void setup() throws IOException {
+    afterSetup();
+  }
+  @After
+  public void teardown() throws IOException {
+    beforeTeardown();
+  }
+  protected void afterSetup() throws IOException {
+
+  }
+
+  protected void beforeTeardown() throws IOException {
+
+  }
+
+  @Test
+  public void testManager() throws Exception {
+    Set<String> expected = Sets.newTreeSet(Sets.newHashSet(
+        ANALYST_PURCHASES_UPDATE, ANALYST_ANALYST1_ALL,
+        ANALYST_JRANALYST1_ACTION_ALL, ANALYST_TMPCOLLECTION_UPDATE,
+        ANALYST_TMPCOLLECTION_QUERY, JRANALYST_JRANALYST1_ALL,
+        JRANALYST_PURCHASES_PARTIAL_QUERY));
+    Assert.assertEquals(expected.toString(),
+        new TreeSet<String>(policy.getPermissions(authorizables, list("manager")).values())
+        .toString());
+  }
+
+  @Test
+  public void testAnalyst() throws Exception {
+    Set<String> expected = Sets.newTreeSet(Sets.newHashSet(
+        ANALYST_PURCHASES_UPDATE, ANALYST_ANALYST1_ALL,
+        ANALYST_JRANALYST1_ACTION_ALL, ANALYST_TMPCOLLECTION_UPDATE,
+        ANALYST_TMPCOLLECTION_QUERY));
+    Assert.assertEquals(expected.toString(),
+        new TreeSet<String>(policy.getPermissions(authorizables, list("analyst")).values())
+        .toString());
+  }
+
+  @Test
+  public void testJuniorAnalyst() throws Exception {
+    Set<String> expected = Sets.newTreeSet(Sets
+        .newHashSet(JRANALYST_JRANALYST1_ALL,
+            JRANALYST_PURCHASES_PARTIAL_QUERY));
+    Assert.assertEquals(expected.toString(),
+        new TreeSet<String>(policy.getPermissions(authorizables, list("jranalyst")).values())
+        .toString());
+  }
+
+  @Test
+  public void testAdmin() throws Exception {
+    Set<String> expected = Sets.newTreeSet(Sets.newHashSet(ADMIN_COLLECTION_ALL));
+    Assert.assertEquals(expected.toString(),
+        new TreeSet<String>(policy.getPermissions(authorizables, list("admin")).values())
+        .toString());
+  }
+
+  private static List<String> list(String... values) {
+    return Lists.newArrayList(values);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/1824f780/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/SearchPolicyFileBackend.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/SearchPolicyFileBackend.java
b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/SearchPolicyFileBackend.java
new file mode 100644
index 0000000..db331ab
--- /dev/null
+++ b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/SearchPolicyFileBackend.java
@@ -0,0 +1,26 @@
+/*
+ * 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.provider.search;
+
+import java.io.IOException;
+import org.apache.sentry.provider.file.SimpleFileProviderBackend;
+
+public class SearchPolicyFileBackend extends SimpleSearchPolicyEngine {
+  public SearchPolicyFileBackend(String resource) throws IOException{
+    super(new SimpleFileProviderBackend(resource));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/1824f780/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchAuthorizationProviderGeneralCases.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchAuthorizationProviderGeneralCases.java
b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchAuthorizationProviderGeneralCases.java
new file mode 100644
index 0000000..95d436f
--- /dev/null
+++ b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchAuthorizationProviderGeneralCases.java
@@ -0,0 +1,179 @@
+/*
+ * 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.provider.search;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.Action;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.core.common.Subject;
+import org.apache.sentry.core.model.search.SearchConstants;
+import org.apache.sentry.core.model.search.SearchModelAction;
+import org.apache.sentry.core.model.search.Collection;
+import org.apache.sentry.provider.common.MockGroupMappingServiceProvider;
+import org.apache.sentry.provider.file.HadoopGroupResourceAuthorizationProvider;
+import org.apache.sentry.provider.file.PolicyFiles;
+import org.apache.sentry.provider.file.ResourceAuthorizationProvider;
+import org.junit.After;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.io.Files;
+
+
+public class TestSearchAuthorizationProviderGeneralCases {
+
+  private static final Logger LOGGER = LoggerFactory
+      .getLogger(TestSearchAuthorizationProviderGeneralCases.class);
+
+  private static final Multimap<String, String> USER_TO_GROUP_MAP = HashMultimap
+      .create();
+
+  private static final Subject SUB_ADMIN = new Subject("admin1");
+  private static final Subject SUB_MANAGER = new Subject("manager1");
+  private static final Subject SUB_ANALYST = new Subject("analyst1");
+  private static final Subject SUB_JUNIOR_ANALYST = new Subject("jranalyst1");
+
+  private static final Collection COLL_PURCHASES = new Collection("purchases");
+  private static final Collection COLL_ANALYST1 = new Collection("analyst1");
+  private static final Collection COLL_JRANALYST1 = new Collection("jranalyst1");
+  private static final Collection COLL_TMP = new Collection("tmpcollection");
+  private static final Collection COLL_PURCHASES_PARTIAL = new Collection("purchases_partial");
+
+  private static final SearchModelAction ALL = SearchModelAction.ALL;
+  private static final SearchModelAction QUERY = SearchModelAction.QUERY;
+  private static final SearchModelAction UPDATE = SearchModelAction.UPDATE;
+
+  static {
+    USER_TO_GROUP_MAP.putAll(SUB_ADMIN.getName(), Arrays.asList("admin"));
+    USER_TO_GROUP_MAP.putAll(SUB_MANAGER.getName(), Arrays.asList("manager"));
+    USER_TO_GROUP_MAP.putAll(SUB_ANALYST.getName(), Arrays.asList("analyst"));
+    USER_TO_GROUP_MAP.putAll(SUB_JUNIOR_ANALYST.getName(),
+        Arrays.asList("jranalyst"));
+  }
+
+  private final ResourceAuthorizationProvider authzProvider;
+  private File baseDir;
+
+  public TestSearchAuthorizationProviderGeneralCases() throws IOException {
+    baseDir = Files.createTempDir();
+    PolicyFiles.copyToDir(baseDir, "test-authz-provider.ini");
+    authzProvider = new HadoopGroupResourceAuthorizationProvider(
+        new SearchPolicyFileBackend(new File(baseDir, "test-authz-provider.ini").getPath()),
+        new MockGroupMappingServiceProvider(USER_TO_GROUP_MAP));
+
+  }
+
+  @After
+  public void teardown() {
+    if(baseDir != null) {
+      FileUtils.deleteQuietly(baseDir);
+    }
+  }
+
+  private void doTestAuthProviderOnCollection(Subject subject,
+      Collection collection, Set<? extends Action> expectedPass) throws Exception {
+    Set<SearchModelAction> allActions = EnumSet.of(SearchModelAction.ALL, SearchModelAction.QUERY,
SearchModelAction.UPDATE);
+    for(SearchModelAction action : allActions) {
+      doTestResourceAuthorizationProvider(subject, collection,
+        EnumSet.of(action), expectedPass.contains(action));
+    }
+  }
+
+  private void doTestResourceAuthorizationProvider(Subject subject,
+      Collection collection,
+      Set<? extends Action> privileges, boolean expected) throws Exception {
+    List<Authorizable> authzHierarchy = Arrays.asList(new Authorizable[] {
+        collection
+    });
+    Objects.ToStringHelper helper = Objects.toStringHelper("TestParameters");
+    helper.add("Subject", subject).add("Collection", collection)
+      .add("Privileges", privileges).add("authzHierarchy", authzHierarchy);
+    LOGGER.info("Running with " + helper.toString());
+    Assert.assertEquals(helper.toString(), expected,
+        authzProvider.hasAccess(subject, authzHierarchy, privileges));
+    LOGGER.info("Passed " + helper.toString());
+  }
+
+  @Test
+  public void testAdmin() throws Exception {
+    Set<SearchModelAction> allActions = EnumSet.allOf(SearchModelAction.class);
+    doTestAuthProviderOnCollection(SUB_ADMIN, COLL_PURCHASES, allActions);
+    doTestAuthProviderOnCollection(SUB_ADMIN, COLL_ANALYST1, allActions);
+    doTestAuthProviderOnCollection(SUB_ADMIN, COLL_JRANALYST1, allActions);
+    doTestAuthProviderOnCollection(SUB_ADMIN, COLL_TMP, allActions);
+    doTestAuthProviderOnCollection(SUB_ADMIN, COLL_PURCHASES_PARTIAL, allActions);
+  }
+
+  @Test
+  public void testManager() throws Exception {
+    Set<SearchModelAction> updateOnly = EnumSet.of(SearchModelAction.UPDATE);
+    doTestAuthProviderOnCollection(SUB_MANAGER, COLL_PURCHASES, updateOnly);
+
+    Set<SearchModelAction> allActions = EnumSet.allOf(SearchModelAction.class);
+    doTestAuthProviderOnCollection(SUB_MANAGER, COLL_ANALYST1, allActions);
+    doTestAuthProviderOnCollection(SUB_MANAGER, COLL_JRANALYST1, allActions);
+
+    Set<SearchModelAction> queryUpdateOnly = EnumSet.of(QUERY, UPDATE);
+    doTestAuthProviderOnCollection(SUB_MANAGER, COLL_TMP, queryUpdateOnly);
+
+    Set<SearchModelAction> queryOnly = EnumSet.of(SearchModelAction.QUERY);
+    doTestAuthProviderOnCollection(SUB_MANAGER, COLL_PURCHASES_PARTIAL, queryOnly);
+  }
+
+  @Test
+  public void testAnalyst() throws Exception {
+    Set<SearchModelAction> updateOnly = EnumSet.of(SearchModelAction.UPDATE);
+    doTestAuthProviderOnCollection(SUB_ANALYST, COLL_PURCHASES, updateOnly);
+
+    Set<SearchModelAction> allActions = EnumSet.allOf(SearchModelAction.class);
+    doTestAuthProviderOnCollection(SUB_ANALYST, COLL_ANALYST1, allActions);
+    doTestAuthProviderOnCollection(SUB_ANALYST, COLL_JRANALYST1, allActions);
+
+    Set<SearchModelAction> queryUpdateOnly = EnumSet.of(QUERY, UPDATE);
+    doTestAuthProviderOnCollection(SUB_ANALYST, COLL_TMP, queryUpdateOnly);
+
+    Set<SearchModelAction> noActions = EnumSet.noneOf(SearchModelAction.class);
+    doTestAuthProviderOnCollection(SUB_ANALYST, COLL_PURCHASES_PARTIAL, noActions);
+  }
+
+  @Test
+  public void testJuniorAnalyst() throws Exception {
+     Set<SearchModelAction> allActions = EnumSet.allOf(SearchModelAction.class);
+     doTestAuthProviderOnCollection(SUB_JUNIOR_ANALYST, COLL_JRANALYST1, allActions);
+
+    Set<SearchModelAction> queryOnly = EnumSet.of(SearchModelAction.QUERY);
+    doTestAuthProviderOnCollection(SUB_JUNIOR_ANALYST, COLL_PURCHASES_PARTIAL, queryOnly);
+
+    Set<SearchModelAction> noActions = EnumSet.noneOf(SearchModelAction.class);
+    doTestAuthProviderOnCollection(SUB_JUNIOR_ANALYST, COLL_PURCHASES, noActions);
+    doTestAuthProviderOnCollection(SUB_JUNIOR_ANALYST, COLL_ANALYST1, noActions);
+    doTestAuthProviderOnCollection(SUB_JUNIOR_ANALYST, COLL_TMP, noActions);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/1824f780/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchAuthorizationProviderSpecialCases.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchAuthorizationProviderSpecialCases.java
b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchAuthorizationProviderSpecialCases.java
new file mode 100644
index 0000000..0163275
--- /dev/null
+++ b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchAuthorizationProviderSpecialCases.java
@@ -0,0 +1,81 @@
+ /*
+ * 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.provider.search;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.core.common.AuthorizationProvider;
+import org.apache.sentry.core.common.Action;
+import org.apache.sentry.core.common.Subject;
+import org.apache.sentry.core.model.search.Collection;
+import org.apache.sentry.core.model.search.SearchModelAction;
+import org.apache.sentry.provider.file.LocalGroupResourceAuthorizationProvider;
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.Files;
+
+public class TestSearchAuthorizationProviderSpecialCases {
+  private AuthorizationProvider authzProvider;
+  private PolicyFile policyFile;
+  private File baseDir;
+  private File iniFile;
+  private String initResource;
+  @Before
+  public void setup() throws IOException {
+    baseDir = Files.createTempDir();
+    iniFile = new File(baseDir, "policy.ini");
+    initResource = "file://" + iniFile.getPath();
+    policyFile = new PolicyFile();
+  }
+
+  @After
+  public void teardown() throws IOException {
+    if(baseDir != null) {
+      FileUtils.deleteQuietly(baseDir);
+    }
+  }
+
+  @Test
+  public void testDuplicateEntries() throws Exception {
+    Subject user1 = new Subject("user1");
+    Collection collection1 = new Collection("collection1");
+    Set<? extends Action> actions = EnumSet.allOf(SearchModelAction.class);
+    policyFile.addGroupsToUser(user1.getName(), true, "group1", "group1")
+      .addRolesToGroup("group1",  true, "role1", "role1")
+      .addPermissionsToRole("role1", true, "collection=" + collection1.getName(),
+          "collection=" + collection1.getName());
+    policyFile.write(iniFile);
+    SearchPolicyFileBackend policy = new SearchPolicyFileBackend(initResource);
+    authzProvider = new LocalGroupResourceAuthorizationProvider(initResource, policy);
+    List<? extends Authorizable> authorizableHierarchy = ImmutableList.of(collection1);
+    Assert.assertTrue(authorizableHierarchy.toString(),
+        authzProvider.hasAccess(user1, authorizableHierarchy, actions));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/1824f780/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyEngineDFS.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyEngineDFS.java
b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyEngineDFS.java
new file mode 100644
index 0000000..a17c82f
--- /dev/null
+++ b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyEngineDFS.java
@@ -0,0 +1,81 @@
+/*
+ * 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.provider.search;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hdfs.MiniDFSCluster;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.provider.file.PolicyFile;
+import org.apache.sentry.provider.file.PolicyFiles;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+
+public class TestSearchPolicyEngineDFS extends AbstractTestSearchPolicyEngine {
+
+  private static MiniDFSCluster dfsCluster;
+  private static FileSystem fileSystem;
+  private static Path root;
+  private static Path etc;
+
+  @BeforeClass
+  public static void setupLocalClazz() throws IOException {
+    File baseDir = getBaseDir();
+    Assert.assertNotNull(baseDir);
+    File dfsDir = new File(baseDir, "dfs");
+    Assert.assertTrue(dfsDir.isDirectory() || dfsDir.mkdirs());
+    Configuration conf = new Configuration();
+    conf.set(MiniDFSCluster.HDFS_MINIDFS_BASEDIR, dfsDir.getPath());
+    dfsCluster = new MiniDFSCluster.Builder(conf).numDataNodes(2).build();
+    fileSystem = dfsCluster.getFileSystem();
+    root = new Path(fileSystem.getUri().toString());
+    etc = new Path(root, "/etc");
+    fileSystem.mkdirs(etc);
+  }
+
+  @AfterClass
+  public static void teardownLocalClazz() {
+    if(dfsCluster != null) {
+      dfsCluster.shutdown();
+    }
+  }
+
+  @Override
+  protected void  afterSetup() throws IOException {
+    fileSystem.delete(etc, true);
+    fileSystem.mkdirs(etc);
+    PolicyFiles.copyToDir(fileSystem, etc, "test-authz-provider.ini");
+    setPolicy(new SearchPolicyFileBackend(new Path(etc, "test-authz-provider.ini").toString()));
+  }
+
+  @Override
+  protected void beforeTeardown() throws IOException {
+    fileSystem.delete(etc, true);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/1824f780/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyEngineLocalFS.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyEngineLocalFS.java
b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyEngineLocalFS.java
new file mode 100644
index 0000000..d85051b
--- /dev/null
+++ b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyEngineLocalFS.java
@@ -0,0 +1,43 @@
+/*
+ * 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.provider.search;
+
+import java.io.File;
+import java.io.IOException;
+
+import junit.framework.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.provider.file.PolicyFiles;
+
+public class TestSearchPolicyEngineLocalFS extends AbstractTestSearchPolicyEngine {
+
+  @Override
+  protected void  afterSetup() throws IOException {
+    File baseDir = getBaseDir();
+    Assert.assertNotNull(baseDir);
+    Assert.assertTrue(baseDir.isDirectory() || baseDir.mkdirs());
+    PolicyFiles.copyToDir(baseDir, "test-authz-provider.ini");
+    setPolicy(new SearchPolicyFileBackend(new File(baseDir, "test-authz-provider.ini").getPath()));
+  }
+  @Override
+  protected void beforeTeardown() throws IOException {
+    File baseDir = getBaseDir();
+    Assert.assertNotNull(baseDir);
+    FileUtils.deleteQuietly(baseDir);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/1824f780/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyNegative.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyNegative.java
b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyNegative.java
new file mode 100644
index 0000000..665591a
--- /dev/null
+++ b/sentry-provider/sentry-provider-policy-search/src/test/java/org/apache/sentry/provider/search/TestSearchPolicyNegative.java
@@ -0,0 +1,111 @@
+/*
+ * 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.provider.search;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+import junit.framework.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.core.model.search.Collection;
+import org.apache.sentry.provider.common.PolicyEngine;
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+
+public class TestSearchPolicyNegative {
+
+  @SuppressWarnings("unused")
+  private static final Logger LOGGER = LoggerFactory
+      .getLogger(TestSearchPolicyNegative.class);
+
+  private File baseDir;
+  private File globalPolicyFile;
+  private File otherPolicyFile;
+
+  @Before
+  public void setup() {
+    baseDir = Files.createTempDir();
+    globalPolicyFile = new File(baseDir, "global.ini");
+    otherPolicyFile = new File(baseDir, "other.ini");
+  }
+
+  @After
+  public void teardown() {
+    if(baseDir != null) {
+      FileUtils.deleteQuietly(baseDir);
+    }
+  }
+
+  private void append(String from, File to) throws IOException {
+    Files.append(from + "\n", to, Charsets.UTF_8);
+  }
+
+  @Test
+  public void testPerDbFileException() throws Exception {
+    append("[databases]", globalPolicyFile);
+    append("other_group_db = " + otherPolicyFile.getPath(), globalPolicyFile);
+    append("[groups]", otherPolicyFile);
+    append("other_group = malicious_role", otherPolicyFile);
+    append("[roles]", otherPolicyFile);
+    append("malicious_role = collection=*", otherPolicyFile);
+    try {
+      PolicyEngine policy = new SearchPolicyFileBackend(globalPolicyFile.getPath());
+      Assert.fail("Excepted ConfigurationException");
+    } catch (ConfigurationException ce) {}
+  }
+
+  @Test
+  public void testCollectionRequiredInRole() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("group = malicious_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("malicious_role = action=query", globalPolicyFile);
+    PolicyEngine policy = new SearchPolicyFileBackend(globalPolicyFile.getPath());
+    ImmutableSet<String> permissions = policy.getPermissions(
+        Arrays.asList(new Authorizable[] {
+            new Collection("collection1"),
+    }), Lists.newArrayList("group")).get("group");
+    Assert.assertTrue(permissions.toString(), permissions.isEmpty());
+  }
+
+  @Test
+  public void testGroupIncorrect() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("group = malicious_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("malicious_role = collection=*", globalPolicyFile);
+    PolicyEngine policy = new SearchPolicyFileBackend(globalPolicyFile.getPath());
+    ImmutableSet<String> permissions = policy.getPermissions(
+        Arrays.asList(new Authorizable[] {
+            Collection.ALL
+    }), Lists.newArrayList("incorrectGroup")).get("incorrectGroup");
+    Assert.assertTrue(permissions.toString(), permissions.isEmpty());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/1824f780/sentry-provider/sentry-provider-policy-search/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-policy-search/src/test/resources/log4j.properties
b/sentry-provider/sentry-provider-policy-search/src/test/resources/log4j.properties
new file mode 100644
index 0000000..c41373c
--- /dev/null
+++ b/sentry-provider/sentry-provider-policy-search/src/test/resources/log4j.properties
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+# Define some default values that can be overridden by system properties.
+#
+# For testing, it may also be convenient to specify
+
+log4j.rootLogger=DEBUG,console
+
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d (%t) [%p - %l] %m%n
+
+log4j.logger.org.apache.hadoop.conf.Configuration=INFO

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/1824f780/sentry-provider/sentry-provider-policy-search/src/test/resources/test-authz-provider.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-policy-search/src/test/resources/test-authz-provider.ini
b/sentry-provider/sentry-provider-policy-search/src/test/resources/test-authz-provider.ini
new file mode 100644
index 0000000..8af8162
--- /dev/null
+++ b/sentry-provider/sentry-provider-policy-search/src/test/resources/test-authz-provider.ini
@@ -0,0 +1,31 @@
+# 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.
+
+[groups]
+manager = analyst_role, junior_analyst_role
+analyst = analyst_role
+jranalyst = junior_analyst_role
+admin = admin
+
+[roles]
+analyst_role = collection=purchases->action=update, \
+  collection=analyst1, \
+  collection=jranalyst1->action=*, \
+  collection=tmpcollection->action=update, \
+  collection=tmpcollection->action=query
+junior_analyst_role = collection=jranalyst1, collection=purchases_partial->action=query
+admin = collection=*


Mime
View raw message