Repository: incubator-sentry Updated Branches: refs/heads/master 6498ce90d -> 357d83fbc
SENTRY-612: Sqoop2 integration with sentry (Guoquan Shen, reviewed by Prasad Mujumdar) Project: http://git-wip-us.apache.org/repos/asf/incubator-sentry/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-sentry/commit/357d83fb Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/357d83fb Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/357d83fb Branch: refs/heads/master Commit: 357d83fbc619ba14bb63a6dce0200c5560e18376 Parents: 6498ce9 Author: Guoquan Shen <[email protected]> Authored: Tue May 12 14:43:06 2015 +0800 Committer: Guoquan Shen <[email protected]> Committed: Tue May 12 14:43:06 2015 +0800 ---------------------------------------------------------------------- pom.xml | 26 ++ sentry-binding/pom.xml | 1 + sentry-binding/sentry-binding-sqoop/pom.xml | 80 ++++ .../org/apache/sentry/sqoop/PrincipalDesc.java | 50 +++ .../apache/sentry/sqoop/SentrySqoopError.java | 32 ++ .../sqoop/authz/SentryAccessController.java | 192 +++++++++ .../sqoop/authz/SentryAuthorizationHander.java | 117 ++++++ .../authz/SentryAuthorizationValidator.java | 63 +++ .../sentry/sqoop/binding/SqoopAuthBinding.java | 393 +++++++++++++++++++ .../binding/SqoopAuthBindingSingleton.java | 96 +++++ .../sqoop/binding/SqoopProviderBackend.java | 44 +++ .../apache/sentry/sqoop/conf/SqoopAuthConf.java | 75 ++++ .../sqoop/MockAuthenticationProvider.java | 32 ++ .../sqoop/TestSentryAuthorizationHander.java | 74 ++++ .../apache/sentry/sqoop/TestSqoopAuthConf.java | 62 +++ .../test/resources/no-configure-sentry-site.xml | 22 ++ .../src/test/resources/sentry-site.xml | 38 ++ .../src/test/resources/test-authz-provider.ini | 40 ++ sentry-dist/pom.xml | 4 + .../provider/common/AuthorizationComponent.java | 1 + sentry-provider/sentry-provider-db/pom.xml | 4 + .../generic/SentryGenericProviderBackend.java | 153 ++++++++ .../persistent/PrivilegeOperatePersistence.java | 2 + .../thrift/SentryGenericPolicyProcessor.java | 9 + 24 files changed, 1610 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 863f70c..8bcf1d0 100644 --- a/pom.xml +++ b/pom.xml @@ -94,6 +94,7 @@ limitations under the License. <objenesis.version>1.2</objenesis.version> <cglib.version>2.2</cglib.version> <commons-pool2.version>2.2</commons-pool2.version> + <sqoop.version>1.99.6</sqoop.version> </properties> <dependencyManagement> @@ -371,6 +372,11 @@ limitations under the License. </dependency> <dependency> <groupId>org.apache.sentry</groupId> + <artifactId>sentry-binding-sqoop</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.sentry</groupId> <artifactId>sentry-provider-common</artifactId> <version>${project.version}</version> </dependency> @@ -531,6 +537,26 @@ limitations under the License. <artifactId>commons-pool2</artifactId> <version>${commons-pool2.version}</version> </dependency> + <dependency> + <groupId>org.apache.sqoop</groupId> + <artifactId>sqoop-common</artifactId> + <version>${sqoop.version}</version> + </dependency> + <dependency> + <groupId>org.apache.sqoop</groupId> + <artifactId>sqoop-security</artifactId> + <version>${sqoop.version}</version> + </dependency> + <dependency> + <groupId>org.apache.sqoop</groupId> + <artifactId>sqoop-server</artifactId> + <version>${sqoop.version}</version> + </dependency> + <dependency> + <groupId>org.apache.sqoop</groupId> + <artifactId>test</artifactId> + <version>${sqoop.version}</version> + </dependency> </dependencies> </dependencyManagement> http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/pom.xml ---------------------------------------------------------------------- diff --git a/sentry-binding/pom.xml b/sentry-binding/pom.xml index b903ab3..8e0256c 100644 --- a/sentry-binding/pom.xml +++ b/sentry-binding/pom.xml @@ -32,6 +32,7 @@ limitations under the License. <modules> <module>sentry-binding-hive</module> <module>sentry-binding-solr</module> + <module>sentry-binding-sqoop</module> </modules> </project> http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/pom.xml ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/pom.xml b/sentry-binding/sentry-binding-sqoop/pom.xml new file mode 100644 index 0000000..2d25d21 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/pom.xml @@ -0,0 +1,80 @@ +<?xml version="1.0"?> +<!-- +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. +--> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.sentry</groupId> + <artifactId>sentry-binding</artifactId> + <version>1.6.0-incubating-SNAPSHOT</version> + </parent> + + <artifactId>sentry-binding-sqoop</artifactId> + <name>Sentry Binding for Sqoop</name> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.sentry</groupId> + <artifactId>sentry-core-common</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sentry</groupId> + <artifactId>sentry-core-model-sqoop</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sentry</groupId> + <artifactId>sentry-provider-common</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sentry</groupId> + <artifactId>sentry-provider-file</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sentry</groupId> + <artifactId>sentry-provider-db</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sentry</groupId> + <artifactId>sentry-policy-common</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sentry</groupId> + <artifactId>sentry-policy-sqoop</artifactId> + </dependency> + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-common</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sqoop</groupId> + <artifactId>sqoop-common</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sqoop</groupId> + <artifactId>sqoop-security</artifactId> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/PrincipalDesc.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/PrincipalDesc.java b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/PrincipalDesc.java new file mode 100644 index 0000000..cc9096c --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/PrincipalDesc.java @@ -0,0 +1,50 @@ +/** + * 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.sqoop; + +public class PrincipalDesc { + public static enum PrincipalType { + USER, + ROLE, + GROUP; + } + + private String name; + private PrincipalType type; + + public PrincipalDesc(String name, String type) { + this.name = name; + this.type = fromStr(type); + } + + private PrincipalType fromStr(String str) { + return Enum.valueOf(PrincipalType.class, str.toUpperCase()); + } + + public String getName() { + return name; + } + + public PrincipalType getType() { + return type; + } + + public static PrincipalDesc fromStr(String name, String type) { + return new PrincipalDesc(name, type); + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/SentrySqoopError.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/SentrySqoopError.java b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/SentrySqoopError.java new file mode 100644 index 0000000..b86c59f --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/SentrySqoopError.java @@ -0,0 +1,32 @@ +/* + * 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.sqoop; + +public class SentrySqoopError { + public static final String SHOW_GRANT_NOT_SUPPORTED_FOR_PRINCIPAL = + "Sentry does only support show roles on group, not supported on "; + public static final String AUTHORIZE_CHECK_NOT_SUPPORT_FOR_PRINCIPAL = + "Sentry does only support authorization check on user principal, not supported on "; + public static final String SHOW_PRIVILEGE_NOT_SUPPORTED_FOR_PRINCIPAL = + "Sentry does only support show privilege on role, not supported on "; + public static final String GRANT_REVOKE_PRIVILEGE_NOT_SUPPORT_FOR_PRINCIPAL = + "Sentry does only support grant/revoke privilege to/from role, not supported on "; + public static final String GRANT_REVOKE_ROLE_NOT_SUPPORT_FOR_PRINCIPAL = + "Sentry does only support grant/revoke role to/from group, not supported on "; + public static final String NOT_IMPLEMENT_YET = + "Sentry does not implement yet "; +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAccessController.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAccessController.java b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAccessController.java new file mode 100644 index 0000000..7762f61 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAccessController.java @@ -0,0 +1,192 @@ +/* + * 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.sqoop.authz; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.apache.sentry.core.common.Subject; +import org.apache.sentry.sqoop.PrincipalDesc; +import org.apache.sentry.sqoop.PrincipalDesc.PrincipalType; +import org.apache.sentry.sqoop.SentrySqoopError; +import org.apache.sentry.sqoop.binding.SqoopAuthBinding; +import org.apache.sentry.sqoop.binding.SqoopAuthBindingSingleton; +import org.apache.sqoop.common.SqoopException; +import org.apache.sqoop.model.MPrincipal; +import org.apache.sqoop.model.MPrivilege; +import org.apache.sqoop.model.MResource; +import org.apache.sqoop.model.MRole; +import org.apache.sqoop.security.AuthorizationAccessController; +import org.apache.sqoop.security.SecurityError; + +public class SentryAccessController extends AuthorizationAccessController { + private static final Logger LOG = Logger.getLogger(SentryAccessController.class); + private final SqoopAuthBinding binding; + + public SentryAccessController() throws Exception { + this.binding = SqoopAuthBindingSingleton.getInstance().getAuthBinding(); + } + + private Subject getSubject() { + return new Subject(SentryAuthorizationHander.getAuthenticator().getUserName()); + } + + @Override + public void createRole(MRole role) throws SqoopException { + binding.createRole(getSubject(), role.getName()); + } + + @Override + public void dropRole(MRole role) throws SqoopException { + binding.dropRole(getSubject(), role.getName()); + } + + @Override + public List<MRole> getAllRoles() throws SqoopException { + return binding.listAllRoles(getSubject()); + } + + @Override + public List<MPrincipal> getPrincipalsByRole(MRole role) throws SqoopException { + /** + * Sentry does not implement this function yet + */ + throw new SqoopException(SecurityError.AUTH_0014, SentrySqoopError.NOT_IMPLEMENT_YET); + } + + @Override + public List<MPrivilege> getPrivilegesByPrincipal(MPrincipal principal, + MResource resource) throws SqoopException { + /** + * Sentry Only supports get privilege by role + */ + PrincipalDesc principalDesc = PrincipalDesc.fromStr(principal.getName(), principal.getType()); + if (principalDesc.getType() != PrincipalType.ROLE) { + throw new SqoopException(SecurityError.AUTH_0014, + SentrySqoopError.SHOW_PRIVILEGE_NOT_SUPPORTED_FOR_PRINCIPAL + + principalDesc.getType().name()); + } + return binding.listPrivilegeByRole(getSubject(), principalDesc.getName(), resource); + } + + @Override + public List<MRole> getRolesByPrincipal(MPrincipal principal) throws SqoopException { + /** + * Sentry Only supports get privilege by role + */ + PrincipalDesc principalDesc = PrincipalDesc.fromStr(principal.getName(), principal.getType()); + if (principalDesc.getType() != PrincipalType.GROUP) { + throw new SqoopException(SecurityError.AUTH_0014, + SentrySqoopError.SHOW_GRANT_NOT_SUPPORTED_FOR_PRINCIPAL + + principalDesc.getType().name()); + } + return binding.listRolesByGroup(getSubject(), principalDesc.getName()); + } + + @Override + public void grantPrivileges(List<MPrincipal> principals, List<MPrivilege> privileges) + throws SqoopException { + for (MPrincipal principal : principals) { + PrincipalDesc principalDesc = PrincipalDesc.fromStr(principal.getName(), principal.getType()); + if (principalDesc.getType() != PrincipalType.ROLE) { + throw new SqoopException(SecurityError.AUTH_0014, + SentrySqoopError.GRANT_REVOKE_PRIVILEGE_NOT_SUPPORT_FOR_PRINCIPAL + + principalDesc.getType().name()); + } + + for (MPrivilege privilege : privileges) { + if (LOG.isDebugEnabled()) { + LOG.debug("Going to grant privilege : " + privilege + + " to principal: " + principal); + } + binding.grantPrivilege(getSubject(), principal.getName(), privilege); + } + } + } + + @Override + public void grantRole(List<MPrincipal> principals, List<MRole> roles) + throws SqoopException { + for (MPrincipal principal : principals) { + PrincipalDesc principalDesc = PrincipalDesc.fromStr(principal.getName(), principal.getType()); + if (principalDesc.getType() != PrincipalType.GROUP) { + throw new SqoopException(SecurityError.AUTH_0014, + SentrySqoopError.GRANT_REVOKE_ROLE_NOT_SUPPORT_FOR_PRINCIPAL + + principalDesc.getType().name()); + } + for (MRole role : roles) { + if (LOG.isDebugEnabled()) { + LOG.debug("Going to grant role : " + role.getName() + + " to principal: " + principal); + } + binding.grantGroupToRole(getSubject(), principal.getName(), role); + } + } + } + + @Override + public void removeResource(MResource resource) throws SqoopException { + binding.dropPrivilege(getSubject(), resource); + } + + @Override + public void revokePrivileges(List<MPrincipal> principals, List<MPrivilege> privileges) + throws SqoopException { + for (MPrincipal principal : principals) { + PrincipalDesc principalDesc = PrincipalDesc.fromStr(principal.getName(), principal.getType()); + if (principalDesc.getType() != PrincipalType.ROLE) { + throw new SqoopException(SecurityError.AUTH_0014, + SentrySqoopError.GRANT_REVOKE_PRIVILEGE_NOT_SUPPORT_FOR_PRINCIPAL + + principalDesc.getType().name()); + } + + for (MPrivilege privilege : privileges) { + if (LOG.isDebugEnabled()) { + LOG.debug("Going to revoke privilege : " + privilege + + " from principal: " + principal); + } + binding.revokePrivilege(getSubject(), principal.getName(), privilege); + } + } + } + + @Override + public void revokeRole(List<MPrincipal> principals, List<MRole> roles) + throws SqoopException { + for (MPrincipal principal : principals) { + PrincipalDesc principalDesc = PrincipalDesc.fromStr(principal.getName(), principal.getType()); + if (principalDesc.getType() != PrincipalType.GROUP) { + throw new SqoopException(SecurityError.AUTH_0014, + SentrySqoopError.GRANT_REVOKE_ROLE_NOT_SUPPORT_FOR_PRINCIPAL + + principalDesc.getType().name()); + } + for (MRole role : roles) { + if (LOG.isDebugEnabled()) { + LOG.debug("Going to revoke role : " + role.getName() + + " from principal: " + principal); + } + binding.revokeGroupfromRole(getSubject(), principal.getName(), role); + } + } + } + + @Override + public void updateResource(MResource srcResource, MResource dstResource) + throws SqoopException { + binding.renamePrivilege(getSubject(), srcResource, dstResource); + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAuthorizationHander.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAuthorizationHander.java b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAuthorizationHander.java new file mode 100644 index 0000000..93bf3f3 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAuthorizationHander.java @@ -0,0 +1,117 @@ +/* + * 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.sqoop.authz; + +import java.util.List; + +import org.apache.sqoop.common.SqoopException; +import org.apache.sqoop.model.MPrincipal; +import org.apache.sqoop.model.MPrivilege; +import org.apache.sqoop.model.MResource; +import org.apache.sqoop.model.MRole; +import org.apache.sqoop.security.AuthenticationProvider; +import org.apache.sqoop.security.authorization.DefaultAuthorizationHandler; + +public class SentryAuthorizationHander extends DefaultAuthorizationHandler { + private static AuthenticationProvider authenticator; + + public static AuthenticationProvider getAuthenticator() { + if (authenticator == null) { + throw new RuntimeException("authenticator can't be null"); + } + return authenticator; + } + @Override + public void doInitialize(AuthenticationProvider authenticationProvider, String serverName) + throws ClassNotFoundException, IllegalAccessException, + InstantiationException { + super.doInitialize(authenticationProvider, serverName); + authenticator = authenticationProvider; + } + + @Override + public void checkPrivileges(MPrincipal principal, List<MPrivilege> privileges) + throws SqoopException { + authorizationValidator.checkPrivileges(principal, privileges); + } + + @Override + public void createRole(MRole role) throws SqoopException { + authorizationAccessController.createRole(role); + } + + @Override + public void dropRole(MRole role) throws SqoopException { + authorizationAccessController.dropRole(role); + } + + @Override + public List<MRole> getAllRoles() throws SqoopException { + return authorizationAccessController.getAllRoles(); + } + + @Override + public List<MPrincipal> getPrincipalsByRole(MRole role) throws SqoopException { + return authorizationAccessController.getPrincipalsByRole(role); + } + + @Override + public List<MPrivilege> getPrivilegesByPrincipal(MPrincipal principal, + MResource resource) throws SqoopException { + return authorizationAccessController.getPrivilegesByPrincipal(principal, resource); + } + + @Override + public List<MRole> getRolesByPrincipal(MPrincipal principal) throws SqoopException { + return authorizationAccessController.getRolesByPrincipal(principal); + } + + @Override + public void grantPrivileges(List<MPrincipal> principals, List<MPrivilege> privileges) + throws SqoopException { + authorizationAccessController.grantPrivileges(principals, privileges); + } + + @Override + public void grantRole(List<MPrincipal> principals, List<MRole> roles) + throws SqoopException { + authorizationAccessController.grantRole(principals, roles); + } + + @Override + public void removeResource(MResource resource) throws SqoopException { + authorizationAccessController.removeResource(resource); + } + + @Override + public void revokePrivileges(List<MPrincipal> principals, List<MPrivilege> privileges) + throws SqoopException { + authorizationAccessController.revokePrivileges(principals, privileges); + } + + @Override + public void revokeRole(List<MPrincipal> principals, List<MRole> roles) + throws SqoopException { + authorizationAccessController.revokeRole(principals, roles); + } + + @Override + public void updateResource(MResource srcResource, MResource dstResource) + throws SqoopException { + authorizationAccessController.updateResource(srcResource, dstResource); + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAuthorizationValidator.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAuthorizationValidator.java b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAuthorizationValidator.java new file mode 100644 index 0000000..5f96767 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/authz/SentryAuthorizationValidator.java @@ -0,0 +1,63 @@ +/* + * 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.sqoop.authz; + +import java.util.List; + +import org.apache.sentry.core.common.Subject; +import org.apache.sentry.sqoop.PrincipalDesc; +import org.apache.sentry.sqoop.PrincipalDesc.PrincipalType; +import org.apache.sentry.sqoop.SentrySqoopError; +import org.apache.sentry.sqoop.binding.SqoopAuthBinding; +import org.apache.sentry.sqoop.binding.SqoopAuthBindingSingleton; +import org.apache.sqoop.common.SqoopException; +import org.apache.sqoop.model.MPrincipal; +import org.apache.sqoop.model.MPrivilege; +import org.apache.sqoop.security.AuthorizationValidator; +import org.apache.sqoop.security.SecurityError; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SentryAuthorizationValidator extends AuthorizationValidator { + private static final Logger LOG = LoggerFactory.getLogger(SentryAuthorizationValidator.class); + private final SqoopAuthBinding binding; + + public SentryAuthorizationValidator() throws Exception { + this.binding = SqoopAuthBindingSingleton.getInstance().getAuthBinding(); + } + + @Override + public void checkPrivileges(MPrincipal principal, List<MPrivilege> privileges) throws SqoopException { + if ((privileges == null) || privileges.isEmpty()) { + return; + } + PrincipalDesc principalDesc = new PrincipalDesc(principal.getName(), principal.getType()); + if (principalDesc.getType() != PrincipalType.USER) { + throw new SqoopException(SecurityError.AUTH_0014,SentrySqoopError.AUTHORIZE_CHECK_NOT_SUPPORT_FOR_PRINCIPAL); + } + for (MPrivilege privilege : privileges) { + if (LOG.isDebugEnabled()) { + LOG.debug("Going to authorize check on privilege : " + privilege + + " for principal: " + principal); + } + if (!binding.authorize(new Subject(principalDesc.getName()), privilege)) { + throw new SqoopException(SecurityError.AUTH_0014, "User " + principalDesc.getName() + + " does not have privileges for : " + privilege.toString()); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/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 new file mode 100644 index 0000000..86b157c --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopAuthBinding.java @@ -0,0 +1,393 @@ +/* + * 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.sqoop.binding; + +import java.lang.reflect.Constructor; +import java.util.List; +import java.util.Set; + +import org.apache.hadoop.conf.Configuration; +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.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.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.db.generic.service.thrift.SentryGenericServiceClient; +import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryGrantOption; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole; +import org.apache.sentry.sqoop.conf.SqoopAuthConf.AuthzConfVars; +import org.apache.sqoop.common.SqoopException; +import org.apache.sqoop.model.MPrivilege; +import org.apache.sqoop.model.MResource; +import org.apache.sqoop.model.MRole; +import org.apache.sqoop.security.SecurityError; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +public class SqoopAuthBinding { + private static final Logger LOG = LoggerFactory.getLogger(SqoopAuthBinding.class); + private static final String COMPONENT_TYPE = AuthorizationComponent.SQOOP; + + private final Configuration authConf; + private final AuthorizationProvider authProvider; + private final Server sqoopServer; + private ProviderBackend providerBackend; + + private final SqoopActionFactory actionFactory = new SqoopActionFactory(); + + public SqoopAuthBinding(Configuration authConf, String serverName) throws Exception { + this.authConf = authConf; + this.authConf.set(AuthzConfVars.AUTHZ_SERVER_NAME.getVar(), serverName); + this.sqoopServer = new Server(serverName); + this.authProvider = createAuthProvider(); + } + + /** + * Instantiate the configured authz provider + * @return {@link AuthorizationProvider} + */ + private AuthorizationProvider createAuthProvider() throws Exception { + /** + * get the authProvider class, policyEngine class, providerBackend class and resources from the sqoopAuthConf config + */ + String authProviderName = authConf.get(AuthzConfVars.AUTHZ_PROVIDER.getVar(),AuthzConfVars.AUTHZ_PROVIDER.getDefault()); + String resourceName = authConf.get(AuthzConfVars.AUTHZ_PROVIDER_RESOURCE.getVar(), AuthzConfVars.AUTHZ_PROVIDER_RESOURCE.getDefault()); + 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()); + if (LOG.isDebugEnabled()) { + LOG.debug("Using authorization provider " + authProviderName + + " with resource " + resourceName + ", policy engine " + + policyEngineName + ", provider backend " + providerBackendName); + } + + //Instantiate the configured providerBackend + Constructor<?> providerBackendConstructor = + Class.forName(providerBackendName).getDeclaredConstructor(Configuration.class, String.class); + providerBackendConstructor.setAccessible(true); + providerBackend = + (ProviderBackend) providerBackendConstructor.newInstance(new Object[] {authConf, resourceName}); + + //Instantiate the configured policyEngine + Constructor<?> policyConstructor = + Class.forName(policyEngineName).getDeclaredConstructor(String.class, ProviderBackend.class); + policyConstructor.setAccessible(true); + PolicyEngine policyEngine = + (PolicyEngine) policyConstructor.newInstance(new Object[] {sqoopServer.getName(), providerBackend}); + + //Instantiate the configured authProvider + Constructor<?> constrctor = + Class.forName(authProviderName).getDeclaredConstructor(Configuration.class, String.class, PolicyEngine.class); + constrctor.setAccessible(true); + return (AuthorizationProvider) constrctor.newInstance(new Object[] {authConf, resourceName, policyEngine}); + } + + /** + * Authorize access to a Sqoop privilege + * @param subject + * @param authorizable + * @param action + * @return true or false + */ + public boolean authorize(Subject subject, MPrivilege privilege) { + List<Authorizable> authorizables = toAuthorizable(privilege.getResource()); + if (!hasServerInclude(authorizables)) { + authorizables.add(0, sqoopServer); + } + return authProvider.hasAccess(subject, + authorizables, + Sets.newHashSet(actionFactory.getActionByName(privilege.getAction())), ActiveRoleSet.ALL); + } + + public boolean hasServerInclude(List<Authorizable> authorizables) { + for (Authorizable authorizable : authorizables) { + if (authorizable.getTypeName().equalsIgnoreCase(sqoopServer.getTypeName())) { + return true; + } + } + return false; + } + + /** + * The Sentry-296(generate client for connection pooling) has already finished development and reviewed by now. When it + * was committed to master, the getClient method was needed to refactor using the connection pool + */ + private SentryGenericServiceClient getClient() throws Exception { + return new SentryGenericServiceClient(authConf); + } + + public void createRole(final Subject subject, final String role) throws SqoopException { + execute(new Command<Void>() { + @Override + public Void run(SentryGenericServiceClient client) throws Exception { + client.createRole(subject.getName(), role, COMPONENT_TYPE); + return null; + } + }); + } + + public void dropRole(final Subject subject, final String role) throws SqoopException { + execute(new Command<Void>() { + @Override + public Void run(SentryGenericServiceClient client) throws Exception { + client.dropRole(subject.getName(), role, COMPONENT_TYPE); + return null; + } + }); + } + + public List<MRole> listAllRoles(final Subject subject) throws SqoopException { + Set<TSentryRole> tSentryRoles = execute(new Command<Set<TSentryRole>>() { + @Override + public Set<TSentryRole> run(SentryGenericServiceClient client) + throws Exception { + return client.listAllRoles(subject.getName(), COMPONENT_TYPE); + } + }); + + List<MRole> roles = Lists.newArrayList(); + for (TSentryRole tRole : tSentryRoles) { + roles.add(new MRole(tRole.getRoleName())); + } + return roles; + } + + public List<MRole> listRolesByGroup(final Subject subject, final String groupName) throws SqoopException { + Set<TSentryRole> tSentryRoles = execute(new Command<Set<TSentryRole>>() { + @Override + public Set<TSentryRole> run(SentryGenericServiceClient client) + throws Exception { + return client.listRolesByGroupName(subject.getName(), groupName, COMPONENT_TYPE); + } + }); + + List<MRole> roles = Lists.newArrayList(); + for (TSentryRole tSentryRole : tSentryRoles) { + roles.add(new MRole(tSentryRole.getRoleName())); + } + return roles; + } + + public List<MPrivilege> listPrivilegeByRole(final Subject subject, final String role, final MResource resource) throws SqoopException { + Set<TSentryPrivilege> tSentryPrivileges = execute(new Command<Set<TSentryPrivilege>>() { + @Override + public Set<TSentryPrivilege> run(SentryGenericServiceClient client) + throws Exception { + if (resource == null) { + return client.listPrivilegesByRoleName(subject.getName(), role, COMPONENT_TYPE, sqoopServer.getName()); + } else if (resource.getType().equalsIgnoreCase(MResource.TYPE.SERVER.name())) { + return client.listPrivilegesByRoleName(subject.getName(), role, COMPONENT_TYPE, resource.getName()); + } else { + return client.listPrivilegesByRoleName(subject.getName(), role, COMPONENT_TYPE, sqoopServer.getName(), toAuthorizable(resource)); + } + } + }); + + List<MPrivilege> privileges = Lists.newArrayList(); + for (TSentryPrivilege tSentryPrivilege : tSentryPrivileges) { + privileges.add(toSqoopPrivilege(tSentryPrivilege)); + } + return privileges; + } + + public void grantPrivilege(final Subject subject, final String role, final MPrivilege privilege) throws SqoopException { + execute(new Command<Void>() { + @Override + public Void run(SentryGenericServiceClient client) throws Exception { + client.grantPrivilege(subject.getName(), role, COMPONENT_TYPE, toTSentryPrivilege(privilege)); + return null; + } + }); + } + + public void revokePrivilege(final Subject subject, final String role, final MPrivilege privilege) throws SqoopException { + execute(new Command<Void>() { + @Override + public Void run(SentryGenericServiceClient client) throws Exception { + client.revokePrivilege(subject.getName(), role, COMPONENT_TYPE, toTSentryPrivilege(privilege)); + return null; + } + }); + } + + public void grantGroupToRole(final Subject subject, final String group, final MRole role) throws SqoopException { + execute(new Command<Void>() { + @Override + public Void run(SentryGenericServiceClient client) throws Exception { + client.addRoleToGroups(subject.getName(), role.getName(), COMPONENT_TYPE, Sets.newHashSet(group)); + return null; + } + }); + } + + public void revokeGroupfromRole(final Subject subject, final String group, final MRole role) throws SqoopException { + execute(new Command<Void>() { + @Override + public Void run(SentryGenericServiceClient client) throws Exception { + client.deleteRoleToGroups(subject.getName(), role.getName(), COMPONENT_TYPE, Sets.newHashSet(group)); + return null; + } + }); + } + + public void renamePrivilege(final Subject subject, final MResource srcResource, final MResource dstResource) throws SqoopException { + execute(new Command<Void>() { + @Override + public Void run(SentryGenericServiceClient client) throws Exception { + client.renamePrivilege(subject.getName(), COMPONENT_TYPE, sqoopServer.getName(), + toAuthorizable(srcResource), toAuthorizable(dstResource)); + return null; + } + }); + } + + public void dropPrivilege(final Subject subject, final MResource resource) throws SqoopException { + execute(new Command<Void>() { + @Override + public Void run(SentryGenericServiceClient client) throws Exception { + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setComponent(COMPONENT_TYPE); + privilege.setServiceName(sqoopServer.getName()); + privilege.setAuthorizables(toTSentryAuthorizable(resource)); + privilege.setAction(SqoopActionConstant.ALL); + client.dropPrivilege(subject.getName(), COMPONENT_TYPE, privilege); + return null; + } + }); + } + + private MPrivilege toSqoopPrivilege(TSentryPrivilege tPrivilege) { + //construct a sqoop resource + boolean grantOption = false; + if (tPrivilege.getGrantOption() == TSentryGrantOption.TRUE) { + grantOption = true; + } + //construct a sqoop privilege + return new MPrivilege( + toSqoopResource(tPrivilege.getAuthorizables()), + tPrivilege.getAction().equalsIgnoreCase(SqoopActionConstant.ALL) ? SqoopActionConstant.ALL_NAME + : tPrivilege.getAction(), grantOption); + } + + private MResource toSqoopResource(List<TAuthorizable> authorizables) { + if ((authorizables == null) || authorizables.isEmpty()) { + //server resource + return new MResource(sqoopServer.getName(), MResource.TYPE.SERVER); + } else { + //currently Sqoop only has one-level hierarchy authorizable resource + return new MResource(authorizables.get(0).getName(), authorizables.get(0).getType()); + } + } + + /** + * construct a Sentry privilege to call by the thrift API + * @param privilege + * @return {@link TSentryPrivilege} + */ + private TSentryPrivilege toTSentryPrivilege(MPrivilege privilege) { + TSentryPrivilege tSentryPrivilege = new TSentryPrivilege(); + tSentryPrivilege.setComponent(COMPONENT_TYPE); + tSentryPrivilege.setServiceName(sqoopServer.getName()); + tSentryPrivilege.setAction(privilege.getAction().equalsIgnoreCase( + SqoopActionConstant.ALL_NAME) ? SqoopActionConstant.ALL : privilege + .getAction()); + if (privilege.isWith_grant_option()) { + tSentryPrivilege.setGrantOption(TSentryGrantOption.TRUE); + } else { + tSentryPrivilege.setGrantOption(TSentryGrantOption.FALSE); + } + tSentryPrivilege.setAuthorizables(toTSentryAuthorizable(privilege.getResource())); + return tSentryPrivilege; + } + + + private List<TAuthorizable> toTSentryAuthorizable(MResource resource) { + List<TAuthorizable> tAuthorizables = Lists.newArrayList(); + /** + * Currently Sqoop supports grant privileges on server object, but the server name must be equaled the configuration + * of org.apache.sqoop.security.authorization.server_name in the Sqoop.properties. + */ + if (resource.getType().equalsIgnoreCase(MResource.TYPE.SERVER.name())) { + if (!resource.getName().equalsIgnoreCase(sqoopServer.getName())) { + throw new IllegalArgumentException( resource.getName() + " must be equal to " + sqoopServer.getName() + "\n" + + " Currently Sqoop supports grant/revoke privileges on server object, but the server name must be equal to the configuration " + + "of org.apache.sqoop.security.authorization.server_name in the Sqoop.properties"); + } + } else { + tAuthorizables.add(new TAuthorizable(resource.getType(), resource.getName())); + } + return tAuthorizables; + } + + private List<Authorizable> toAuthorizable(final MResource resource) { + List<Authorizable> authorizables = Lists.newArrayList(); + if (resource == null) { + return authorizables; + } + authorizables.add(new Authorizable() { + @Override + public String getTypeName() { + return resource.getType(); + } + + @Override + public String getName() { + return resource.getName(); + } + }); + return authorizables; + } + + /** + * A Command is a closure used to pass a block of code from individual + * functions to execute, which centralizes connection error + * handling. Command is parameterized on the return type of the function. + */ + private static interface Command<T> { + T run(SentryGenericServiceClient client) throws Exception; + } + + private <T> T execute(Command<T> cmd) throws SqoopException { + SentryGenericServiceClient client = null; + try { + client = getClient(); + return cmd.run(client); + } catch (SentryUserException ex) { + String msg = "Unable to excute command on sentry server: " + ex.getMessage(); + LOG.error(msg, ex); + throw new SqoopException(SecurityError.AUTH_0014, msg, ex); + } catch (Exception ex) { + String msg = "Unable to obtain client:" + ex.getMessage(); + LOG.error(msg, ex); + throw new SqoopException(SecurityError.AUTH_0014, msg, ex); + } finally { + if (client != null) { + client.close(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopAuthBindingSingleton.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopAuthBindingSingleton.java b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopAuthBindingSingleton.java new file mode 100644 index 0000000..bdd60a4 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopAuthBindingSingleton.java @@ -0,0 +1,96 @@ +/* + * 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.sqoop.binding; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.hadoop.conf.Configuration; +import org.apache.sentry.sqoop.conf.SqoopAuthConf; +import org.apache.sentry.sqoop.conf.SqoopAuthConf.AuthzConfVars; +import org.apache.sqoop.core.SqoopConfiguration; +import org.apache.sqoop.security.SecurityConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Strings; + +public class SqoopAuthBindingSingleton { + private static Logger log = LoggerFactory.getLogger(SqoopAuthBindingSingleton.class); + private static SqoopAuthBindingSingleton instance = null; + + private SqoopAuthBinding binding; + + private SqoopAuthBindingSingleton() { + SqoopAuthBinding tmpBinding = null; + try { + String serverName = SqoopConfiguration.getInstance().getContext().getString(SecurityConstants.SERVER_NAME); + if (Strings.isNullOrEmpty(serverName)) { + throw new IllegalArgumentException(SecurityConstants.SERVER_NAME + " can't be null or empty"); + } + SqoopAuthConf conf = loadAuthzConf(); + validateSentrySqoopConfig(conf); + tmpBinding = new SqoopAuthBinding(conf, serverName.trim()); + log.info("SqoopAuthBinding created successfully"); + } catch (Exception ex) { + log.error("Unable to create SqoopAuthBinding", ex); + throw new RuntimeException("Unable to create SqoopAuthBinding: " + ex.getMessage(), ex); + } + binding = tmpBinding; + } + + private SqoopAuthConf loadAuthzConf() { + String sentry_site = SqoopConfiguration.getInstance().getContext() + .getString(SqoopAuthConf.SENTRY_SQOOP_SITE_URL); + if (Strings.isNullOrEmpty(sentry_site)) { + throw new IllegalArgumentException("Configuration key " + SqoopAuthConf.SENTRY_SQOOP_SITE_URL + + " value '" + sentry_site + "' is invalid."); + } + + SqoopAuthConf sqoopAuthConf = null; + try { + sqoopAuthConf = new SqoopAuthConf(new URL(sentry_site)); + } catch (MalformedURLException e) { + throw new IllegalArgumentException("Configuration key " + SqoopAuthConf.SENTRY_SQOOP_SITE_URL + + " specifies a malformed URL '" + sentry_site + "'", e); + } + return sqoopAuthConf; + } + + private void validateSentrySqoopConfig(SqoopAuthConf conf) { + boolean isTestingMode = Boolean.parseBoolean(conf.get(AuthzConfVars.AUTHZ_TESTING_MODE.getVar(), + AuthzConfVars.AUTHZ_TESTING_MODE.getDefault())); + String authentication = SqoopConfiguration.getInstance().getContext() + .getString(SecurityConstants.AUTHENTICATION_TYPE, SecurityConstants.TYPE.SIMPLE.name()); + String kerberos = SecurityConstants.TYPE.KERBEROS.name(); + if(!isTestingMode && !kerberos.equalsIgnoreCase(authentication)) { + throw new IllegalArgumentException(SecurityConstants.AUTHENTICATION_TYPE + "can't be set simple mode in non-testing mode"); + } + } + + public static SqoopAuthBindingSingleton getInstance() { + if (instance != null) { + return instance; + } + instance = new SqoopAuthBindingSingleton(); + return instance; + } + + public SqoopAuthBinding getAuthBinding() { + return binding; + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopProviderBackend.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopProviderBackend.java b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopProviderBackend.java new file mode 100644 index 0000000..cadc2f5 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/binding/SqoopProviderBackend.java @@ -0,0 +1,44 @@ +/* + * 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.sqoop.binding; + +import org.apache.hadoop.conf.Configuration; +import org.apache.sentry.core.model.sqoop.Server; +import org.apache.sentry.provider.common.AuthorizationComponent; +import org.apache.sentry.provider.db.generic.SentryGenericProviderBackend; +import org.apache.sentry.sqoop.conf.SqoopAuthConf.AuthzConfVars; + +public class SqoopProviderBackend extends SentryGenericProviderBackend { + private Server sqoopServer; + public SqoopProviderBackend(Configuration conf, String resourcePath) throws Exception { + super(conf); + sqoopServer = new Server(conf.get(AuthzConfVars.AUTHZ_SERVER_NAME.getVar())); + } + @Override + public String getComponentType() { + return AuthorizationComponent.SQOOP; + } + + /** + * SqoopProviderBackend use the name of Sqoop Server as the identifier to + * distinguish itself from multiple Sqoop Servers + */ + @Override + public String getComponentIdentifier() { + return sqoopServer.getName(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/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 new file mode 100644 index 0000000..fcf7860 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/main/java/org/apache/sentry/sqoop/conf/SqoopAuthConf.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.sqoop.conf; + +import java.net.URL; +import org.apache.hadoop.conf.Configuration; + +public class SqoopAuthConf extends Configuration { + /** + * Configuration key used in sqoop.properties to point at sentry-site.xml + */ + public static final String SENTRY_SQOOP_SITE_URL = "sentry.sqoop.site.url"; + /** + * Config setting definitions + */ + public static enum AuthzConfVars { + AUTHZ_PROVIDER("sentry.sqoop.provider","org.apache.sentry.provider.common.HadoopGroupResourceAuthorizationProvider"), + AUTHZ_PROVIDER_RESOURCE("sentry.sqoop.provider.resource", ""), + AUTHZ_PROVIDER_BACKEND("sentry.sqoop.provider.backend","org.apache.sentry.provider.file.SimpleFileProviderBackend"), + AUTHZ_POLICY_ENGINE("sentry.sqoop.policy.engine","org.apache.sentry.policy.sqoop.SimpleSqoopPolicyEngine"), + AUTHZ_SERVER_NAME("sentry.sqoop.name", ""), + AUTHZ_TESTING_MODE("sentry.sqoop.testing.mode", "false"); + + private final String varName; + private final String defaultVal; + + AuthzConfVars(String varName, String defaultVal) { + this.varName = varName; + this.defaultVal = defaultVal; + } + + public String getVar() { + return varName; + } + + public String getDefault() { + return defaultVal; + } + + public static String getDefault(String varName) { + for (AuthzConfVars oneVar : AuthzConfVars.values()) { + if (oneVar.getVar().equalsIgnoreCase(varName)) { + return oneVar.getDefault(); + } + } + return null; + } + } + + public static final String AUTHZ_SITE_FILE = "sentry-site.xml"; + + public SqoopAuthConf(URL sqoopAuthzSiteURL) { + super(true); + addResource(sqoopAuthzSiteURL); + } + + @Override + public String get(String varName) { + return get(varName, AuthzConfVars.getDefault(varName)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/MockAuthenticationProvider.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/MockAuthenticationProvider.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/MockAuthenticationProvider.java new file mode 100644 index 0000000..0cd9fc6 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/MockAuthenticationProvider.java @@ -0,0 +1,32 @@ +/* + * 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.sqoop; + +import org.apache.sqoop.security.AuthenticationProvider; + +public class MockAuthenticationProvider extends AuthenticationProvider { + + @Override + public String[] getGroupNames() { + return new String[]{""}; + } + + @Override + public String getUserName() { + return ""; + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/TestSentryAuthorizationHander.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/TestSentryAuthorizationHander.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/TestSentryAuthorizationHander.java new file mode 100644 index 0000000..7efc0a2 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/TestSentryAuthorizationHander.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.sqoop; + +import static junit.framework.Assert.fail; + +import java.io.File; + +import org.apache.commons.io.FileUtils; +import org.apache.sentry.provider.file.PolicyFiles; +import org.apache.sentry.sqoop.conf.SqoopAuthConf; +import org.apache.sentry.sqoop.conf.SqoopAuthConf.AuthzConfVars; +import org.apache.sqoop.security.SecurityFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.io.Files; +import com.google.common.io.Resources; + +public class TestSentryAuthorizationHander { + private static final String RESOURCE_PATH = "test-authz-provider.ini"; + private SqoopAuthConf authzConf; + private File baseDir; + + @Before + public void setup() throws Exception { + baseDir = Files.createTempDir(); + PolicyFiles.copyToDir(baseDir, RESOURCE_PATH); + authzConf = new SqoopAuthConf(Resources.getResource("sentry-site.xml")); + authzConf.set(AuthzConfVars.AUTHZ_PROVIDER_RESOURCE.getVar(), new File(baseDir, RESOURCE_PATH).getPath()); + } + + @After + public void teardown() { + if(baseDir != null) { + FileUtils.deleteQuietly(baseDir); + } + } + + /** + * Test that incorrect specification of classes for + * AUTHZ_ACCESS_CONTROLLER and AUTHZ_ACCESS_VALIDATOR + * correctly throw ClassNotFoundExceptions + */ + @Test + public void testClassNotFound() throws Exception { + try { + SecurityFactory.getAuthorizationAccessController("org.apache.sentry.sqoop.authz.BogusSentryAccessController"); + fail("Exception should have been thrown"); + } catch (Exception ex) { + } + + try { + SecurityFactory.getAuthorizationValidator("org.apache.sentry.sqoop.authz.BogusSentryAuthorizationValidator"); + fail("Exception should have been thrown"); + } catch (Exception ex) { + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/TestSqoopAuthConf.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/TestSqoopAuthConf.java b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/TestSqoopAuthConf.java new file mode 100644 index 0000000..e4991e1 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/test/java/org/apache/sentry/sqoop/TestSqoopAuthConf.java @@ -0,0 +1,62 @@ +/* + * 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.sqoop; + +import java.util.Arrays; +import java.util.List; + +import org.apache.sentry.sqoop.conf.SqoopAuthConf; +import org.apache.sentry.sqoop.conf.SqoopAuthConf.AuthzConfVars; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.io.Resources; + +public class TestSqoopAuthConf { + private static SqoopAuthConf authAllConf; + private static SqoopAuthConf authNoConf; + private static List<AuthzConfVars> currentProps; + + @BeforeClass + public static void setup() throws Exception { + authAllConf = new SqoopAuthConf(Resources.getResource("sentry-site.xml")); + authNoConf = new SqoopAuthConf(Resources.getResource("no-configure-sentry-site.xml")); + currentProps = Arrays.asList(new AuthzConfVars[]{ + AuthzConfVars.AUTHZ_PROVIDER, AuthzConfVars.AUTHZ_PROVIDER_BACKEND, + AuthzConfVars.AUTHZ_POLICY_ENGINE, AuthzConfVars.AUTHZ_PROVIDER_RESOURCE + }); + } + + @Test + public void testPropertiesHaveConfigured() { + Assert.assertEquals("org.apache.sentry.provider.common.HadoopGroupResourceAuthorizationProvider", + authAllConf.get(AuthzConfVars.AUTHZ_PROVIDER.getVar())); + Assert.assertEquals("classpath:test-authz-provider.ini", + authAllConf.get(AuthzConfVars.AUTHZ_PROVIDER_RESOURCE.getVar())); + Assert.assertEquals("org.apache.sentry.policy.sqoop.SimpleSqoopPolicyEngine", + authAllConf.get(AuthzConfVars.AUTHZ_POLICY_ENGINE.getVar())); + Assert.assertEquals("true", authAllConf.get(AuthzConfVars.AUTHZ_TESTING_MODE.getVar())); + } + + @Test + public void testPropertiesNoConfigured() { + for (AuthzConfVars currentVar : currentProps) { + Assert.assertEquals(currentVar.getDefault(), authNoConf.get(currentVar.getVar())); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/test/resources/no-configure-sentry-site.xml ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/test/resources/no-configure-sentry-site.xml b/sentry-binding/sentry-binding-sqoop/src/test/resources/no-configure-sentry-site.xml new file mode 100644 index 0000000..f642712 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/test/resources/no-configure-sentry-site.xml @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> +<!-- + 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. +--> + +<configuration> +</configuration> + http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/test/resources/sentry-site.xml ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/test/resources/sentry-site.xml b/sentry-binding/sentry-binding-sqoop/src/test/resources/sentry-site.xml new file mode 100644 index 0000000..2c98980 --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/test/resources/sentry-site.xml @@ -0,0 +1,38 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> +<!-- + 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. +--> + +<configuration> + <property> + <name>sentry.sqoop.provider</name> + <value>org.apache.sentry.provider.common.HadoopGroupResourceAuthorizationProvider</value> + </property> + <property> + <name>sentry.sqoop.provider.resource</name> + <value>classpath:test-authz-provider.ini</value> + </property> + <property> + <name>sentry.sqoop.policy.engine</name> + <value>org.apache.sentry.policy.sqoop.SimpleSqoopPolicyEngine</value> + </property> + <property> + <name>sentry.sqoop.testing.mode</name> + <value>true</value> + </property> +</configuration> + http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-binding/sentry-binding-sqoop/src/test/resources/test-authz-provider.ini ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-sqoop/src/test/resources/test-authz-provider.ini b/sentry-binding/sentry-binding-sqoop/src/test/resources/test-authz-provider.ini new file mode 100644 index 0000000..dc11b4b --- /dev/null +++ b/sentry-binding/sentry-binding-sqoop/src/test/resources/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=*->action=* +job1_role = server=server1->job=job1->action=read +job2_role = server=server1->job=job2->action=read +links_analyst_role = server=server1->link=*->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/incubator-sentry/blob/357d83fb/sentry-dist/pom.xml ---------------------------------------------------------------------- diff --git a/sentry-dist/pom.xml b/sentry-dist/pom.xml index 51e05a5..cde21c0 100644 --- a/sentry-dist/pom.xml +++ b/sentry-dist/pom.xml @@ -56,6 +56,10 @@ limitations under the License. </dependency> <dependency> <groupId>org.apache.sentry</groupId> + <artifactId>sentry-binding-sqoop</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sentry</groupId> <artifactId>solr-sentry-handlers</artifactId> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-provider/sentry-provider-common/src/main/java/org/apache/sentry/provider/common/AuthorizationComponent.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-common/src/main/java/org/apache/sentry/provider/common/AuthorizationComponent.java b/sentry-provider/sentry-provider-common/src/main/java/org/apache/sentry/provider/common/AuthorizationComponent.java index def3486..6409015 100644 --- a/sentry-provider/sentry-provider-common/src/main/java/org/apache/sentry/provider/common/AuthorizationComponent.java +++ b/sentry-provider/sentry-provider-common/src/main/java/org/apache/sentry/provider/common/AuthorizationComponent.java @@ -21,4 +21,5 @@ package org.apache.sentry.provider.common; */ public class AuthorizationComponent{ public static final String Search = "solr"; + public static final String SQOOP = "sqoop"; } http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-provider/sentry-provider-db/pom.xml ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/pom.xml b/sentry-provider/sentry-provider-db/pom.xml index 7dd40b8..9c4618f 100644 --- a/sentry-provider/sentry-provider-db/pom.xml +++ b/sentry-provider/sentry-provider-db/pom.xml @@ -88,6 +88,10 @@ limitations under the License. </dependency> <dependency> <groupId>org.apache.sentry</groupId> + <artifactId>sentry-core-model-sqoop</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sentry</groupId> <artifactId>sentry-provider-common</artifactId> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java new file mode 100644 index 0000000..11ffde2 --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java @@ -0,0 +1,153 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sentry.provider.db.generic; + +import java.util.Arrays; +import java.util.Set; + +import org.apache.hadoop.conf.Configuration; +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.SentryConfigurationException; +import org.apache.sentry.provider.common.ProviderBackend; +import org.apache.sentry.provider.common.ProviderBackendContext; +import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; + +/** + * This class used when any component such as Hive, Solr or Sqoop want to integration with the Sentry service + */ +public abstract class SentryGenericProviderBackend implements ProviderBackend { + private static final Logger LOGGER = LoggerFactory.getLogger(SentryGenericProviderBackend.class); + private final Configuration conf; + private volatile boolean initialized = false; + + public SentryGenericProviderBackend(Configuration conf) throws Exception { + this.conf = conf; + } + + @Override + public void initialize(ProviderBackendContext context) { + if (initialized) { + throw new IllegalStateException("SentryGenericProviderBackend has already been initialized, cannot be initialized twice"); + } + this.initialized = true; + } + + /** + * The Sentry-296(generate client for connection pooling) has already finished development and reviewed by now. When it + * was committed to master, the getClient method was needed to refactor using the connection pool + */ + private SentryGenericServiceClient getClient() throws Exception { + return new SentryGenericServiceClient(conf); + } + + @Override + public ImmutableSet<String> getPrivileges(Set<String> groups, + ActiveRoleSet roleSet, Authorizable... authorizableHierarchy) { + if (!initialized) { + throw new IllegalStateException("SentryGenericProviderBackend has not been properly initialized"); + } + SentryGenericServiceClient client = null; + try { + client = getClient(); + return ImmutableSet.copyOf(client.listPrivilegesForProvider( + getComponentType(), getComponentIdentifier(), roleSet, groups, + Arrays.asList(authorizableHierarchy))); + } catch (SentryUserException e) { + String msg = "Unable to obtain privileges from server: " + e.getMessage(); + LOGGER.error(msg, e); + } catch (Exception e) { + String msg = "Unable to obtain client:" + e.getMessage(); + LOGGER.error(msg, e); + } finally { + if (client != null) { + client.close(); + } + } + return ImmutableSet.of(); + } + + @Override + public ImmutableSet<String> getRoles(Set<String> groups, ActiveRoleSet roleSet) { + if (!initialized) { + throw new IllegalStateException("SentryGenericProviderBackend has not been properly initialized"); + } + SentryGenericServiceClient client = null; + try { + Set<TSentryRole> tRoles = Sets.newHashSet(); + client = getClient(); + //get the roles according to group + String requestor = UserGroupInformation.getCurrentUser().getShortUserName(); + for (String group : groups) { + tRoles.addAll(client.listRolesByGroupName(requestor, group, getComponentType())); + } + Set<String> roles = Sets.newHashSet(); + for (TSentryRole tRole : tRoles) { + roles.add(tRole.getRoleName()); + } + return ImmutableSet.copyOf(roleSet.isAll() ? roles : Sets.intersection(roles, roleSet.getRoles())); + } catch (SentryUserException e) { + String msg = "Unable to obtain roles from server: " + e.getMessage(); + LOGGER.error(msg, e); + } catch (Exception e) { + String msg = "Unable to obtain client:" + e.getMessage(); + LOGGER.error(msg, e); + } finally { + if (client != null) { + client.close(); + } + } + return ImmutableSet.of(); + } + + /** + * SentryGenericProviderBackend does nothing in the validatePolicy() + */ + @Override + public void validatePolicy(boolean strictValidation) + throws SentryConfigurationException { + if (!initialized) { + throw new IllegalStateException("SentryGenericProviderBackend has not been properly initialized"); + } + } + + @Override + public void close() { + } + + /** + * Get the component type for the Generic Provider backend, such as Hive,Solr or Sqoop + */ + public abstract String getComponentType(); + + /** + * When the providerBackend want to get privileges from the Sentry service. + * The component identifier is very important to Sentry service. Take the component type is Hive for example, + * when there are multiple HiveServers implemented role-based authorization via Sentry. Each HiveServer must uses a + * identifier to distinguish itself from multiple HiveServers. + */ + public abstract String getComponentIdentifier(); +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeOperatePersistence.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeOperatePersistence.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeOperatePersistence.java index daeefdf..98b22b0 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeOperatePersistence.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeOperatePersistence.java @@ -32,6 +32,7 @@ import org.apache.sentry.core.common.Authorizable; import org.apache.sentry.core.common.BitFieldAction; import org.apache.sentry.core.common.BitFieldActionFactory; import org.apache.sentry.core.model.search.SearchActionFactory; +import org.apache.sentry.core.model.sqoop.SqoopActionFactory; import org.apache.sentry.provider.db.generic.service.persistent.PrivilegeObject.Builder; import org.apache.sentry.provider.db.service.model.MSentryGMPrivilege; import org.apache.sentry.provider.db.service.model.MSentryPrivilege; @@ -50,6 +51,7 @@ public class PrivilegeOperatePersistence { private static final Map<String, BitFieldActionFactory> actionFactories = Maps.newHashMap(); static{ actionFactories.put("solr", new SearchActionFactory()); + actionFactories.put("sqoop", new SqoopActionFactory()); } public boolean checkPrivilegeOption(Set<MSentryRole> roles, PrivilegeObject privilege, PersistenceManager pm) { http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/357d83fb/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessor.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessor.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessor.java index d6600a0..62f36b4 100644 --- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessor.java +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/SentryGenericPolicyProcessor.java @@ -29,6 +29,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.sentry.SentryUserException; import org.apache.sentry.core.common.Authorizable; import org.apache.sentry.core.model.db.AccessConstants; +import org.apache.sentry.provider.common.AuthorizationComponent; import org.apache.sentry.provider.db.SentryAccessDeniedException; import org.apache.sentry.provider.db.SentryAlreadyExistsException; import org.apache.sentry.provider.db.SentryInvalidInputException; @@ -255,6 +256,9 @@ public class SentryGenericPolicyProcessor implements SentryGenericPolicyService. Set<String> permissions = Sets.newHashSet(); for (PrivilegeObject privilege : privileges) { List<String> hierarchy = Lists.newArrayList(); + if (hasComponentServerPrivilege(privilege.getComponent())) { + hierarchy.add(KV_JOINER.join("server", privilege.getService())); + } for (Authorizable authorizable : privilege.getAuthorizables()) { hierarchy.add(KV_JOINER.join(authorizable.getTypeName(),authorizable.getName())); } @@ -264,6 +268,11 @@ public class SentryGenericPolicyProcessor implements SentryGenericPolicyService. return permissions; } + private boolean hasComponentServerPrivilege(String component) { + //judge the component whether has the server privilege, for example: sqoop has the privilege on the server + return AuthorizationComponent.SQOOP.equalsIgnoreCase(component); + } + @Override public TCreateSentryRoleResponse create_sentry_role( final TCreateSentryRoleRequest request) throws TException {
