sentry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From co...@apache.org
Subject [09/13] sentry git commit: SENTRY-999: Refactor the sentry to integrate with external components quickly (Colin Ma, reviewed by Dapeng Sun)
Date Fri, 22 Apr 2016 06:28:29 GMT
http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/policy/kafka/TestKafkaPolicyNegative.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/policy/kafka/TestKafkaPolicyNegative.java b/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/policy/kafka/TestKafkaPolicyNegative.java
new file mode 100644
index 0000000..fd33b31
--- /dev/null
+++ b/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/policy/kafka/TestKafkaPolicyNegative.java
@@ -0,0 +1,104 @@
+/*
+ * 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.policy.kafka;
+
+import java.io.File;
+import java.io.IOException;
+
+import junit.framework.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.ActiveRoleSet;
+import org.apache.sentry.policy.common.PolicyEngine;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
+
+public class TestKafkaPolicyNegative {
+  private File baseDir;
+  private File globalPolicyFile;
+
+  @Before
+  public void setup() {
+    baseDir = Files.createTempDir();
+    globalPolicyFile = new File(baseDir, "global.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 testauthorizedKafkaInPolicyFile() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("other_group = other_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("other_role = host=host1->topic=t1->action=read, host=host1->consumergroup=l1->action=read", globalPolicyFile);
+    PolicyEngine policy = KafkaPolicyTestUtil.createPolicyEngineForTest(globalPolicyFile.getPath());
+    //malicious_group has no privilege
+    ImmutableSet<String> permissions = policy.getAllPrivileges(Sets.newHashSet("malicious_group"), ActiveRoleSet.ALL);
+    Assert.assertTrue(permissions.toString(), permissions.isEmpty());
+    //other_group has two privileges
+    permissions = policy.getAllPrivileges(Sets.newHashSet("other_group"), ActiveRoleSet.ALL);
+    Assert.assertTrue(permissions.toString(), permissions.size() == 2);
+  }
+
+  @Test
+  public void testNoHostNameConfig() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("other_group = malicious_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("malicious_role = topic=t1->action=read", globalPolicyFile);
+    PolicyEngine policy = KafkaPolicyTestUtil.createPolicyEngineForTest(globalPolicyFile.getPath());
+    ImmutableSet<String> permissions = policy.getAllPrivileges(Sets.newHashSet("other_group"), ActiveRoleSet.ALL);
+    Assert.assertTrue(permissions.toString(), permissions.isEmpty());
+  }
+
+  @Test
+  public void testHostAllName() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("group = malicious_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("malicious_role = host=*->action=read", globalPolicyFile);
+    PolicyEngine policy = KafkaPolicyTestUtil.createPolicyEngineForTest(globalPolicyFile.getPath());
+    ImmutableSet<String> permissions = policy.getAllPrivileges(Sets.newHashSet("group"), ActiveRoleSet.ALL);
+    Assert.assertTrue(permissions.toString(), permissions.size() == 1);
+  }
+
+  @Test
+  public void testAll() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("group = malicious_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("malicious_role = *", globalPolicyFile);
+    PolicyEngine policy = KafkaPolicyTestUtil.createPolicyEngineForTest(globalPolicyFile.getPath());
+    ImmutableSet<String> permissions = policy.getAllPrivileges(Sets.newHashSet("group"), ActiveRoleSet.ALL);
+    Assert.assertTrue(permissions.toString(), permissions.isEmpty());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/policy/kafka/TestKafkaPrivilegeValidator.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/policy/kafka/TestKafkaPrivilegeValidator.java b/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/policy/kafka/TestKafkaPrivilegeValidator.java
new file mode 100644
index 0000000..ba66d43
--- /dev/null
+++ b/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/policy/kafka/TestKafkaPrivilegeValidator.java
@@ -0,0 +1,170 @@
+/*
+ * 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.policy.kafka;
+
+import junit.framework.Assert;
+
+import org.apache.sentry.core.common.validator.PrivilegeValidatorContext;
+import org.apache.sentry.core.model.kafka.validator.KafkaPrivilegeValidator;
+import org.apache.shiro.config.ConfigurationException;
+import org.junit.Test;
+
+public class TestKafkaPrivilegeValidator {
+  @Test
+  public void testOnlyHostResource() {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("host=host1"));
+    } catch (ConfigurationException ex) {
+      Assert.assertEquals(KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg, ex.getMessage());
+    }
+  }
+
+  @Test
+  public void testWithoutHostResource() throws Exception {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    testHostResourceIsChecked(kafkaPrivilegeValidator, "cluster=kafka-cluster->action=read");
+    testHostResourceIsChecked(kafkaPrivilegeValidator, "topic=t1->action=read");
+    testHostResourceIsChecked(kafkaPrivilegeValidator, "consumergroup=g1->action=read");
+  }
+
+  private void testHostResourceIsChecked(KafkaPrivilegeValidator kafkaPrivilegeValidator, String privilege) {
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext(privilege));
+      Assert.fail("Expected ConfigurationException");
+    } catch (ConfigurationException ex) {
+      Assert.assertEquals("Kafka privilege must begin with host authorizable.\n" + KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg, ex.getMessage());
+    }
+  }
+
+  @Test
+  public void testValidPrivileges() throws Exception {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("host=host1->cluster=kafka-cluster->action=read"));
+    } catch (ConfigurationException ex) {
+      Assert.fail("Not expected ConfigurationException");
+    }
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("host=host1->topic=t1->action=read"));
+    } catch (ConfigurationException ex) {
+      Assert.fail("Not expected ConfigurationException");
+    }
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("host=host1->consumergroup=g1->action=read"));
+    } catch (ConfigurationException ex) {
+      Assert.fail("Not expected ConfigurationException");
+    }
+  }
+
+  @Test
+  public void testInvalidHostResource() throws Exception {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("hhost=host1->cluster=kafka-cluster->action=read"));
+      Assert.fail("Expected ConfigurationException");
+    } catch (ConfigurationException ex) {
+    }
+  }
+
+  @Test
+  public void testInvalidClusterResource() throws Exception {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("host=host1->clluster=kafka-cluster->action=read"));
+      Assert.fail("Expected ConfigurationException");
+    } catch (ConfigurationException ex) {
+    }
+  }
+
+  @Test
+  public void testInvalidTopicResource() throws Exception {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("host=host1->ttopic=t1->action=read"));
+      Assert.fail("Expected ConfigurationException");
+    } catch (ConfigurationException ex) {
+    }
+  }
+
+  @Test
+  public void testInvalidConsumerGroupResource() throws Exception {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("host=host1->coonsumergroup=g1->action=read"));
+      Assert.fail("Expected ConfigurationException");
+    } catch (ConfigurationException ex) {
+    }
+  }
+
+  @Test
+  public void testPrivilegeMustHaveExcatlyOneHost() {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("host=host1->host=host2->action=read"));
+      Assert.fail("Multiple Host resources are not allowed within a Kafka privilege.");
+    } catch (ConfigurationException ex) {
+      Assert.assertEquals("Host authorizable can be specified just once in a Kafka privilege.\n" + KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg, ex.getMessage());
+    }
+  }
+
+  @Test
+  public void testPrivilegeCanNotStartWithAction() {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("action=write->host=host1->topic=t1"));
+      Assert.fail("Kafka privilege can not start with an action.");
+    } catch (ConfigurationException ex) {
+      Assert.assertEquals("Kafka privilege can not start with an action.\n" + KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg, ex.getMessage());
+    }
+  }
+
+  @Test
+  public void testPrivilegeWithMoreParts() {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("host=host1->topic=t1->consumergroup=cg1->action=read"));
+      Assert.fail("Kafka privilege can have one Host authorizable, at most one non Host authorizable and one action.");
+    } catch (ConfigurationException ex) {
+      Assert.assertEquals(KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg, ex.getMessage());
+    }
+  }
+
+  @Test
+  public void testPrivilegeNotEndingWithAction() {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("host=host1->topic=t1->consumergroup=cg1"));
+      Assert.fail("Kafka privilege must end with a valid action.");
+    } catch (ConfigurationException ex) {
+      Assert.assertEquals("Kafka privilege must end with a valid action.\n" + KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg, ex.getMessage());
+    }
+  }
+
+  @Test
+  public void testPrivilegeNotEndingWithValidAction() {
+    KafkaPrivilegeValidator kafkaPrivilegeValidator = new KafkaPrivilegeValidator();
+    try {
+      kafkaPrivilegeValidator.validate(new PrivilegeValidatorContext("host=host1->topic=t1->action=bla"));
+      Assert.fail("Kafka privilege must end with a valid action.");
+    } catch (ConfigurationException ex) {
+      Assert.assertEquals("Kafka privilege must end with a valid action.\n" + KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg, ex.getMessage());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/privilege/kafka/TestKafkaWildcardPrivilege.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/privilege/kafka/TestKafkaWildcardPrivilege.java b/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/privilege/kafka/TestKafkaWildcardPrivilege.java
new file mode 100644
index 0000000..a616f67
--- /dev/null
+++ b/sentry-binding/sentry-binding-kafka/src/test/java/org/apache/sentry/privilege/kafka/TestKafkaWildcardPrivilege.java
@@ -0,0 +1,188 @@
+/*
+ * 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.privilege.kafka;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import org.apache.sentry.core.common.Model;
+import org.apache.sentry.core.common.utils.KeyValue;
+import org.apache.sentry.core.common.utils.SentryConstants;
+import org.apache.sentry.core.model.kafka.KafkaActionConstant;
+import org.apache.sentry.core.model.kafka.KafkaPrivilegeModel;
+import org.apache.sentry.policy.common.CommonPrivilege;
+import org.apache.sentry.policy.common.Privilege;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestKafkaWildcardPrivilege {
+
+  private Model kafkaPrivilegeModel;
+
+  private static final CommonPrivilege KAFKA_HOST1_ALL =
+      create(new KeyValue("HOST", "host1"), new KeyValue("action", KafkaActionConstant.ALL));
+  private static final CommonPrivilege KAFKA_HOST1_READ =
+      create(new KeyValue("HOST", "host1"), new KeyValue("action", KafkaActionConstant.READ));
+  private static final CommonPrivilege KAFKA_HOST1_WRITE =
+      create(new KeyValue("HOST", "host1"), new KeyValue("action", KafkaActionConstant.WRITE));
+
+  private static final CommonPrivilege KAFKA_HOST1_TOPIC1_ALL =
+      create(new KeyValue("HOST", "host1"), new KeyValue("TOPIC", "topic1"), new KeyValue("action", KafkaActionConstant.ALL));
+  private static final CommonPrivilege KAFKA_HOST1_TOPIC1_READ =
+      create(new KeyValue("HOST", "host1"), new KeyValue("TOPIC", "topic1"), new KeyValue("action", KafkaActionConstant.READ));
+  private static final CommonPrivilege KAFKA_HOST1_TOPIC1_WRITE =
+      create(new KeyValue("HOST", "host1"), new KeyValue("TOPIC", "topic1"), new KeyValue("action", KafkaActionConstant.WRITE));
+
+  private static final CommonPrivilege KAFKA_HOST1_CLUSTER1_ALL =
+      create(new KeyValue("HOST", "host1"), new KeyValue("CLUSTER", "cluster1"), new KeyValue("action", KafkaActionConstant.ALL));
+  private static final CommonPrivilege KAFKA_HOST1_CLUSTER1_READ =
+      create(new KeyValue("HOST", "host1"), new KeyValue("CLUSTER", "cluster1"), new KeyValue("action", KafkaActionConstant.READ));
+  private static final CommonPrivilege KAFKA_HOST1_CLUSTER1_WRITE =
+      create(new KeyValue("HOST", "host1"), new KeyValue("CLUSTER", "cluster1"), new KeyValue("action", KafkaActionConstant.WRITE));
+
+  private static final CommonPrivilege KAFKA_HOST1_GROUP1_ALL =
+      create(new KeyValue("HOST", "host1"), new KeyValue("GROUP", "cgroup1"), new KeyValue("action", KafkaActionConstant.ALL));
+  private static final CommonPrivilege KAFKA_HOST1_GROUP1_READ =
+      create(new KeyValue("HOST", "host1"), new KeyValue("GROUP", "cgroup1"), new KeyValue("action", KafkaActionConstant.READ));
+  private static final CommonPrivilege KAFKA_HOST1_GROUP1_WRITE =
+      create(new KeyValue("HOST", "host1"), new KeyValue("GROUP", "cgroup1"), new KeyValue("action", KafkaActionConstant.WRITE));
+
+  @Before
+  public void prepareData() {
+    kafkaPrivilegeModel = KafkaPrivilegeModel.getInstance();
+  }
+
+  @Test
+  public void testSimpleAction() throws Exception {
+    //host
+    assertFalse(KAFKA_HOST1_WRITE.implies(KAFKA_HOST1_READ, kafkaPrivilegeModel));
+    assertFalse(KAFKA_HOST1_READ.implies(KAFKA_HOST1_WRITE, kafkaPrivilegeModel));
+    //consumer group
+    assertFalse(KAFKA_HOST1_GROUP1_WRITE.implies(KAFKA_HOST1_GROUP1_READ, kafkaPrivilegeModel));
+    assertFalse(KAFKA_HOST1_GROUP1_READ.implies(KAFKA_HOST1_GROUP1_WRITE, kafkaPrivilegeModel));
+    //topic
+    assertFalse(KAFKA_HOST1_TOPIC1_READ.implies(KAFKA_HOST1_TOPIC1_WRITE, kafkaPrivilegeModel));
+    assertFalse(KAFKA_HOST1_TOPIC1_WRITE.implies(KAFKA_HOST1_TOPIC1_READ, kafkaPrivilegeModel));
+    //cluster
+    assertFalse(KAFKA_HOST1_CLUSTER1_READ.implies(KAFKA_HOST1_CLUSTER1_WRITE, kafkaPrivilegeModel));
+    assertFalse(KAFKA_HOST1_CLUSTER1_WRITE.implies(KAFKA_HOST1_CLUSTER1_READ, kafkaPrivilegeModel));
+  }
+
+  @Test
+  public void testShorterThanRequest() throws Exception {
+    //topic
+    assertTrue(KAFKA_HOST1_ALL.implies(KAFKA_HOST1_TOPIC1_ALL, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_ALL.implies(KAFKA_HOST1_TOPIC1_READ, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_ALL.implies(KAFKA_HOST1_TOPIC1_WRITE, kafkaPrivilegeModel));
+
+    assertFalse(KAFKA_HOST1_WRITE.implies(KAFKA_HOST1_READ, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_READ.implies(KAFKA_HOST1_TOPIC1_READ, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_WRITE.implies(KAFKA_HOST1_TOPIC1_WRITE, kafkaPrivilegeModel));
+
+    //cluster
+    assertTrue(KAFKA_HOST1_ALL.implies(KAFKA_HOST1_CLUSTER1_ALL, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_ALL.implies(KAFKA_HOST1_CLUSTER1_READ, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_ALL.implies(KAFKA_HOST1_CLUSTER1_WRITE, kafkaPrivilegeModel));
+
+    assertTrue(KAFKA_HOST1_READ.implies(KAFKA_HOST1_CLUSTER1_READ, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_WRITE.implies(KAFKA_HOST1_CLUSTER1_WRITE, kafkaPrivilegeModel));
+
+    //consumer group
+    assertTrue(KAFKA_HOST1_ALL.implies(KAFKA_HOST1_GROUP1_ALL, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_ALL.implies(KAFKA_HOST1_GROUP1_READ, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_ALL.implies(KAFKA_HOST1_GROUP1_WRITE, kafkaPrivilegeModel));
+
+    assertTrue(KAFKA_HOST1_READ.implies(KAFKA_HOST1_GROUP1_READ, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_WRITE.implies(KAFKA_HOST1_GROUP1_WRITE, kafkaPrivilegeModel));
+  }
+
+  @Test
+  public void testActionAll() throws Exception {
+    //host
+    assertTrue(KAFKA_HOST1_ALL.implies(KAFKA_HOST1_READ, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_ALL.implies(KAFKA_HOST1_WRITE, kafkaPrivilegeModel));
+
+    //topic
+    assertTrue(KAFKA_HOST1_TOPIC1_ALL.implies(KAFKA_HOST1_TOPIC1_READ, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_TOPIC1_ALL.implies(KAFKA_HOST1_TOPIC1_WRITE, kafkaPrivilegeModel));
+
+    //cluster
+    assertTrue(KAFKA_HOST1_CLUSTER1_ALL.implies(KAFKA_HOST1_CLUSTER1_READ, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_CLUSTER1_ALL.implies(KAFKA_HOST1_CLUSTER1_WRITE, kafkaPrivilegeModel));
+
+    //consumer group
+    assertTrue(KAFKA_HOST1_GROUP1_ALL.implies(KAFKA_HOST1_GROUP1_READ, kafkaPrivilegeModel));
+    assertTrue(KAFKA_HOST1_GROUP1_ALL.implies(KAFKA_HOST1_GROUP1_WRITE, kafkaPrivilegeModel));
+  }
+
+  @Test
+  public void testUnexpected() throws Exception {
+    Privilege p = new Privilege() {
+      @Override
+      public boolean implies(Privilege p, Model model) {
+        return false;
+      }
+    };
+    Privilege topic1 = create(new KeyValue("HOST", "host"), new KeyValue("TOPIC", "topic1"));
+    assertFalse(topic1.implies(null, kafkaPrivilegeModel));
+    assertFalse(topic1.implies(p, kafkaPrivilegeModel));
+    assertFalse(topic1.equals(null));
+    assertFalse(topic1.equals(p));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testNullString() throws Exception {
+    System.out.println(create((String)null));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyString() throws Exception {
+    System.out.println(create(""));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyKey() throws Exception {
+    System.out.println(create(SentryConstants.KV_JOINER.join("", "host1")));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyValue() throws Exception {
+    System.out.println(create(SentryConstants.KV_JOINER.join("HOST", "")));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyPart() throws Exception {
+    System.out.println(create(SentryConstants.AUTHORIZABLE_JOINER.
+        join(SentryConstants.KV_JOINER.join("HOST", "host1"), "")));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testOnlySeperators() throws Exception {
+    System.out.println(create(SentryConstants.AUTHORIZABLE_JOINER.
+        join(SentryConstants.KV_SEPARATOR, SentryConstants.KV_SEPARATOR,
+        SentryConstants.KV_SEPARATOR)));
+  }
+
+  static CommonPrivilege create(KeyValue... keyValues) {
+    return create(SentryConstants.AUTHORIZABLE_JOINER.join(keyValues));
+
+  }
+  static CommonPrivilege create(String s) {
+    return new CommonPrivilege(s);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-kafka/src/test/resources/kafka-policy-test-authz-provider.ini
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-kafka/src/test/resources/kafka-policy-test-authz-provider.ini b/sentry-binding/sentry-binding-kafka/src/test/resources/kafka-policy-test-authz-provider.ini
new file mode 100644
index 0000000..1951aba
--- /dev/null
+++ b/sentry-binding/sentry-binding-kafka/src/test/resources/kafka-policy-test-authz-provider.ini
@@ -0,0 +1,38 @@
+# 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]
+admin_group = admin_all
+subadmin_group = admin_host1
+consumer_group0 = consumer_t1_all
+consumer_group1 = consumer_t1_host1
+consumer_group2 = consumer_t2_host2
+producer_group0 = producer_t1_all
+producer_group1 = producer_t1_host1
+producer_group2 = producer_t2_host2
+consumer_producer_group0 = consumer_producer_t1
+
+[roles]
+admin_all = host=*->action=all
+admin_host1 = host=host1->action=all
+consumer_t1_all = host=*->topic=t1->action=read
+consumer_t1_host1 = host=host1->topic=t1->action=read
+consumer_t2_host2 = host=host2->topic=t2->action=read
+producer_t1_all = host=*->topic=t1->action=write
+producer_t1_host1 = host=host1->topic=t1->action=write
+producer_t2_host2 = host=host2->topic=t2->action=write
+consumer_producer_t1 = host=host1->topic=t1->action=all

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-kafka/src/test/resources/sentry-site.xml
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-kafka/src/test/resources/sentry-site.xml b/sentry-binding/sentry-binding-kafka/src/test/resources/sentry-site.xml
index 69ce5a7..6383481 100644
--- a/sentry-binding/sentry-binding-kafka/src/test/resources/sentry-site.xml
+++ b/sentry-binding/sentry-binding-kafka/src/test/resources/sentry-site.xml
@@ -32,7 +32,7 @@
   </property>
   <property>
     <name>sentry.kafka.policy.engine</name>
-    <value>org.apache.sentry.policy.kafka.SimpleKafkaPolicyEngine</value>
+    <value>org.apache.sentry.policy.engine.common.CommonPolicyEngine</value>
   </property>
   <property>
     <name>sentry.kafka.provider.backend</name>

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/pom.xml b/sentry-binding/sentry-binding-solr/pom.xml
index 3927188..a63a600 100644
--- a/sentry-binding/sentry-binding-solr/pom.xml
+++ b/sentry-binding/sentry-binding-solr/pom.xml
@@ -56,10 +56,6 @@ limitations under the License.
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache.sentry</groupId>
-      <artifactId>sentry-policy-search</artifactId>
-    </dependency>
-    <dependency>
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-common</artifactId>
       <scope>provided</scope>

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/authz/SolrAuthzBinding.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/authz/SolrAuthzBinding.java b/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/authz/SolrAuthzBinding.java
index a6d6c8b..24e5172 100644
--- a/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/authz/SolrAuthzBinding.java
+++ b/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/authz/SolrAuthzBinding.java
@@ -36,15 +36,18 @@ import org.apache.sentry.binding.solr.conf.SolrAuthzConf;
 import org.apache.sentry.binding.solr.conf.SolrAuthzConf.AuthzConfVars;
 import org.apache.sentry.core.common.Action;
 import org.apache.sentry.core.common.ActiveRoleSet;
+import org.apache.sentry.core.common.Model;
 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.core.model.search.SearchPrivilegeModel;
 import org.apache.sentry.policy.common.PolicyEngine;
 import org.apache.sentry.provider.common.AuthorizationComponent;
 import org.apache.sentry.provider.common.AuthorizationProvider;
 import org.apache.sentry.provider.common.GroupMappingService;
 import org.apache.sentry.provider.common.HadoopGroupResourceAuthorizationProvider;
 import org.apache.sentry.provider.common.ProviderBackend;
+import org.apache.sentry.provider.common.ProviderBackendContext;
 import org.apache.sentry.provider.db.generic.SentryGenericProviderBackend;
 import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
 import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
@@ -65,6 +68,7 @@ public class SolrAuthzBinding {
   public static final String KERBEROS_ENABLED = "solr.hdfs.security.kerberos.enabled";
   public static final String KERBEROS_KEYTAB = "solr.hdfs.security.kerberos.keytabfile";
   public static final String KERBEROS_PRINCIPAL = "solr.hdfs.security.kerberos.principal";
+  private static final String SOLR_POLICY_ENGINE_OLD = "org.apache.sentry.policy.search.SimpleSearchPolicyEngine";
   private static final String kerberosEnabledProp = Strings.nullToEmpty(System.getProperty(KERBEROS_ENABLED)).trim();
   private static final String keytabProp = Strings.nullToEmpty(System.getProperty(KERBEROS_KEYTAB)).trim();
   private static final String principalProp = Strings.nullToEmpty(System.getProperty(KERBEROS_PRINCIPAL)).trim();
@@ -94,14 +98,19 @@ public class SolrAuthzBinding {
     String resourceName =
         authzConf.get(AuthzConfVars.AUTHZ_PROVIDER_RESOURCE.getVar());
     String providerBackendName =
-      authzConf.get(AuthzConfVars.AUTHZ_PROVIDER_BACKEND.getVar());
+        authzConf.get(AuthzConfVars.AUTHZ_PROVIDER_BACKEND.getVar());
     String policyEngineName =
-      authzConf.get(AuthzConfVars.AUTHZ_POLICY_ENGINE.getVar());
+        authzConf.get(AuthzConfVars.AUTHZ_POLICY_ENGINE.getVar(), AuthzConfVars.AUTHZ_POLICY_ENGINE.getDefault());
     String serviceName = authzConf.get(SENTRY_SEARCH_SERVICE_KEY, SENTRY_SEARCH_SERVICE_DEFAULT);
 
+    // for the backward compatibility
+    if (SOLR_POLICY_ENGINE_OLD.equals(policyEngineName)) {
+      policyEngineName = AuthzConfVars.AUTHZ_POLICY_ENGINE.getDefault();
+    }
+
     LOG.debug("Using authorization provider " + authProviderName +
-      " with resource " + resourceName + ", policy engine "
-      + policyEngineName + ", provider backend " + providerBackendName);
+        " with resource " + resourceName + ", policy engine "
+        + policyEngineName + ", provider backend " + providerBackendName);
     // load the provider backend class
     if (kerberosEnabledProp.equalsIgnoreCase("true")) {
       initKerberos(keytabProp, principalProp);
@@ -118,11 +127,11 @@ public class SolrAuthzBinding {
       providerBackendName = SentryGenericProviderBackend.class.getName();
     }
     Constructor<?> providerBackendConstructor =
-      Class.forName(providerBackendName).getDeclaredConstructor(Configuration.class, String.class);
+        Class.forName(providerBackendName).getDeclaredConstructor(Configuration.class, String.class);
     providerBackendConstructor.setAccessible(true);
 
     providerBackend =
-      (ProviderBackend) providerBackendConstructor.newInstance(new Object[] {authzConf, resourceName});
+        (ProviderBackend) providerBackendConstructor.newInstance(new Object[] {authzConf, resourceName});
 
     if (providerBackend instanceof SentryGenericProviderBackend) {
       ((SentryGenericProviderBackend) providerBackend)
@@ -130,12 +139,18 @@ public class SolrAuthzBinding {
       ((SentryGenericProviderBackend) providerBackend).setServiceName(serviceName);
     }
 
+    // Create backend context
+    ProviderBackendContext context = new ProviderBackendContext();
+    context.setAllowPerDatabase(false);
+    context.setValidators(SearchPrivilegeModel.getInstance().getPrivilegeValidators());
+    providerBackend.initialize(context);
+
     // load the policy engine class
     Constructor<?> policyConstructor =
-      Class.forName(policyEngineName).getDeclaredConstructor(ProviderBackend.class);
+        Class.forName(policyEngineName).getDeclaredConstructor(ProviderBackend.class);
     policyConstructor.setAccessible(true);
     PolicyEngine policyEngine =
-      (PolicyEngine) policyConstructor.newInstance(new Object[] {providerBackend});
+        (PolicyEngine) policyConstructor.newInstance(new Object[] {providerBackend});
 
     // if unset, set the hadoop auth provider to use new groups, so we don't
     // conflict with the group mappings that may already be set up
@@ -145,9 +160,11 @@ public class SolrAuthzBinding {
 
     // load the authz provider class
     Constructor<?> constrctor =
-      Class.forName(authProviderName).getDeclaredConstructor(Configuration.class, String.class, PolicyEngine.class);
+      Class.forName(authProviderName).getDeclaredConstructor(Configuration.class,
+              String.class, PolicyEngine.class, Model.class);
     constrctor.setAccessible(true);
-    return (AuthorizationProvider) constrctor.newInstance(new Object[] {authzConf, resourceName, policyEngine});
+    return (AuthorizationProvider) constrctor.newInstance(new Object[] {authzConf, resourceName,
+            policyEngine, SearchPrivilegeModel.getInstance()});
   }
 
 

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/conf/SolrAuthzConf.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/conf/SolrAuthzConf.java b/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/conf/SolrAuthzConf.java
index 227f75e..b31f4fa 100644
--- a/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/conf/SolrAuthzConf.java
+++ b/sentry-binding/sentry-binding-solr/src/main/java/org/apache/sentry/binding/solr/conf/SolrAuthzConf.java
@@ -33,7 +33,7 @@ public class SolrAuthzConf extends Configuration {
       "org.apache.sentry.provider.common.HadoopGroupResourceAuthorizationProvider"),
     AUTHZ_PROVIDER_RESOURCE("sentry.solr.provider.resource", ""),
     AUTHZ_PROVIDER_BACKEND("sentry.solr.provider.backend", "org.apache.sentry.provider.file.SimpleFileProviderBackend"),
-    AUTHZ_POLICY_ENGINE("sentry.solr.policy.engine", "org.apache.sentry.policy.search.SimpleSearchPolicyEngine");
+    AUTHZ_POLICY_ENGINE("sentry.solr.policy.engine", "org.apache.sentry.policy.engine.common.CommonPolicyEngine");
 
     private final String varName;
     private final String defaultVal;

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/AbstractTestSearchPolicyEngine.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/AbstractTestSearchPolicyEngine.java b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/AbstractTestSearchPolicyEngine.java
new file mode 100644
index 0000000..3df6ecf
--- /dev/null
+++ b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/AbstractTestSearchPolicyEngine.java
@@ -0,0 +1,129 @@
+/*
+ * 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.policy.solr;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.ActiveRoleSet;
+import org.apache.sentry.policy.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.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;
+
+  @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.getPrivileges(set("manager"), ActiveRoleSet.ALL))
+        .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.getPrivileges(set("analyst"), ActiveRoleSet.ALL))
+        .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.getPrivileges(set("jranalyst"), ActiveRoleSet.ALL))
+        .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.getPrivileges(set("admin"), ActiveRoleSet.ALL))
+        .toString());
+  }
+
+  private static Set<String> set(String... values) {
+    return Sets.newHashSet(values);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/SearchPolicyTestUtil.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/SearchPolicyTestUtil.java b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/SearchPolicyTestUtil.java
new file mode 100644
index 0000000..e198b5c
--- /dev/null
+++ b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/SearchPolicyTestUtil.java
@@ -0,0 +1,45 @@
+/*
+ * 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.policy.solr;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.core.model.search.SearchPrivilegeModel;
+import org.apache.sentry.policy.common.PolicyEngine;
+import org.apache.sentry.policy.engine.common.CommonPolicyEngine;
+import org.apache.sentry.provider.common.ProviderBackend;
+import org.apache.sentry.provider.common.ProviderBackendContext;
+import org.apache.sentry.provider.file.SimpleFileProviderBackend;
+
+import java.io.IOException;
+
+public class SearchPolicyTestUtil {
+
+  public static PolicyEngine createPolicyEngineForTest(String resource) throws IOException {
+
+    ProviderBackend providerBackend = new SimpleFileProviderBackend(new Configuration(), resource);
+
+    // create backendContext
+    ProviderBackendContext context = new ProviderBackendContext();
+    context.setAllowPerDatabase(false);
+    context.setValidators(SearchPrivilegeModel.getInstance().getPrivilegeValidators());
+    // initialize the backend with the context
+    providerBackend.initialize(context);
+
+
+    return new CommonPolicyEngine(providerBackend);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestCollectionRequiredInRole.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestCollectionRequiredInRole.java b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestCollectionRequiredInRole.java
new file mode 100644
index 0000000..76211dd
--- /dev/null
+++ b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestCollectionRequiredInRole.java
@@ -0,0 +1,64 @@
+/*
+ * 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.policy.solr;
+
+import org.junit.Assert;
+
+import org.apache.sentry.core.common.validator.PrivilegeValidatorContext;
+import org.apache.sentry.core.model.search.validator.CollectionRequiredInPrivilege;
+import org.apache.shiro.config.ConfigurationException;
+import org.junit.Test;
+
+public class TestCollectionRequiredInRole {
+
+  @Test
+  public void testEmptyRole() throws Exception {
+    CollectionRequiredInPrivilege collRequiredInRole = new CollectionRequiredInPrivilege();
+
+    // check no db
+    try {
+      collRequiredInRole.validate(new PrivilegeValidatorContext("index=index1"));
+      Assert.fail("Expected ConfigurationException");
+    } catch (ConfigurationException e) {
+      // expected
+    }
+
+    // check with db
+    try {
+      collRequiredInRole.validate(new PrivilegeValidatorContext("db1","index=index2"));
+      Assert.fail("Expected ConfigurationException");
+    } catch (ConfigurationException e) {
+      // expected
+    }
+  }
+
+  @Test
+  public void testCollectionWithoutAction() throws Exception {
+    CollectionRequiredInPrivilege collRequiredInRole = new CollectionRequiredInPrivilege();
+    collRequiredInRole.validate(new PrivilegeValidatorContext("collection=nodb"));
+    collRequiredInRole.validate(new PrivilegeValidatorContext("db2","collection=db"));
+  }
+
+  @Test
+  public void testCollectionWithAction() throws Exception {
+    CollectionRequiredInPrivilege collRequiredInRole = new CollectionRequiredInPrivilege();
+    collRequiredInRole.validate(new PrivilegeValidatorContext(null,"collection=nodb->action=query"));
+    collRequiredInRole.validate(new PrivilegeValidatorContext("db2","collection=db->action=update"));
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchAuthorizationProviderGeneralCases.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchAuthorizationProviderGeneralCases.java b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchAuthorizationProviderGeneralCases.java
new file mode 100644
index 0000000..6f7f07a
--- /dev/null
+++ b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchAuthorizationProviderGeneralCases.java
@@ -0,0 +1,193 @@
+/*
+ * 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.policy.solr;
+
+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 com.google.common.collect.Sets;
+import junit.framework.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.Action;
+import org.apache.sentry.core.common.ActiveRoleSet;
+import org.apache.sentry.core.common.Authorizable;
+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.core.model.search.SearchPrivilegeModel;
+import org.apache.sentry.provider.common.GroupMappingService;
+import org.apache.sentry.provider.common.ResourceAuthorizationProvider;
+import org.apache.sentry.provider.file.HadoopGroupResourceAuthorizationProvider;
+import org.apache.sentry.provider.file.PolicyFiles;
+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 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, "solr-policy-test-authz-provider.ini");
+    authzProvider = new HadoopGroupResourceAuthorizationProvider(
+            SearchPolicyTestUtil.createPolicyEngineForTest(new File(baseDir, "solr-policy-test-authz-provider.ini").getPath()),
+        new MockGroupMappingServiceProvider(USER_TO_GROUP_MAP), SearchPrivilegeModel.getInstance());
+
+  }
+
+  @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, ActiveRoleSet.ALL));
+    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);
+  }
+
+  public class MockGroupMappingServiceProvider implements GroupMappingService {
+    private final Multimap<String, String> userToGroupMap;
+
+    public MockGroupMappingServiceProvider(Multimap<String, String> userToGroupMap) {
+      this.userToGroupMap = userToGroupMap;
+    }
+
+    @Override
+    public Set<String> getGroups(String user) {
+      return Sets.newHashSet(userToGroupMap.get(user));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchAuthorizationProviderSpecialCases.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchAuthorizationProviderSpecialCases.java b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchAuthorizationProviderSpecialCases.java
new file mode 100644
index 0000000..371f361
--- /dev/null
+++ b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchAuthorizationProviderSpecialCases.java
@@ -0,0 +1,84 @@
+ /*
+ * 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.policy.solr;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.Action;
+import org.apache.sentry.core.common.ActiveRoleSet;
+import org.apache.sentry.core.common.Authorizable;
+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.core.model.search.SearchPrivilegeModel;
+import org.apache.sentry.policy.common.PolicyEngine;
+import org.apache.sentry.provider.common.AuthorizationProvider;
+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);
+    PolicyEngine policy = SearchPolicyTestUtil.createPolicyEngineForTest(initResource);
+    authzProvider = new LocalGroupResourceAuthorizationProvider(initResource, policy, SearchPrivilegeModel.getInstance());
+    List<? extends Authorizable> authorizableHierarchy = ImmutableList.of(collection1);
+    Assert.assertTrue(authorizableHierarchy.toString(),
+        authzProvider.hasAccess(user1, authorizableHierarchy, actions, ActiveRoleSet.ALL));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchModelAuthorizables.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchModelAuthorizables.java b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchModelAuthorizables.java
new file mode 100644
index 0000000..e7da13a
--- /dev/null
+++ b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchModelAuthorizables.java
@@ -0,0 +1,54 @@
+/*
+ * 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.policy.solr;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+import org.apache.sentry.core.model.search.Collection;
+import org.apache.sentry.core.model.search.SearchModelAuthorizables;
+import org.junit.Test;
+
+public class TestSearchModelAuthorizables {
+
+  @Test
+  public void testCollection() throws Exception {
+    Collection coll = (Collection) SearchModelAuthorizables.from("CoLleCtiOn=collection1");
+    assertEquals("collection1", coll.getName());
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testNoKV() throws Exception {
+    System.out.println(SearchModelAuthorizables.from("nonsense"));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyKey() throws Exception {
+    System.out.println(SearchModelAuthorizables.from("=v"));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyValue() throws Exception {
+    System.out.println(SearchModelAuthorizables.from("k="));
+  }
+
+  @Test
+  public void testNotAuthorizable() throws Exception {
+    assertNull(SearchModelAuthorizables.from("k=v"));
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchPolicyEngineDFS.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchPolicyEngineDFS.java b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchPolicyEngineDFS.java
new file mode 100644
index 0000000..3e3aa47
--- /dev/null
+++ b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchPolicyEngineDFS.java
@@ -0,0 +1,74 @@
+/*
+ * 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.policy.solr;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.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.provider.file.PolicyFiles;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+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, "solr-policy-test-authz-provider.ini");
+    setPolicy(SearchPolicyTestUtil.createPolicyEngineForTest(new Path(etc,
+        "solr-policy-test-authz-provider.ini").toString()));
+  }
+
+  @Override
+  protected void beforeTeardown() throws IOException {
+    fileSystem.delete(etc, true);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchPolicyEngineLocalFS.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchPolicyEngineLocalFS.java b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchPolicyEngineLocalFS.java
new file mode 100644
index 0000000..a7928b5
--- /dev/null
+++ b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/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.policy.solr;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.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, "solr-policy-test-authz-provider.ini");
+    setPolicy(SearchPolicyTestUtil.createPolicyEngineForTest(new File(baseDir, "solr-policy-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/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchPolicyNegative.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchPolicyNegative.java b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchPolicyNegative.java
new file mode 100644
index 0000000..20fee76
--- /dev/null
+++ b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/policy/solr/TestSearchPolicyNegative.java
@@ -0,0 +1,101 @@
+/*
+ * 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.policy.solr;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+
+import org.junit.Assert;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.ActiveRoleSet;
+import org.apache.sentry.policy.common.PolicyEngine;
+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.Sets;
+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 = some_role", otherPolicyFile);
+    append("[roles]", otherPolicyFile);
+    append("some_role = collection=c1", otherPolicyFile);
+    PolicyEngine policy = SearchPolicyTestUtil.createPolicyEngineForTest(globalPolicyFile.getPath());
+    Assert.assertEquals(Collections.emptySet(),
+        policy.getPrivileges(Sets.newHashSet("other_group"), ActiveRoleSet.ALL));
+  }
+
+  @Test
+  public void testCollectionRequiredInRole() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("group = some_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("some_role = action=query", globalPolicyFile);
+    PolicyEngine policy = SearchPolicyTestUtil.createPolicyEngineForTest(globalPolicyFile.getPath());
+    ImmutableSet<String> permissions = policy.getPrivileges(Sets.newHashSet("group"), ActiveRoleSet.ALL);
+    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 = SearchPolicyTestUtil.createPolicyEngineForTest(globalPolicyFile.getPath());
+    ImmutableSet<String> permissions = policy.getPrivileges(Sets.newHashSet("incorrectGroup"), ActiveRoleSet.ALL);
+    Assert.assertTrue(permissions.toString(), permissions.isEmpty());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/privilege/solr/TestCommonPrivilegeForSearch.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/privilege/solr/TestCommonPrivilegeForSearch.java b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/privilege/solr/TestCommonPrivilegeForSearch.java
new file mode 100644
index 0000000..294091c
--- /dev/null
+++ b/sentry-binding/sentry-binding-solr/src/test/java/org/apache/sentry/privilege/solr/TestCommonPrivilegeForSearch.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.privilege.solr;
+
+import org.apache.sentry.core.common.Model;
+import org.apache.sentry.core.common.utils.KeyValue;
+import org.apache.sentry.core.common.utils.SentryConstants;
+import org.apache.sentry.core.model.search.SearchConstants;
+import org.apache.sentry.core.model.search.SearchPrivilegeModel;
+import org.apache.sentry.policy.common.CommonPrivilege;
+import org.apache.sentry.policy.common.Privilege;
+import org.junit.Before;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+public class TestCommonPrivilegeForSearch {
+
+  private Model searchPrivilegeModel;
+
+  private static final String ALL = SearchConstants.ALL;
+
+  @Before
+  public void prepareData() {
+    searchPrivilegeModel = SearchPrivilegeModel.getInstance();
+  }
+
+  @Test
+  public void testSimpleNoAction() throws Exception {
+    CommonPrivilege collection1 = create(new KeyValue("collection", "coll1"));
+    CommonPrivilege collection2 = create(new KeyValue("collection", "coll2"));
+    CommonPrivilege collection1Case = create(new KeyValue("colleCtIon", "coLl1"));
+
+    assertTrue(collection1.implies(collection1, searchPrivilegeModel));
+    assertTrue(collection2.implies(collection2, searchPrivilegeModel));
+    assertTrue(collection1.implies(collection1Case, searchPrivilegeModel));
+    assertTrue(collection1Case.implies(collection1, searchPrivilegeModel));
+
+    assertFalse(collection1.implies(collection2, searchPrivilegeModel));
+    assertFalse(collection1Case.implies(collection2, searchPrivilegeModel));
+    assertFalse(collection2.implies(collection1, searchPrivilegeModel));
+    assertFalse(collection2.implies(collection1Case, searchPrivilegeModel));
+  }
+
+  @Test
+  public void testSimpleAction() throws Exception {
+    CommonPrivilege query =
+            create(new KeyValue("collection", "coll1"), new KeyValue("action", "query"));
+    CommonPrivilege update =
+            create(new KeyValue("collection", "coll1"), new KeyValue("action", "update"));
+    CommonPrivilege queryCase =
+            create(new KeyValue("colleCtIon", "coLl1"), new KeyValue("AcTiOn", "QuERy"));
+
+    assertTrue(query.implies(query, searchPrivilegeModel));
+    assertTrue(update.implies(update, searchPrivilegeModel));
+    assertTrue(query.implies(queryCase, searchPrivilegeModel));
+    assertTrue(queryCase.implies(query, searchPrivilegeModel));
+
+    assertFalse(query.implies(update, searchPrivilegeModel));
+    assertFalse(queryCase.implies(update, searchPrivilegeModel));
+    assertFalse(update.implies(query, searchPrivilegeModel));
+    assertFalse(update.implies(queryCase, searchPrivilegeModel));
+  }
+
+  @Test
+  public void testRoleShorterThanRequest() throws Exception {
+    CommonPrivilege collection1 = create(new KeyValue("collection", "coll1"));
+    CommonPrivilege query =
+            create(new KeyValue("collection", "coll1"), new KeyValue("action", "query"));
+    CommonPrivilege update =
+            create(new KeyValue("collection", "coll1"), new KeyValue("action", "update"));
+    CommonPrivilege all =
+            create(new KeyValue("collection", "coll1"), new KeyValue("action", ALL));
+
+    assertTrue(collection1.implies(query, searchPrivilegeModel));
+    assertTrue(collection1.implies(update, searchPrivilegeModel));
+    assertTrue(collection1.implies(all, searchPrivilegeModel));
+
+    assertFalse(query.implies(collection1, searchPrivilegeModel));
+    assertFalse(update.implies(collection1, searchPrivilegeModel));
+    assertTrue(all.implies(collection1, searchPrivilegeModel));
+  }
+
+  @Test
+  public void testCollectionAll() throws Exception {
+    CommonPrivilege collectionAll = create(new KeyValue("collection", ALL));
+    CommonPrivilege collection1 = create(new KeyValue("collection", "coll1"));
+    assertTrue(collectionAll.implies(collection1, searchPrivilegeModel));
+    assertTrue(collection1.implies(collectionAll, searchPrivilegeModel));
+
+    CommonPrivilege allUpdate =
+            create(new KeyValue("collection", ALL), new KeyValue("action", "update"));
+    CommonPrivilege allQuery =
+            create(new KeyValue("collection", ALL), new KeyValue("action", "query"));
+    CommonPrivilege coll1Update =
+            create(new KeyValue("collection", "coll1"), new KeyValue("action", "update"));
+    CommonPrivilege coll1Query =
+            create(new KeyValue("collection", "coll1"), new KeyValue("action", "query"));
+    assertTrue(allUpdate.implies(coll1Update, searchPrivilegeModel));
+    assertTrue(allQuery.implies(coll1Query, searchPrivilegeModel));
+    assertTrue(coll1Update.implies(allUpdate, searchPrivilegeModel));
+    assertTrue(coll1Query.implies(allQuery, searchPrivilegeModel));
+    assertFalse(allUpdate.implies(coll1Query, searchPrivilegeModel));
+    assertFalse(coll1Update.implies(coll1Query, searchPrivilegeModel));
+    assertFalse(allQuery.implies(coll1Update, searchPrivilegeModel));
+    assertFalse(coll1Query.implies(allUpdate, searchPrivilegeModel));
+    assertFalse(allUpdate.implies(allQuery, searchPrivilegeModel));
+    assertFalse(allQuery.implies(allUpdate, searchPrivilegeModel));
+    assertFalse(coll1Update.implies(coll1Query, searchPrivilegeModel));
+    assertFalse(coll1Query.implies(coll1Update, searchPrivilegeModel));
+
+    // test different length paths
+    assertTrue(collectionAll.implies(allUpdate, searchPrivilegeModel));
+    assertTrue(collectionAll.implies(allQuery, searchPrivilegeModel));
+    assertTrue(collectionAll.implies(coll1Update, searchPrivilegeModel));
+    assertTrue(collectionAll.implies(coll1Query, searchPrivilegeModel));
+    assertFalse(allUpdate.implies(collectionAll, searchPrivilegeModel));
+    assertFalse(allQuery.implies(collectionAll, searchPrivilegeModel));
+    assertFalse(coll1Update.implies(collectionAll, searchPrivilegeModel));
+    assertFalse(coll1Query.implies(collectionAll, searchPrivilegeModel));
+  }
+
+  @Test
+  public void testActionAll() throws Exception {
+    CommonPrivilege coll1All =
+            create(new KeyValue("collection", "coll1"), new KeyValue("action", ALL));
+    CommonPrivilege coll1Update =
+            create(new KeyValue("collection", "coll1"), new KeyValue("action", "update"));
+    CommonPrivilege coll1Query =
+            create(new KeyValue("collection", "coll1"), new KeyValue("action", "query"));
+    assertTrue(coll1All.implies(coll1All, searchPrivilegeModel));
+    assertTrue(coll1All.implies(coll1Update, searchPrivilegeModel));
+    assertTrue(coll1All.implies(coll1Query, searchPrivilegeModel));
+    assertFalse(coll1Update.implies(coll1All, searchPrivilegeModel));
+    assertFalse(coll1Query.implies(coll1All, searchPrivilegeModel));
+
+    // test different lengths
+    CommonPrivilege coll1 =
+            create(new KeyValue("collection", "coll1"));
+    assertTrue(coll1All.implies(coll1, searchPrivilegeModel));
+    assertTrue(coll1.implies(coll1All, searchPrivilegeModel));
+  }
+
+  @Test
+  public void testUnexpected() throws Exception {
+    Privilege p = new Privilege() {
+      @Override
+      public boolean implies(Privilege p, Model m) {
+        return false;
+      }
+    };
+    Privilege collection1 = create(new KeyValue("collection", "coll1"));
+    assertFalse(collection1.implies(null, searchPrivilegeModel));
+    assertFalse(collection1.implies(p, searchPrivilegeModel));
+    assertFalse(collection1.equals(null));
+    assertFalse(collection1.equals(p));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testNullString() throws Exception {
+    System.out.println(create((String)null));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyString() throws Exception {
+    System.out.println(create(""));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyKey() throws Exception {
+    System.out.println(create(SentryConstants.KV_JOINER.join("collection", "")));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyValue() throws Exception {
+    System.out.println(create(SentryConstants.KV_JOINER.join("", "coll1")));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyPart() throws Exception {
+    System.out.println(create(SentryConstants.AUTHORIZABLE_JOINER.
+            join(SentryConstants.KV_JOINER.join("collection1", "coll1"), "")));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testOnlySeperators() throws Exception {
+    System.out.println(create(SentryConstants.AUTHORIZABLE_JOINER.
+            join(SentryConstants.KV_SEPARATOR, SentryConstants.KV_SEPARATOR,
+            SentryConstants.KV_SEPARATOR)));
+  }
+
+  static CommonPrivilege create(KeyValue... keyValues) {
+    return create(SentryConstants.AUTHORIZABLE_JOINER.join(keyValues));
+  }
+
+  static CommonPrivilege create(String s) {
+    return new CommonPrivilege(s);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-solr/src/test/resources/solr-policy-test-authz-provider.ini
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-solr/src/test/resources/solr-policy-test-authz-provider.ini b/sentry-binding/sentry-binding-solr/src/test/resources/solr-policy-test-authz-provider.ini
new file mode 100644
index 0000000..8af8162
--- /dev/null
+++ b/sentry-binding/sentry-binding-solr/src/test/resources/solr-policy-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=*

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-sqoop/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/pom.xml b/sentry-binding/sentry-binding-sqoop/pom.xml
index 73ddee8..732da26 100644
--- a/sentry-binding/sentry-binding-sqoop/pom.xml
+++ b/sentry-binding/sentry-binding-sqoop/pom.xml
@@ -59,21 +59,22 @@ limitations under the License.
       <artifactId>sentry-policy-common</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.apache.sentry</groupId>
-      <artifactId>sentry-policy-sqoop</artifactId>
-    </dependency>
-    <dependency>
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-common</artifactId>
       <scope>provided</scope>
     </dependency>
 	<dependency>
-        <groupId>org.apache.sqoop</groupId>
-        <artifactId>sqoop-common</artifactId>
+      <groupId>org.apache.sqoop</groupId>
+      <artifactId>sqoop-common</artifactId>
     </dependency>
 	<dependency>
-        <groupId>org.apache.sqoop</groupId>
-        <artifactId>sqoop-security</artifactId>
+      <groupId>org.apache.sqoop</groupId>
+      <artifactId>sqoop-security</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-minicluster</artifactId>
+      <scope>test</scope>
     </dependency>
   </dependencies>
 


Mime
View raw message