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
