sentry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From co...@apache.org
Subject [08/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:28 GMT
http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopAuthBinding.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopAuthBinding.java b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopAuthBinding.java
index 8456031..731541d 100644
--- a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopAuthBinding.java
+++ b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopAuthBinding.java
@@ -25,14 +25,17 @@ import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.sentry.SentryUserException;
 import org.apache.sentry.core.common.ActiveRoleSet;
 import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.core.common.Model;
 import org.apache.sentry.core.common.Subject;
 import org.apache.sentry.core.model.sqoop.Server;
 import org.apache.sentry.core.model.sqoop.SqoopActionConstant;
 import org.apache.sentry.core.model.sqoop.SqoopActionFactory;
+import org.apache.sentry.core.model.sqoop.SqoopPrivilegeModel;
 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.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;
@@ -63,6 +66,7 @@ public class SqoopAuthBinding {
   private ProviderBackend providerBackend;
 
   private final SqoopActionFactory actionFactory = new SqoopActionFactory();
+  private final String SQOOP_POLICY_ENGINE_OLD = "org.apache.sentry.policy.sqoop.SimpleSqoopPolicyEngine";
 
   public SqoopAuthBinding(Configuration authConf, String serverName) throws Exception {
     this.authConf = authConf;
@@ -87,6 +91,12 @@ public class SqoopAuthBinding {
     String providerBackendName = authConf.get(AuthzConfVars.AUTHZ_PROVIDER_BACKEND.getVar(), AuthzConfVars.AUTHZ_PROVIDER_BACKEND.getDefault());
     String policyEngineName = authConf.get(AuthzConfVars.AUTHZ_POLICY_ENGINE.getVar(), AuthzConfVars.AUTHZ_POLICY_ENGINE.getDefault());
     String serviceName = authConf.get(AuthzConfVars.AUTHZ_SERVER_NAME.getVar());
+
+    // for the backward compatibility
+    if (SQOOP_POLICY_ENGINE_OLD.equals(policyEngineName)) {
+      policyEngineName = AuthzConfVars.AUTHZ_POLICY_ENGINE.getDefault();
+    }
+
     if (LOG.isDebugEnabled()) {
       LOG.debug("Using authorization provider " + authProviderName +
           " with resource " + resourceName + ", policy engine "
@@ -110,18 +120,26 @@ public class SqoopAuthBinding {
       ((SentryGenericProviderBackend) providerBackend).setServiceName(serviceName);
     }
 
+    // Create backend context
+    ProviderBackendContext context = new ProviderBackendContext();
+    context.setAllowPerDatabase(false);
+    context.setValidators(SqoopPrivilegeModel.getInstance().getPrivilegeValidators(serviceName));
+    providerBackend.initialize(context);
+
     //Instantiate the configured policyEngine
     Constructor<?> policyConstructor =
-        Class.forName(policyEngineName).getDeclaredConstructor(String.class, ProviderBackend.class);
+        Class.forName(policyEngineName).getDeclaredConstructor(ProviderBackend.class);
     policyConstructor.setAccessible(true);
     PolicyEngine policyEngine =
-        (PolicyEngine) policyConstructor.newInstance(new Object[] {sqoopServer.getName(), providerBackend});
+        (PolicyEngine) policyConstructor.newInstance(new Object[] {providerBackend});
 
     //Instantiate the configured authProvider
     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[] {authConf, resourceName, policyEngine});
+    return (AuthorizationProvider) constrctor.newInstance(new Object[] {authConf, resourceName,
+            policyEngine, SqoopPrivilegeModel.getInstance()});
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/conf/SqoopAuthConf.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/conf/SqoopAuthConf.java b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/conf/SqoopAuthConf.java
index 097e7f7..7836871 100644
--- a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/conf/SqoopAuthConf.java
+++ b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/conf/SqoopAuthConf.java
@@ -34,7 +34,7 @@ public class SqoopAuthConf extends Configuration {
     AUTHZ_PROVIDER_BACKEND(
         "sentry.sqoop.provider.backend",
         "org.apache.sentry.provider.db.generic.SentryGenericProviderBackend"),
-    AUTHZ_POLICY_ENGINE("sentry.sqoop.policy.engine","org.apache.sentry.policy.sqoop.SimpleSqoopPolicyEngine"),
+    AUTHZ_POLICY_ENGINE("sentry.sqoop.policy.engine","org.apache.sentry.policy.engine.common.CommonPolicyEngine"),
     AUTHZ_SERVER_NAME("sentry.sqoop.name", ""),
     AUTHZ_TESTING_MODE("sentry.sqoop.testing.mode", "false");
 

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/AbstractTestSqoopPolicyEngine.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/AbstractTestSqoopPolicyEngine.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/AbstractTestSqoopPolicyEngine.java
new file mode 100644
index 0000000..49b9bc1
--- /dev/null
+++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/AbstractTestSqoopPolicyEngine.java
@@ -0,0 +1,145 @@
+/*
+ * 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.sqoop;
+
+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 AbstractTestSqoopPolicyEngine {
+  private static final String OPERATOR_JDBC_CONNECTORS_READ = "server=server1->connector=generic-jdbc-connector->action=read";
+  private static final String OPERATOR_HDFS_CONNECTORS_READ = "server=server1->connector=hdfs-connector->action=read";
+  private static final String OPERATOR_KAFKA_CONNECTORS_READ = "server=server1->connector=kafka-connector->action=read";
+  private static final String OPERATOR_KITE_CONNECTORS_READ = "server=server1->connector=kite-connector->action=read";
+  private static final String ANALYST_JOBS_ALL = "server=server1->job=all->action=*";
+  private static final String OPERATOR_JOB1_READ = "server=server1->job=job1->action=read";
+  private static final String OPERATOR_JOB2_READ = "server=server1->job=job2->action=read";
+  private static final String ANALYST_LINKS_ALL = "server=server1->link=all->action=*";
+  private static final String OPERATOR_LINK1_READ = "server=server1->link=link1->action=read";
+  private static final String OPERATOR_LINK2_READ = "server=server1->link=link2->action=read";
+  private static final String ADMIN = "server=server1->action=*";
+
+  private PolicyEngine policy;
+  private static File baseDir;
+
+  protected String sqoopServerName = "server1";
+
+  @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 testDeveloper() throws Exception {
+    Set<String> expected = Sets.newTreeSet(Sets.newHashSet(
+        OPERATOR_JDBC_CONNECTORS_READ, OPERATOR_HDFS_CONNECTORS_READ,
+        OPERATOR_KAFKA_CONNECTORS_READ, OPERATOR_KITE_CONNECTORS_READ,
+        ANALYST_JOBS_ALL, ANALYST_LINKS_ALL));
+    Assert.assertEquals(expected.toString(),
+        Sets.newTreeSet(policy.getPrivileges(set("developer"), ActiveRoleSet.ALL))
+        .toString());
+  }
+
+  @Test
+  public void testAnalyst() throws Exception {
+    Set<String> expected = Sets.newTreeSet(Sets.newHashSet(ANALYST_JOBS_ALL, ANALYST_LINKS_ALL));
+    Assert.assertEquals(expected.toString(),
+        new TreeSet<String>(policy.getPrivileges(set("analyst"), ActiveRoleSet.ALL))
+        .toString());
+  }
+
+  @Test
+  public void testConnectorOperator() throws Exception {
+
+  }
+
+  @Test
+  public void testJobOperator() throws Exception {
+    Set<String> expected = Sets.newTreeSet(Sets
+        .newHashSet(OPERATOR_JOB1_READ,OPERATOR_JOB2_READ));
+    Assert.assertEquals(expected.toString(),
+        new TreeSet<String>(policy.getPrivileges(set("job1_2_operator"), ActiveRoleSet.ALL))
+        .toString());
+  }
+
+  @Test
+  public void testLinkOperator() throws Exception {
+    Set<String> expected = Sets.newTreeSet(Sets
+        .newHashSet(OPERATOR_LINK1_READ, OPERATOR_LINK2_READ));
+    Assert.assertEquals(expected.toString(),
+        new TreeSet<String>(policy.getPrivileges(set("link1_2_operator"), ActiveRoleSet.ALL))
+        .toString());
+  }
+
+  @Test
+  public void testAdmin() throws Exception {
+    Set<String> expected = Sets.newTreeSet(Sets.newHashSet(ADMIN));
+    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-sqoop/src/test/java/org/apache/sentry/policy/sqoop/SqoopPolicyTestUtil.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/SqoopPolicyTestUtil.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/SqoopPolicyTestUtil.java
new file mode 100644
index 0000000..bfd11e3
--- /dev/null
+++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/SqoopPolicyTestUtil.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.sqoop;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.core.model.sqoop.SqoopPrivilegeModel;
+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 SqoopPolicyTestUtil {
+
+  public static PolicyEngine createPolicyEngineForTest(String server, String resource) throws IOException {
+
+    ProviderBackend providerBackend = new SimpleFileProviderBackend(new Configuration(), resource);
+
+    // create backendContext
+    ProviderBackendContext context = new ProviderBackendContext();
+    context.setAllowPerDatabase(false);
+    context.setValidators(SqoopPrivilegeModel.getInstance().getPrivilegeValidators(server));
+    // 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-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestServerNameRequiredMatch.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestServerNameRequiredMatch.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestServerNameRequiredMatch.java
new file mode 100644
index 0000000..7cb0ae4
--- /dev/null
+++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestServerNameRequiredMatch.java
@@ -0,0 +1,57 @@
+/*
+ * 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.sqoop;
+
+import org.junit.Assert;
+
+import org.apache.sentry.core.common.validator.PrivilegeValidatorContext;
+import org.apache.sentry.core.model.sqoop.validator.ServerNameRequiredMatch;
+import org.apache.shiro.config.ConfigurationException;
+import org.junit.Test;
+
+public class TestServerNameRequiredMatch {
+  @Test
+  public void testWithoutServerName() {
+    ServerNameRequiredMatch serverNameMatch = new ServerNameRequiredMatch("server1");
+    try {
+      serverNameMatch.validate(new PrivilegeValidatorContext("connector=c1->action=read"));
+      Assert.fail("Expected ConfigurationException");
+    } catch (ConfigurationException ex) {
+    }
+  }
+  @Test
+  public void testServerNameNotMatch() throws Exception {
+    ServerNameRequiredMatch serverNameMatch = new ServerNameRequiredMatch("server1");
+    try {
+      serverNameMatch.validate(new PrivilegeValidatorContext("server=server2->connector=c1->action=read"));
+      Assert.fail("Expected ConfigurationException");
+    } catch (ConfigurationException ex) {
+    }
+  }
+  @Test
+  public void testServerNameMatch() throws Exception {
+    ServerNameRequiredMatch serverNameMatch = new ServerNameRequiredMatch("server1");
+    try {
+      serverNameMatch.validate(new PrivilegeValidatorContext("server=server1->connector=c1->action=read"));
+    } catch (ConfigurationException ex) {
+      Assert.fail("Not expected ConfigurationException");
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopAuthorizationProviderGeneralCases.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopAuthorizationProviderGeneralCases.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopAuthorizationProviderGeneralCases.java
new file mode 100644
index 0000000..7ce8881
--- /dev/null
+++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopAuthorizationProviderGeneralCases.java
@@ -0,0 +1,241 @@
+/*
+ * 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.sqoop;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+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.sqoop.Connector;
+import org.apache.sentry.core.model.sqoop.Job;
+import org.apache.sentry.core.model.sqoop.Link;
+import org.apache.sentry.core.model.sqoop.Server;
+import org.apache.sentry.core.model.sqoop.SqoopActionConstant;
+import org.apache.sentry.core.model.sqoop.SqoopActionFactory.SqoopAction;
+import org.apache.sentry.core.model.sqoop.SqoopPrivilegeModel;
+import org.apache.sentry.provider.common.GroupMappingService;
+import org.apache.sentry.provider.common.ResourceAuthorizationProvider;
+import org.apache.sentry.provider.common.HadoopGroupResourceAuthorizationProvider;
+import org.apache.sentry.provider.file.PolicyFiles;
+import org.junit.After;
+import org.junit.Test;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
+
+public class TestSqoopAuthorizationProviderGeneralCases {
+  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_DEVELOPER = new Subject("developer1");
+  private static final Subject SUB_ANALYST = new Subject("analyst1");
+  private static final Subject SUB_JOB_OPERATOR = new Subject("job_operator1");
+  private static final Subject SUB_LINK_OPERATOR = new Subject("link_operator1");
+  private static final Subject SUB_CONNECTOR_OPERATOR = new Subject("connector_operator1");
+
+
+
+  private static final Server server1 = new Server("server1");
+  private static final Connector jdbc_connector = new Connector("generic-jdbc-connector");
+  private static final Connector hdfs_connector = new Connector("hdfs-connector");
+  private static final Connector kafka_connector = new Connector("kafka-connector");
+  private static final Connector kite_connector = new Connector("kite-connector");
+  private static final Link link1 = new Link("link1");
+  private static final Link link2 = new Link("link2");
+  private static final Job job1 = new Job("job1");
+  private static final Job job2 = new Job("job2");
+
+  private static final SqoopAction ALL = new SqoopAction(SqoopActionConstant.ALL);
+  private static final SqoopAction READ = new SqoopAction(SqoopActionConstant.READ);
+  private static final SqoopAction WRITE = new SqoopAction(SqoopActionConstant.WRITE);
+
+  private static final String ADMIN = "admin";
+  private static final String DEVELOPER = "developer";
+  private static final String ANALYST = "analyst";
+  private static final String JOB_OPERATOR = "job1_2_operator";
+  private static final String LINK_OPERATOR ="link1_2_operator";
+  private static final String CONNECTOR_OPERATOR = "connectors_operator";
+
+  static {
+    USER_TO_GROUP_MAP.putAll(SUB_ADMIN.getName(), Arrays.asList(ADMIN));
+    USER_TO_GROUP_MAP.putAll(SUB_DEVELOPER.getName(), Arrays.asList(DEVELOPER));
+    USER_TO_GROUP_MAP.putAll(SUB_ANALYST.getName(), Arrays.asList(ANALYST));
+    USER_TO_GROUP_MAP.putAll(SUB_JOB_OPERATOR.getName(),Arrays.asList(JOB_OPERATOR));
+    USER_TO_GROUP_MAP.putAll(SUB_LINK_OPERATOR.getName(),Arrays.asList(LINK_OPERATOR));
+    USER_TO_GROUP_MAP.putAll(SUB_CONNECTOR_OPERATOR.getName(),Arrays.asList(CONNECTOR_OPERATOR));
+  }
+
+  private final ResourceAuthorizationProvider authzProvider;
+  private File baseDir;
+
+  public TestSqoopAuthorizationProviderGeneralCases() throws IOException {
+    baseDir = Files.createTempDir();
+    PolicyFiles.copyToDir(baseDir, "sqoop-policy-test-authz-provider.ini");
+    authzProvider = new HadoopGroupResourceAuthorizationProvider(
+        SqoopPolicyTestUtil.createPolicyEngineForTest(server1.getName(),
+        new File(baseDir, "sqoop-policy-test-authz-provider.ini").getPath()),
+        new MockGroupMappingServiceProvider(USER_TO_GROUP_MAP), SqoopPrivilegeModel.getInstance());
+  }
+
+  @After
+  public void teardown() {
+    if(baseDir != null) {
+      FileUtils.deleteQuietly(baseDir);
+    }
+  }
+
+  private void doTestResourceAuthorizationProvider(Subject subject, List<? extends Authorizable> authorizableHierarchy,
+      Set<? extends Action> actions, boolean expected) throws Exception {
+    Objects.ToStringHelper helper = Objects.toStringHelper("TestParameters");
+    helper.add("Subject", subject).add("authzHierarchy", authorizableHierarchy).add("action", actions);
+    Assert.assertEquals(helper.toString(), expected,
+        authzProvider.hasAccess(subject, authorizableHierarchy, actions, ActiveRoleSet.ALL));
+  }
+
+  @Test
+  public void testAdmin() throws Exception {
+    Set<? extends Action> allActions = Sets.newHashSet(ALL, READ, WRITE);
+    doTestResourceAuthorizationProvider(SUB_ADMIN, Arrays.asList(server1), allActions, true);
+    doTestResourceAuthorizationProvider(SUB_ADMIN, Arrays.asList(server1,hdfs_connector), allActions, true);
+    doTestResourceAuthorizationProvider(SUB_ADMIN, Arrays.asList(server1,jdbc_connector), allActions, true);
+    doTestResourceAuthorizationProvider(SUB_ADMIN, Arrays.asList(server1,kafka_connector), allActions, true);
+    doTestResourceAuthorizationProvider(SUB_ADMIN, Arrays.asList(server1,kite_connector), allActions, true);
+    doTestResourceAuthorizationProvider(SUB_ADMIN, Arrays.asList(server1,link1), allActions, true);
+    doTestResourceAuthorizationProvider(SUB_ADMIN, Arrays.asList(server1,link2), allActions, true);
+    doTestResourceAuthorizationProvider(SUB_ADMIN, Arrays.asList(server1,job1), allActions, true);
+    doTestResourceAuthorizationProvider(SUB_ADMIN, Arrays.asList(server1,job2), allActions, true);
+  }
+
+  @Test
+  public void testDeveloper() throws Exception {
+    Set<SqoopAction> allActions = Sets.newHashSet(ALL, READ, WRITE);
+    for (SqoopAction action : allActions) {
+      //developer only has the read action on all connectors
+      for (Connector connector : Sets.newHashSet(jdbc_connector, hdfs_connector, kafka_connector, kite_connector)) {
+        doTestResourceAuthorizationProvider(SUB_DEVELOPER, Arrays.asList(server1, connector), Sets.newHashSet(action), READ.equals(action));
+      }
+    }
+
+    for (Link link : Sets.newHashSet(link1, link2)) {
+      //developer has the all action on all links
+      doTestResourceAuthorizationProvider(SUB_DEVELOPER, Arrays.asList(server1, link), allActions, true);
+    }
+
+    for (Job job : Sets.newHashSet(job1,job2)) {
+      //developer has the all action on all jobs
+      doTestResourceAuthorizationProvider(SUB_DEVELOPER, Arrays.asList(server1, job), allActions, true);
+    }
+  }
+
+  @Test
+  public void testAnalyst() throws Exception {
+    Set<SqoopAction> allActions = Sets.newHashSet(ALL, READ, WRITE);
+    for (SqoopAction action : allActions) {
+      //analyst has not the any action on all connectors
+      for (Connector connector : Sets.newHashSet(jdbc_connector, hdfs_connector, kafka_connector, kite_connector)) {
+        doTestResourceAuthorizationProvider(SUB_ANALYST, Arrays.asList(server1, connector), Sets.newHashSet(action), false);
+      }
+    }
+
+    for (Link link : Sets.newHashSet(link1, link2)) {
+      //analyst has the all action on all links
+      doTestResourceAuthorizationProvider(SUB_ANALYST, Arrays.asList(server1, link), allActions, true);
+    }
+
+    for (Job job : Sets.newHashSet(job1,job2)) {
+      //analyst has the all action on all jobs
+      doTestResourceAuthorizationProvider(SUB_ANALYST, Arrays.asList(server1, job), allActions, true);
+    }
+  }
+
+  @Test
+  public void testJobOperator() throws Exception {
+    Set<SqoopAction> allActions = Sets.newHashSet(ALL, READ, WRITE);
+    for (SqoopAction action : allActions) {
+      for (Job job : Sets.newHashSet(job1,job2)) {
+        //Job operator has the read action on all jobs
+        doTestResourceAuthorizationProvider(SUB_JOB_OPERATOR, Arrays.asList(server1, job), Sets.newHashSet(action), READ.equals(action));
+      }
+      for (Link link : Sets.newHashSet(link1, link2)) {
+        doTestResourceAuthorizationProvider(SUB_JOB_OPERATOR, Arrays.asList(server1, link), Sets.newHashSet(action), false);
+      }
+      for (Connector connector : Sets.newHashSet(jdbc_connector, hdfs_connector, kafka_connector, kite_connector)) {
+        doTestResourceAuthorizationProvider(SUB_JOB_OPERATOR, Arrays.asList(server1, connector), Sets.newHashSet(action), false);
+      }
+    }
+  }
+
+  @Test
+  public void testLinkOperator() throws Exception {
+    Set<SqoopAction> allActions = Sets.newHashSet(ALL, READ, WRITE);
+    for (SqoopAction action : allActions) {
+      for (Link link : Sets.newHashSet(link1, link2)) {
+        //Link operator has the read action on all links
+        doTestResourceAuthorizationProvider(SUB_LINK_OPERATOR, Arrays.asList(server1, link), Sets.newHashSet(action), READ.equals(action));
+      }
+      for (Job job : Sets.newHashSet(job1,job2)) {
+        doTestResourceAuthorizationProvider(SUB_LINK_OPERATOR, Arrays.asList(server1, job), Sets.newHashSet(action), false);
+      }
+      for (Connector connector : Sets.newHashSet(jdbc_connector, hdfs_connector, kafka_connector, kite_connector)) {
+        doTestResourceAuthorizationProvider(SUB_LINK_OPERATOR, Arrays.asList(server1, connector), Sets.newHashSet(action), false);
+      }
+    }
+  }
+
+  @Test
+  public void testConnectorOperator() throws Exception {
+    Set<SqoopAction> allActions = Sets.newHashSet(ALL, READ, WRITE);
+    for (SqoopAction action : allActions) {
+      for (Connector connector : Sets.newHashSet(jdbc_connector, hdfs_connector, kafka_connector, kite_connector)) {
+        doTestResourceAuthorizationProvider(SUB_CONNECTOR_OPERATOR, Arrays.asList(server1, connector), Sets.newHashSet(action), READ.equals(action));
+      }
+      for (Job job : Sets.newHashSet(job1,job2)) {
+        doTestResourceAuthorizationProvider(SUB_CONNECTOR_OPERATOR, Arrays.asList(server1, job), Sets.newHashSet(action), false);
+      }
+      for (Link link : Sets.newHashSet(link1, link2)) {
+        doTestResourceAuthorizationProvider(SUB_CONNECTOR_OPERATOR, Arrays.asList(server1, link), Sets.newHashSet(action), false);
+      }
+    }
+  }
+
+  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-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopAuthorizationProviderSpecialCases.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopAuthorizationProviderSpecialCases.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopAuthorizationProviderSpecialCases.java
new file mode 100644
index 0000000..8d69402
--- /dev/null
+++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopAuthorizationProviderSpecialCases.java
@@ -0,0 +1,89 @@
+/*
+ * 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.sqoop;
+
+import java.io.File;
+import java.io.IOException;
+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.sqoop.Connector;
+import org.apache.sentry.core.model.sqoop.Server;
+import org.apache.sentry.core.model.sqoop.SqoopActionConstant;
+import org.apache.sentry.core.model.sqoop.SqoopActionFactory.SqoopAction;
+import org.apache.sentry.core.model.sqoop.SqoopPrivilegeModel;
+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.collect.Sets;
+import com.google.common.io.Files;
+
+public class TestSqoopAuthorizationProviderSpecialCases {
+  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");
+    Server server1 = new Server("server1");
+    Connector connector1 = new Connector("c1");
+    Set<? extends Action> actions = Sets.newHashSet(new SqoopAction(SqoopActionConstant.READ));
+    policyFile.addGroupsToUser(user1.getName(), true, "group1", "group1")
+      .addRolesToGroup("group1",  true, "role1", "role1")
+      .addPermissionsToRole("role1", true, "server=server1->connector=c1->action=read",
+          "server=server1->connector=c1->action=read");
+    policyFile.write(iniFile);
+    PolicyEngine policy = SqoopPolicyTestUtil.createPolicyEngineForTest(server1.getName(), initResource);
+    authzProvider = new LocalGroupResourceAuthorizationProvider(initResource, policy, SqoopPrivilegeModel.getInstance());
+    List<? extends Authorizable> authorizableHierarchy = ImmutableList.of(server1, connector1);
+    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-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopModelAuthorizables.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopModelAuthorizables.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopModelAuthorizables.java
new file mode 100644
index 0000000..5a69f4a
--- /dev/null
+++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopModelAuthorizables.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.sqoop;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.apache.sentry.core.model.sqoop.Server;
+import org.apache.sentry.core.model.sqoop.SqoopModelAuthorizables;
+import org.junit.Test;
+
+public class TestSqoopModelAuthorizables {
+
+  @Test
+  public void testServer() throws Exception {
+    Server server1 = (Server) SqoopModelAuthorizables.from("SERVER=server1");
+    assertEquals("server1", server1.getName());
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testNoKV() throws Exception {
+    System.out.println(SqoopModelAuthorizables.from("nonsense"));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyKey() throws Exception {
+    System.out.println(SqoopModelAuthorizables.from("=server1"));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyValue() throws Exception {
+    System.out.println(SqoopModelAuthorizables.from("SERVER="));
+  }
+
+  @Test
+  public void testNotAuthorizable() throws Exception {
+    assertNull(SqoopModelAuthorizables.from("k=v"));
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyEngineDFS.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyEngineDFS.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyEngineDFS.java
new file mode 100644
index 0000000..c156ed0
--- /dev/null
+++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyEngineDFS.java
@@ -0,0 +1,75 @@
+/*
+ * 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.sqoop;
+
+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 TestSqoopPolicyEngineDFS extends AbstractTestSqoopPolicyEngine {
+  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, "sqoop-policy-test-authz-provider.ini");
+    setPolicy(SqoopPolicyTestUtil.createPolicyEngineForTest(sqoopServerName, new Path(etc,
+        "sqoop-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-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyEngineLocalFS.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyEngineLocalFS.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyEngineLocalFS.java
new file mode 100644
index 0000000..b30d04b
--- /dev/null
+++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyEngineLocalFS.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.sqoop;
+
+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 TestSqoopPolicyEngineLocalFS extends AbstractTestSqoopPolicyEngine {
+  @Override
+  protected void  afterSetup() throws IOException {
+    File baseDir = getBaseDir();
+    Assert.assertNotNull(baseDir);
+    Assert.assertTrue(baseDir.isDirectory() || baseDir.mkdirs());
+    PolicyFiles.copyToDir(baseDir, "sqoop-policy-test-authz-provider.ini");
+    setPolicy(SqoopPolicyTestUtil.createPolicyEngineForTest(sqoopServerName,
+      new File(baseDir, "sqoop-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-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyNegative.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyNegative.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyNegative.java
new file mode 100644
index 0000000..12c68f3
--- /dev/null
+++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/policy/sqoop/TestSqoopPolicyNegative.java
@@ -0,0 +1,121 @@
+/*
+ * 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.sqoop;
+
+import java.io.File;
+import java.io.IOException;
+
+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 TestSqoopPolicyNegative {
+  @SuppressWarnings("unused")
+  private static final Logger LOGGER = LoggerFactory
+      .getLogger(TestSqoopPolicyNegative.class);
+
+  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 testauthorizedSqoopInPolicyFile() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("other_group = other_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("other_role = server=server1->connector=c1->action=read, server=server1->link=l1->action=read", globalPolicyFile);
+    PolicyEngine policy = SqoopPolicyTestUtil.createPolicyEngineForTest("server1", 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 testNoServerNameConfig() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("other_group = malicious_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("malicious_role = connector=c1->action=read,link=l1->action=read", globalPolicyFile);
+    PolicyEngine policy = SqoopPolicyTestUtil.createPolicyEngineForTest("server1", globalPolicyFile.getPath());
+    ImmutableSet<String> permissions = policy.getAllPrivileges(Sets.newHashSet("other_group"), ActiveRoleSet.ALL);
+    Assert.assertTrue(permissions.toString(), permissions.isEmpty());
+  }
+
+  @Test
+  public void testServerAllName() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("group = malicious_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("malicious_role = server=*", globalPolicyFile);
+    PolicyEngine policy = SqoopPolicyTestUtil.createPolicyEngineForTest("server1", globalPolicyFile.getPath());
+    ImmutableSet<String> permissions = policy.getAllPrivileges(Sets.newHashSet("group"), ActiveRoleSet.ALL);
+    Assert.assertTrue(permissions.toString(), permissions.isEmpty());
+  }
+
+  @Test
+  public void testServerIncorrect() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("group = malicious_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("malicious_role = server=server2", globalPolicyFile);
+    PolicyEngine policy = SqoopPolicyTestUtil.createPolicyEngineForTest("server1", globalPolicyFile.getPath());
+    ImmutableSet<String> permissions = policy.getAllPrivileges(Sets.newHashSet("group"), ActiveRoleSet.ALL);
+    Assert.assertTrue(permissions.toString(), permissions.isEmpty());
+  }
+
+  @Test
+  public void testAll() throws Exception {
+    append("[groups]", globalPolicyFile);
+    append("group = malicious_role", globalPolicyFile);
+    append("[roles]", globalPolicyFile);
+    append("malicious_role = *", globalPolicyFile);
+    PolicyEngine policy = SqoopPolicyTestUtil.createPolicyEngineForTest("server1", 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-sqoop/src/test/java/org/apache/sentry/privilege/sqoop/TestCommonPrivilegeForSqoop.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/privilege/sqoop/TestCommonPrivilegeForSqoop.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/privilege/sqoop/TestCommonPrivilegeForSqoop.java
new file mode 100644
index 0000000..92e9290
--- /dev/null
+++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/privilege/sqoop/TestCommonPrivilegeForSqoop.java
@@ -0,0 +1,196 @@
+/*
+ * 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.sqoop;
+
+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.sqoop.SqoopActionConstant;
+import org.apache.sentry.core.model.sqoop.SqoopPrivilegeModel;
+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 TestCommonPrivilegeForSqoop {
+
+  private Model sqoopPrivilegeModel;
+
+  private static final CommonPrivilege SQOOP_SERVER1_ALL =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("action", SqoopActionConstant.ALL));
+  private static final CommonPrivilege SQOOP_SERVER1_READ =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("action", SqoopActionConstant.READ));
+  private static final CommonPrivilege SQOOP_SERVER1_WRITE =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("action", SqoopActionConstant.WRITE));
+
+  private static final CommonPrivilege SQOOP_SERVER1_JOB1_ALL =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("JOB", "job1"),
+                  new KeyValue("action", SqoopActionConstant.ALL));
+  private static final CommonPrivilege SQOOP_SERVER1_JOB1_READ =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("JOB", "job1"),
+                  new KeyValue("action", SqoopActionConstant.READ));
+  private static final CommonPrivilege SQOOP_SERVER1_JOB1_WRITE =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("JOB", "job1"),
+                  new KeyValue("action", SqoopActionConstant.WRITE));
+
+  private static final CommonPrivilege SQOOP_SERVER1_LINK1_ALL =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("LINK", "link1"),
+                  new KeyValue("action", SqoopActionConstant.ALL));
+  private static final CommonPrivilege SQOOP_SERVER1_LINK1_READ =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("LINK", "link1"),
+                  new KeyValue("action", SqoopActionConstant.READ));
+  private static final CommonPrivilege SQOOP_SERVER1_LINK1_WRITE =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("LINK", "link1"),
+                  new KeyValue("action", SqoopActionConstant.WRITE));
+
+  private static final CommonPrivilege SQOOP_SERVER1_CONNECTOR1_ALL =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("CONNECTOR", "connector1"),
+                  new KeyValue("action", SqoopActionConstant.ALL));
+  private static final CommonPrivilege SQOOP_SERVER1_CONNECTOR1_READ =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("CONNECTOR", "connector1"),
+                  new KeyValue("action", SqoopActionConstant.READ));
+  private static final CommonPrivilege SQOOP_SERVER1_CONNECTOR1_WRITE =
+          create(new KeyValue("SERVER", "server1"), new KeyValue("CONNECTOR", "connector1"),
+                  new KeyValue("action", SqoopActionConstant.WRITE));
+
+  @Before
+  public void prepareData() {
+    sqoopPrivilegeModel = SqoopPrivilegeModel.getInstance();
+  }
+
+  @Test
+  public void testSimpleAction() throws Exception {
+    //server
+    assertFalse(SQOOP_SERVER1_WRITE.implies(SQOOP_SERVER1_READ, sqoopPrivilegeModel));
+    assertFalse(SQOOP_SERVER1_READ.implies(SQOOP_SERVER1_WRITE, sqoopPrivilegeModel));
+    //connector
+    assertFalse(SQOOP_SERVER1_CONNECTOR1_WRITE.implies(SQOOP_SERVER1_CONNECTOR1_READ, sqoopPrivilegeModel));
+    assertFalse(SQOOP_SERVER1_CONNECTOR1_READ.implies(SQOOP_SERVER1_CONNECTOR1_WRITE, sqoopPrivilegeModel));
+    //job
+    assertFalse(SQOOP_SERVER1_JOB1_READ.implies(SQOOP_SERVER1_JOB1_WRITE, sqoopPrivilegeModel));
+    assertFalse(SQOOP_SERVER1_JOB1_WRITE.implies(SQOOP_SERVER1_JOB1_READ, sqoopPrivilegeModel));
+    //link
+    assertFalse(SQOOP_SERVER1_LINK1_READ.implies(SQOOP_SERVER1_LINK1_WRITE, sqoopPrivilegeModel));
+    assertFalse(SQOOP_SERVER1_LINK1_WRITE.implies(SQOOP_SERVER1_LINK1_READ, sqoopPrivilegeModel));
+  }
+
+  @Test
+  public void testShorterThanRequest() throws Exception {
+    //job
+    assertTrue(SQOOP_SERVER1_ALL.implies(SQOOP_SERVER1_JOB1_ALL, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_ALL.implies(SQOOP_SERVER1_JOB1_READ, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_ALL.implies(SQOOP_SERVER1_JOB1_WRITE, sqoopPrivilegeModel));
+
+    assertFalse(SQOOP_SERVER1_WRITE.implies(SQOOP_SERVER1_READ, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_READ.implies(SQOOP_SERVER1_JOB1_READ, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_WRITE.implies(SQOOP_SERVER1_JOB1_WRITE, sqoopPrivilegeModel));
+
+    //link
+    assertTrue(SQOOP_SERVER1_ALL.implies(SQOOP_SERVER1_LINK1_ALL, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_ALL.implies(SQOOP_SERVER1_LINK1_READ, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_ALL.implies(SQOOP_SERVER1_LINK1_WRITE, sqoopPrivilegeModel));
+
+    assertTrue(SQOOP_SERVER1_READ.implies(SQOOP_SERVER1_LINK1_READ, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_WRITE.implies(SQOOP_SERVER1_LINK1_WRITE, sqoopPrivilegeModel));
+
+    //connector
+    assertTrue(SQOOP_SERVER1_ALL.implies(SQOOP_SERVER1_CONNECTOR1_ALL, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_ALL.implies(SQOOP_SERVER1_CONNECTOR1_READ, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_ALL.implies(SQOOP_SERVER1_CONNECTOR1_WRITE, sqoopPrivilegeModel));
+
+    assertTrue(SQOOP_SERVER1_READ.implies(SQOOP_SERVER1_CONNECTOR1_READ, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_WRITE.implies(SQOOP_SERVER1_CONNECTOR1_WRITE, sqoopPrivilegeModel));
+  }
+
+  @Test
+  public void testActionAll() throws Exception {
+    //server
+    assertTrue(SQOOP_SERVER1_ALL.implies(SQOOP_SERVER1_READ, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_ALL.implies(SQOOP_SERVER1_WRITE, sqoopPrivilegeModel));
+
+    //job
+    assertTrue(SQOOP_SERVER1_JOB1_ALL.implies(SQOOP_SERVER1_JOB1_READ, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_JOB1_ALL.implies(SQOOP_SERVER1_JOB1_WRITE, sqoopPrivilegeModel));
+
+    //link
+    assertTrue(SQOOP_SERVER1_LINK1_ALL.implies(SQOOP_SERVER1_LINK1_READ, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_LINK1_ALL.implies(SQOOP_SERVER1_LINK1_WRITE, sqoopPrivilegeModel));
+
+    //connector
+    assertTrue(SQOOP_SERVER1_CONNECTOR1_ALL.implies(SQOOP_SERVER1_CONNECTOR1_READ, sqoopPrivilegeModel));
+    assertTrue(SQOOP_SERVER1_CONNECTOR1_ALL.implies(SQOOP_SERVER1_CONNECTOR1_WRITE, sqoopPrivilegeModel));
+  }
+
+  @Test
+  public void testUnexpected() throws Exception {
+    Privilege p = new Privilege() {
+      @Override
+      public boolean implies(Privilege p, Model m) {
+        return false;
+      }
+    };
+    Privilege job1 = create(new KeyValue("SERVER", "server"), new KeyValue("JOB", "job1"));
+    assertFalse(job1.implies(null, sqoopPrivilegeModel));
+    assertFalse(job1.implies(p, sqoopPrivilegeModel));
+    assertFalse(job1.equals(null));
+    assertFalse(job1.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("", "server1")));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyValue() throws Exception {
+    System.out.println(create(SentryConstants.KV_JOINER.join("SERVER", "")));
+  }
+
+  @Test(expected=IllegalArgumentException.class)
+  public void testEmptyPart() throws Exception {
+    System.out.println(create(SentryConstants.AUTHORIZABLE_JOINER.
+            join(SentryConstants.KV_JOINER.join("SERVER", "server1"), "")));
+  }
+
+  @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-sqoop/src/test/resources/sqoop-policy-test-authz-provider.ini
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-sqoop/src/test/resources/sqoop-policy-test-authz-provider.ini b/sentry-binding/sentry-binding-sqoop/src/test/resources/sqoop-policy-test-authz-provider.ini
new file mode 100644
index 0000000..a4ab5d1
--- /dev/null
+++ b/sentry-binding/sentry-binding-sqoop/src/test/resources/sqoop-policy-test-authz-provider.ini
@@ -0,0 +1,40 @@
+# 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]
+developer = jdbc_connector_role, hdfs_connector_role,kafka_connector_role,kite_connector_role,\
+    jobs_analyst_role,links_analyst_role
+analyst = jobs_analyst_role,links_analyst_role
+connectors_operator = jdbc_connector_role, hdfs_connector_role,kafka_connector_role,kite_connector_role
+jobs_analyst = jobs_analyst_role
+job1_2_operator = job1_role,job2_role
+links_analyst = links_analyst_role
+link1_2_operator = link1_role,link2_role
+admin = admin_role
+
+[roles]
+admin_role = server=server1->action=*
+jdbc_connector_role = server=server1->connector=generic-jdbc-connector->action=read
+hdfs_connector_role = server=server1->connector=hdfs-connector->action=read
+kafka_connector_role = server=server1->connector=kafka-connector->action=read
+kite_connector_role = server=server1->connector=kite-connector->action=read
+jobs_analyst_role = server=server1->job=all->action=*
+job1_role = server=server1->job=job1->action=read
+job2_role = server=server1->job=job2->action=read
+links_analyst_role = server=server1->link=all->action=*
+link1_role = server=server1->link=link1->action=read
+link2_role = server=server1->link=link2->action=read
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/BitFieldAction.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/BitFieldAction.java b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/BitFieldAction.java
index ce0e4fb..0f5b23b 100644
--- a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/BitFieldAction.java
+++ b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/BitFieldAction.java
@@ -20,7 +20,7 @@ package org.apache.sentry.core.common;
  * example, There exists three actions, UPDATE, QUERY and ALL.
  * The a bit set for UPDATE is 0x0001, QUERY is 0x0002, ALL is 0x0001|0x0002=0x0003
  */
-public abstract class BitFieldAction implements Action {
+public class BitFieldAction implements Action {
   private String name;
   private int code;
 

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/ImplyMethodType.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/ImplyMethodType.java b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/ImplyMethodType.java
new file mode 100644
index 0000000..8931989
--- /dev/null
+++ b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/ImplyMethodType.java
@@ -0,0 +1,24 @@
+/*
+ * 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.core.common;
+
+public enum ImplyMethodType {
+  STRING,
+  STRING_CASE_SENSITIVE,
+  URL,
+  ACTION,
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/Model.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/Model.java b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/Model.java
new file mode 100644
index 0000000..a63cd63
--- /dev/null
+++ b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/Model.java
@@ -0,0 +1,29 @@
+/*
+ * 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.core.common;
+
+import java.util.Map;
+
+// The interface is used for define the authorization model for different component
+public interface Model {
+  // The authorizableTypeName is the key of map, and the ImplyMethodType is the value.
+  Map<String, ImplyMethodType> getImplyMethodMap();
+
+  BitFieldActionFactory getBitFieldActionFactory();
+
+  // TODO: add interface to validate the hierarchy for the resources
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/Resource.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/Resource.java b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/Resource.java
new file mode 100644
index 0000000..3ce52e8
--- /dev/null
+++ b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/Resource.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.core.common;
+
+// The interface is responsible for define the resource for every component.
+public interface Resource {
+  // Get the ResourceImplyMethodType which indicate how to compare the resource value.
+  // eg, For Hive component, it will output STRING for "db", "table", "column" and URL for "url"
+  //     in CommonPrivilege, the method imply() will compare the resource value according to the ResourceImplyMethodType.
+  //     Using String.equals() for STRING and PathUtils.impliesURI() for URL
+  ImplyMethodType getResourceImplyMethod();
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/KeyValue.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/KeyValue.java b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/KeyValue.java
new file mode 100644
index 0000000..4e944e5
--- /dev/null
+++ b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/KeyValue.java
@@ -0,0 +1,99 @@
+/*
+ * 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.core.common.utils;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+public class KeyValue {
+  private final String key;
+  private final String value;
+
+  public KeyValue(String keyValue) {
+    List<String> kvList = Lists.newArrayList(SentryConstants.KV_SPLITTER.trimResults().limit(2).split(keyValue));
+    if (kvList.size() != 2) {
+      throw new IllegalArgumentException("Invalid key value: " + keyValue + " " + kvList);
+    }
+    key = kvList.get(0);
+    value = kvList.get(1);
+    if (key.isEmpty()) {
+      throw new IllegalArgumentException("Key cannot be empty");
+    } else if (value.isEmpty()) {
+      throw new IllegalArgumentException("Value cannot be empty");
+    }
+  }
+
+  public KeyValue(String key, String value) {
+    super();
+    this.key = key;
+    this.value = value;
+  }
+
+  public String getKey() {
+    return key;
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  @Override
+  public String toString() {
+    return SentryConstants.KV_JOINER.join(key, value);
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((key == null) ? 0 : key.hashCode());
+    result = prime * result + ((value == null) ? 0 : value.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    KeyValue other = (KeyValue) obj;
+    if (key == null) {
+      if (other.key != null) {
+        return false;
+      }
+    } else if (!key.equals(other.key)) {
+      return false;
+    }
+    if (value == null) {
+      if (other.value != null) {
+        return false;
+      }
+    } else if (!value.equals(other.value)) {
+      return false;
+    }
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/SentryConstants.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/SentryConstants.java b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/SentryConstants.java
new file mode 100644
index 0000000..3da4906
--- /dev/null
+++ b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/utils/SentryConstants.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.core.common.utils;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+
+public class SentryConstants {
+
+  public static final String ROLE_SEPARATOR = ",";
+  public static final String AUTHORIZABLE_SEPARATOR = "->";
+  public static final String KV_SEPARATOR = "=";
+
+  public static final Splitter ROLE_SPLITTER = Splitter.on(ROLE_SEPARATOR);
+  public static final Splitter AUTHORIZABLE_SPLITTER = Splitter.on(AUTHORIZABLE_SEPARATOR);
+  public static final Splitter KV_SPLITTER = Splitter.on(KV_SEPARATOR);
+  public static final Joiner ROLE_JOINER = Joiner.on(ROLE_SEPARATOR);
+  public static final Joiner AUTHORIZABLE_JOINER = Joiner.on(AUTHORIZABLE_SEPARATOR);
+  public static final Joiner KV_JOINER = Joiner.on(KV_SEPARATOR);
+
+  public static final String PRIVILEGE_NAME = "action";
+  public static final String PRIVILEGE_PREFIX = (PRIVILEGE_NAME + KV_SEPARATOR).toLowerCase();
+  public static final String PRIVILEGE_WILDCARD_VALUE = "*";
+
+  public static final String RESOURCE_WILDCARD_VALUE = "*";
+  public static final String RESOURCE_WILDCARD_VALUE_ALL = "ALL";
+  public static final String RESOURCE_WILDCARD_VALUE_SOME = "+";
+  public static final String ACCESS_ALLOW_URI_PER_DB_POLICYFILE = "sentry.allow.uri.db.policyfile";
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/validator/PrivilegeValidator.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/validator/PrivilegeValidator.java b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/validator/PrivilegeValidator.java
new file mode 100644
index 0000000..f5643ff
--- /dev/null
+++ b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/validator/PrivilegeValidator.java
@@ -0,0 +1,24 @@
+/*
+ * 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.core.common.validator;
+
+import org.apache.shiro.config.ConfigurationException;
+
+public interface PrivilegeValidator {
+
+  void validate(PrivilegeValidatorContext context) throws ConfigurationException;
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/validator/PrivilegeValidatorContext.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/validator/PrivilegeValidatorContext.java b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/validator/PrivilegeValidatorContext.java
new file mode 100644
index 0000000..ccee977
--- /dev/null
+++ b/sentry-core/sentry-core-common/src/main/java/org/apache/sentry/core/common/validator/PrivilegeValidatorContext.java
@@ -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.
+ */
+package org.apache.sentry.core.common.validator;
+
+import javax.annotation.Nullable;
+
+public class PrivilegeValidatorContext {
+  private final String database;
+  private final String privilege;
+  public PrivilegeValidatorContext(String privilege) {
+    this(null, privilege);
+  }
+  public PrivilegeValidatorContext(@Nullable String database, String privilege) {
+    super();
+    this.database = database;
+    this.privilege = privilege;
+  }
+  public @Nullable String getDatabase() {
+    return database;
+  }
+  public String getPrivilege() {
+    return privilege;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-common/src/test/java/org/apache/sentry/core/common/utils/TestKeyValue.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-common/src/test/java/org/apache/sentry/core/common/utils/TestKeyValue.java b/sentry-core/sentry-core-common/src/test/java/org/apache/sentry/core/common/utils/TestKeyValue.java
new file mode 100644
index 0000000..ca44a24
--- /dev/null
+++ b/sentry-core/sentry-core-common/src/test/java/org/apache/sentry/core/common/utils/TestKeyValue.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.core.common.utils;
+
+import static org.apache.sentry.core.common.utils.SentryConstants.KV_JOINER;
+import junit.framework.Assert;
+import org.junit.Test;
+
+public class TestKeyValue {
+
+  @Test
+  public void testWithSeparators() throws Exception {
+    KeyValue kv = new KeyValue("URI=/u/h/w/t/partition=value/");
+    Assert.assertEquals("URI", kv.getKey());
+    Assert.assertEquals("/u/h/w/t/partition=value/", kv.getValue());
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testEmptyKey() throws Exception {
+    new KeyValue(KV_JOINER.join("", "b"));
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testEmptyValue() throws Exception {
+    new KeyValue(KV_JOINER.join("a", ""));
+  }
+
+  @Test
+  public void testOneParameterConstructor() throws Exception {
+    KeyValue kv1 = new KeyValue(KV_JOINER.join("k1", "v1"));
+    KeyValue kv2 = new KeyValue(KV_JOINER.join("k1", "v1"));
+    KeyValue kv3 = new KeyValue(KV_JOINER.join("k2", "v2"));
+    doTest(kv1, kv2, kv3);
+  }
+
+  @Test
+  public void testTwoParameterConstructor() throws Exception {
+    KeyValue kv1 = new KeyValue("k1", "v1");
+    KeyValue kv2 = new KeyValue("k1", "v1");
+    KeyValue kv3 = new KeyValue("k2", "v2");
+    doTest(kv1, kv2, kv3);
+  }
+
+  private void doTest(KeyValue kv1, KeyValue kv2, KeyValue kv3) {
+    Assert.assertEquals(kv1, kv2);
+    Assert.assertFalse(kv1.equals(kv3));
+
+    Assert.assertEquals(kv1.toString(), kv2.toString());
+    Assert.assertFalse(kv1.toString().equals(kv3.toString()));
+
+    Assert.assertEquals(kv1.hashCode(), kv2.hashCode());
+    Assert.assertFalse(kv1.hashCode() == kv3.hashCode());
+
+    Assert.assertEquals(kv1.getKey(), kv2.getKey());
+    Assert.assertFalse(kv1.getKey().equals(kv3.getKey()));
+
+    Assert.assertEquals(kv1.getValue(), kv2.getValue());
+    Assert.assertFalse(kv1.getValue().equals(kv3.getValue()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/DBModelAuthorizables.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/DBModelAuthorizables.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/DBModelAuthorizables.java
new file mode 100644
index 0000000..3a05a3b
--- /dev/null
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/DBModelAuthorizables.java
@@ -0,0 +1,60 @@
+/*
+ * 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.core.model.db;
+
+import org.apache.sentry.core.model.db.DBModelAuthorizable.AuthorizableType;
+import org.apache.sentry.core.common.utils.KeyValue;
+
+public class DBModelAuthorizables {
+
+  public static DBModelAuthorizable from(KeyValue keyValue) {
+    String prefix = keyValue.getKey().toLowerCase();
+    String name = keyValue.getValue();
+    for(AuthorizableType type : AuthorizableType.values()) {
+      if(prefix.equalsIgnoreCase(type.name())) {
+        if (prefix.equalsIgnoreCase(AuthorizableType.URI.toString())) {
+          return from(type, name);
+        } else {
+          return from(type, name.toLowerCase());
+        }
+      }
+    }
+    return null;
+  }
+  public static DBModelAuthorizable from(String s) {
+    return from(new KeyValue(s));
+  }
+
+  private static DBModelAuthorizable from(AuthorizableType type, String name) {
+    switch (type) {
+    case Server:
+      return new Server(name);
+    case Db:
+      return new Database(name);
+    case Table:
+      return new Table(name);
+    case View:
+      return new View(name);
+    case Column:
+      return new Column(name);
+    case URI:
+      return new AccessURI(name);
+    default:
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/d94e900a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/HiveActionFactory.java
----------------------------------------------------------------------
diff --git a/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/HiveActionFactory.java b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/HiveActionFactory.java
new file mode 100644
index 0000000..ad7e1c9
--- /dev/null
+++ b/sentry-core/sentry-core-model-db/src/main/java/org/apache/sentry/core/model/db/HiveActionFactory.java
@@ -0,0 +1,73 @@
+/*
+ * 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.core.model.db;
+
+import org.apache.sentry.core.common.BitFieldAction;
+import org.apache.sentry.core.common.BitFieldActionFactory;
+
+import java.util.List;
+
+// The class is used to define the privilege code for Hive
+public class HiveActionFactory extends BitFieldActionFactory {
+
+  enum ActionType {
+    SELECT(AccessConstants.SELECT, 1),    // binary: 00000001
+    INSERT(AccessConstants.INSERT, 2),    // binary: 00000010
+    ALTER(AccessConstants.ALTER, 4),      // binary: 00000100
+    CREATE(AccessConstants.CREATE, 8),    // binary: 00001000
+    DROP(AccessConstants.DROP, 16),       // binary: 00010000
+    INDEX(AccessConstants.INDEX, 32),     // binary: 00100000
+    LOCK(AccessConstants.LOCK, 64),       // binary: 01000000
+
+    // For the compatibility, ALL, ALL_STAR, SOME have the same binary value: 01111111
+    // They have the different names which are "ALL", "*", "+"
+    ALL(AccessConstants.ACTION_ALL, SELECT.getCode() | INSERT.getCode() | ALTER.getCode() | CREATE.getCode() |
+            DROP.getCode() | INDEX.getCode() | LOCK.getCode()),   // binary: 01111111
+    ALL_STAR(AccessConstants.ALL, ALL.getCode()),                 // binary: 01111111
+    SOME(AccessConstants.SOME, ALL.getCode());                    // binary: 01111111
+
+    private String name;
+    private int code;
+
+    ActionType(String name, int code) {
+      this.name = name;
+      this.code = code;
+    }
+
+    public int getCode() {
+      return code;
+    }
+
+    public String getName() {
+      return name;
+    }
+  }
+
+  public List<? extends BitFieldAction> getActionsByCode(int actionCode) {
+    return null;
+  }
+
+  public BitFieldAction getActionByName(String name) {
+    for (ActionType action : ActionType.values()) {
+      if (action.name.equalsIgnoreCase(name)) {
+        return new BitFieldAction(action.getName(), action.getCode());
+      }
+    }
+    return null;
+  }
+
+}
\ No newline at end of file


Mime
View raw message