ATLAS-495 Atlas Ranger Authorization Plugin (nixonrodrigues via shwethags)
Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/353ea964 Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/353ea964 Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/353ea964 Branch: refs/heads/master Commit: 353ea964e594cb33096263791fae95720203d2cc Parents: 19751c6 Author: Shwetha GS <[email protected]> Authored: Fri May 20 23:25:31 2016 +0530 Committer: Shwetha GS <[email protected]> Committed: Fri May 20 23:25:31 2016 +0530 ---------------------------------------------------------------------- authorization/pom.xml | 57 +++ .../atlas/authorize/AtlasAccessRequest.java | 125 ++++++ .../atlas/authorize/AtlasActionTypes.java | 22 ++ .../authorize/AtlasAuthorizationException.java | 40 ++ .../apache/atlas/authorize/AtlasAuthorizer.java | 42 ++ .../atlas/authorize/AtlasAuthorizerFactory.java | 84 ++++ .../atlas/authorize/AtlasResourceTypes.java | 23 ++ .../simple/AtlasAuthorizationUtils.java | 131 +++++++ .../atlas/authorize/simple/FileReaderUtil.java | 56 +++ .../atlas/authorize/simple/PolicyDef.java | 70 ++++ .../atlas/authorize/simple/PolicyParser.java | 265 +++++++++++++ .../atlas/authorize/simple/PolicyUtil.java | 103 +++++ .../authorize/simple/SimpleAtlasAuthorizer.java | 387 +++++++++++++++++++ .../simple/AtlasAuthorizationUtilsTest.java | 118 ++++++ .../authorize/simple/PolicyParserTest.java | 172 +++++++++ .../atlas/authorize/simple/PolicyUtilTest.java | 100 +++++ .../simple/SimpleAtlasAuthorizerTest.java | 208 ++++++++++ common/pom.xml | 6 + .../org/apache/atlas/utils/PropertiesUtil.java | 137 +++++++ .../apache/atlas/utils/XMLPropertiesUtil.java | 85 ++++ distro/src/conf/atlas-application.properties | 3 + distro/src/conf/policy-store.txt | 2 - distro/src/conf/users-credentials.properties | 2 - pom.xml | 3 + release-log.txt | 1 + webapp/pom.xml | 6 + .../atlas/authorize/AtlasAccessRequest.java | 117 ------ .../atlas/authorize/AtlasAccessorTypes.java | 22 -- .../atlas/authorize/AtlasActionTypes.java | 22 -- .../authorize/AtlasAuthorizationException.java | 40 -- .../authorize/AtlasAuthorizationUtils.java | 149 ------- .../apache/atlas/authorize/AtlasAuthorizer.java | 43 --- .../atlas/authorize/AtlasResourceTypes.java | 23 -- .../org/apache/atlas/authorize/PolicyDef.java | 67 ---- .../apache/atlas/authorize/PolicyParser.java | 238 ------------ .../org/apache/atlas/authorize/PolicyUtil.java | 164 -------- .../atlas/authorize/SimpleAtlasAuthorizer.java | 380 ------------------ .../org/apache/atlas/util/FileReaderUtil.java | 56 --- .../org/apache/atlas/util/PropertiesUtil.java | 135 ------- .../apache/atlas/util/XMLPropertiesUtil.java | 85 ---- .../web/filters/AtlasAuthorizationFilter.java | 96 +++-- .../security/AtlasADAuthenticationProvider.java | 2 +- .../AtlasLdapAuthenticationProvider.java | 2 +- .../main/webapp/WEB-INF/applicationContext.xml | 4 +- .../authorize/AtlasAuthorizationUtilsTest.java | 121 ------ .../atlas/authorize/PolicyParserTest.java | 167 -------- .../apache/atlas/authorize/PolicyUtilTest.java | 95 ----- .../authorize/SimpleAtlasAuthorizerTest.java | 185 --------- 48 files changed, 2303 insertions(+), 2158 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/pom.xml ---------------------------------------------------------------------- diff --git a/authorization/pom.xml b/authorization/pom.xml new file mode 100644 index 0000000..74c433b --- /dev/null +++ b/authorization/pom.xml @@ -0,0 +1,57 @@ +<?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.atlas</groupId> + <artifactId>apache-atlas</artifactId> + <version>0.7-incubating-SNAPSHOT</version> + </parent> + <artifactId>atlas-authorization</artifactId> + <name>Apache Atlas Authorization</name> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.apache.atlas</groupId> + <artifactId>atlas-common</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.atlas</groupId> + <artifactId>atlas-client</artifactId> + </dependency> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>${javax.servlet.version}</version> + </dependency> + + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + </dependency> + + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessRequest.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessRequest.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessRequest.java new file mode 100644 index 0000000..377aca7 --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessRequest.java @@ -0,0 +1,125 @@ +/** + * 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.atlas.authorize; + +import java.util.Date; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.atlas.authorize.simple.AtlasAuthorizationUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AtlasAccessRequest { + + private static Logger LOG = LoggerFactory.getLogger(AtlasAccessRequest.class); + private static boolean isDebugEnabled = LOG.isDebugEnabled(); + private Set<AtlasResourceTypes> resourceType = null; + private String resource = null; + private AtlasActionTypes action = null; + private String user = null; + private Set<String> userGroups = null; + private Date accessTime = null; + private String clientIPAddress = null; + + public AtlasAccessRequest(HttpServletRequest request, String user, Set<String> userGroups) { + this(AtlasAuthorizationUtils.getAtlasResourceType(request.getServletPath()), "*", AtlasAuthorizationUtils + .getAtlasAction(request.getMethod()), user, userGroups); + } + + public AtlasAccessRequest(Set<AtlasResourceTypes> resourceType, String resource, AtlasActionTypes action, + String user, Set<String> userGroups) { + if (isDebugEnabled) { + LOG.debug("==> AtlasAccessRequestImpl-- Initializing AtlasAccessRequest"); + } + setResource(resource); + setAction(action); + setUser(user); + setUserGroups(userGroups); + setResourceType(resourceType); + + // set remaining fields to default value + setAccessTime(null); + setClientIPAddress(null); + } + + public Set<AtlasResourceTypes> getResourceTypes() { + return resourceType; + } + + public void setResourceType(Set<AtlasResourceTypes> resourceType) { + this.resourceType = resourceType; + } + + public String getResource() { + return resource; + } + + public void setResource(String resource) { + this.resource = resource; + } + + public AtlasActionTypes getAction() { + return action; + } + + public void setAction(AtlasActionTypes action) { + this.action = action; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public void setUserGroups(Set<String> userGroups) { + this.userGroups = userGroups; + } + + public Set<String> getUserGroups() { + return userGroups; + } + + public Date getAccessTime() { + return accessTime; + } + + public void setAccessTime(Date accessTime) { + this.accessTime = accessTime; + } + + public String getClientIPAddress() { + return clientIPAddress; + } + + public void setClientIPAddress(String clientIPAddress) { + this.clientIPAddress = clientIPAddress; + } + + @Override + public String toString() { + return "AtlasAccessRequest [resourceType=" + resourceType + ", resource=" + resource + ", action=" + action + + ", user=" + user + ", userGroups=" + userGroups + ", accessTime=" + accessTime + ", clientIPAddress=" + + clientIPAddress + "]"; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/AtlasActionTypes.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasActionTypes.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasActionTypes.java new file mode 100644 index 0000000..b42162f --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasActionTypes.java @@ -0,0 +1,22 @@ +/** + * 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.atlas.authorize; + +public enum AtlasActionTypes { + READ, CREATE, UPDATE, DELETE; +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationException.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationException.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationException.java new file mode 100644 index 0000000..ff35e7d --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationException.java @@ -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. + */ + +package org.apache.atlas.authorize; + +public class AtlasAuthorizationException extends Exception { + private static final long serialVersionUID = 1L; + + public AtlasAuthorizationException(String message) { + super(message); + } + + public AtlasAuthorizationException(String message, Throwable exception) { + super(message, exception); + } + + public AtlasAuthorizationException(String message, Throwable exception, boolean enableSuppression, + boolean writableStackTrace) { + super(message, exception, enableSuppression, writableStackTrace); + } + + public AtlasAuthorizationException(AtlasAccessRequest request) { + super("Unauthorized Request : " + request); + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java new file mode 100644 index 0000000..9c50a04 --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java @@ -0,0 +1,42 @@ +/** + * 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.atlas.authorize; + + +public interface AtlasAuthorizer { + + + /** + * This method will load the policy file and would initialize the required data-structures. + */ + public void init(); + + /** + * This method is responsible to perform the actual authorization for every REST API call. It will check if + * user can perform action on resource. + */ + public boolean isAccessAllowed(AtlasAccessRequest request) throws AtlasAuthorizationException; + + /** + * This method is responsible to perform the cleanup and release activities. It must be called when you are done + * with the Authorization activity and once it's called a restart would be required. Try to invoke this while + * destroying the context. + */ + public void cleanUp(); +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java new file mode 100644 index 0000000..5aad72d --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.atlas.authorize; + +import org.apache.atlas.ApplicationProperties; +import org.apache.atlas.AtlasException; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AtlasAuthorizerFactory { + + private static final Logger LOG = LoggerFactory.getLogger(AtlasAuthorizerFactory.class); + private static final String SIMPLE_AUTHORIZER = "org.apache.atlas.authorize.simple.SimpleAtlasAuthorizer"; + private static final String RANGER_AUTHORIZER = + "org.apache.ranger.authorization.atlas.authorizer.RangerAtlasAuthorizer"; + private static volatile AtlasAuthorizer INSTANCE = null; + private static boolean isDebugEnabled = LOG.isDebugEnabled(); + + public static AtlasAuthorizer getAtlasAuthorizer() throws AtlasAuthorizationException { + Configuration configuration = null; + try { + configuration = ApplicationProperties.get(); + } catch (AtlasException e) { + if (LOG.isErrorEnabled()) { + LOG.error("Exception while fetching configuration. ", e); + } + } + AtlasAuthorizer ret = INSTANCE; + + if (ret == null) { + synchronized (AtlasAuthorizerFactory.class) { + if (INSTANCE == null) { + String authorizerClass = + configuration != null ? configuration.getString("atlas.authorizer.impl") : "SIMPLE"; + + if (StringUtils.isNotEmpty(authorizerClass)) { + if (StringUtils.equalsIgnoreCase(authorizerClass, "SIMPLE")) { + authorizerClass = SIMPLE_AUTHORIZER; + } else if (StringUtils.equalsIgnoreCase(authorizerClass, "RANGER")) { + authorizerClass = RANGER_AUTHORIZER; + } + } else { + authorizerClass = SIMPLE_AUTHORIZER; + } + + if (isDebugEnabled) { + LOG.debug("Initializing Authorizer :: " + authorizerClass); + } + try { + Class authorizerMetaObject = Class.forName(authorizerClass); + if (authorizerMetaObject != null) { + INSTANCE = (AtlasAuthorizer) authorizerMetaObject.newInstance(); + } + } catch (Exception e) { + LOG.error("Error while creating authorizer of type '" + authorizerClass + "'", e); + throw new AtlasAuthorizationException("Error while creating authorizer of type '" + + authorizerClass + "'", e); + } + ret = INSTANCE; + } + } + } + return ret; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/AtlasResourceTypes.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasResourceTypes.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasResourceTypes.java new file mode 100644 index 0000000..e34c740 --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasResourceTypes.java @@ -0,0 +1,23 @@ +/** + * 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.atlas.authorize; + +public enum AtlasResourceTypes { + UNKNOWN, ENTITY, TYPE, OPERATION, TAXONOMY, TERM; +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtils.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtils.java b/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtils.java new file mode 100644 index 0000000..48b536f --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtils.java @@ -0,0 +1,131 @@ +/** + * 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.atlas.authorize.simple; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.atlas.AtlasClient; +import org.apache.atlas.authorize.AtlasActionTypes; +import org.apache.atlas.authorize.AtlasResourceTypes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AtlasAuthorizationUtils { + private static final Logger LOG = LoggerFactory.getLogger(AtlasAuthorizationUtils.class); + private static boolean isDebugEnabled = LOG.isDebugEnabled(); + private static final String BASE_URL = "/" + AtlasClient.BASE_URI; + + public static String getApi(String contextPath) { + if (isDebugEnabled) { + LOG.debug("==> getApi from " + contextPath); + } + if (contextPath.startsWith(BASE_URL)) { + contextPath = contextPath.substring(BASE_URL.length()); + } else { + // strip of leading '/' + if (contextPath.startsWith("/")) { + contextPath = contextPath.substring(1); + } + } + String[] split = contextPath.split("/", 3); + String api = split[0]; + if (split.length > 1) { + return (!api.equals("v1")) ? api : String.format("v1/%s", split[1]); + } else { + return api; + } + } + + public static AtlasActionTypes getAtlasAction(String method) { + AtlasActionTypes action = null; + + switch (method.toUpperCase()) { + case "POST": + action = AtlasActionTypes.CREATE; + break; + case "GET": + action = AtlasActionTypes.READ; + break; + case "PUT": + action = AtlasActionTypes.UPDATE; + break; + case "DELETE": + action = AtlasActionTypes.DELETE; + break; + default: + if (isDebugEnabled) { + LOG.debug("getAtlasAction(): Invalid HTTP method '" + method + "'"); + } + break; + } + + if (isDebugEnabled) { + LOG.debug("<== AtlasAuthorizationFilter getAtlasAction HTTP Method " + method + " mapped to AtlasAction : " + + action); + } + return action; + } + + /** + * @param contextPath + * @return set of AtlasResourceTypes types api mapped with AtlasResourceTypes.TYPE eg :- /api/atlas/types/* + * + * gremlin discovery,admin,graph apis are mapped with AtlasResourceTypes.OPERATION eg :-/api/atlas/admin/* + * /api/atlas/discovery/search/gremlin /api/atlas/graph/* + * + * entities,lineage and discovery apis are mapped with AtlasResourceTypes.ENTITY eg :- /api/atlas/lineage/hive/table/* + * /api/atlas/entities/{guid}* /api/atlas/discovery/* + * + * unprotected types are mapped with AtlasResourceTypes.UNKNOWN, access to these are allowed. + */ + public static Set<AtlasResourceTypes> getAtlasResourceType(String contextPath) { + Set<AtlasResourceTypes> resourceTypes = new HashSet<AtlasResourceTypes>(); + if (isDebugEnabled) { + LOG.debug("==> getAtlasResourceType for " + contextPath); + } + String api = getApi(contextPath); + if (api.startsWith("types")) { + resourceTypes.add(AtlasResourceTypes.TYPE); + } else if ((api.startsWith("discovery") && contextPath.contains("/gremlin")) || api.startsWith("admin") + || api.startsWith("graph")) { + resourceTypes.add(AtlasResourceTypes.OPERATION); + } else if (api.startsWith("entities") || api.startsWith("lineage") || api.startsWith("discovery")) { + resourceTypes.add(AtlasResourceTypes.ENTITY); + } else if (api.startsWith("v1/taxonomies")) { + resourceTypes.add(AtlasResourceTypes.TAXONOMY); + // taxonomies are modeled as entities + resourceTypes.add(AtlasResourceTypes.ENTITY); + if (contextPath.contains("/terms")) { + resourceTypes.add(AtlasResourceTypes.TERM); + } + } else if (api.startsWith("v1/entities")) { + resourceTypes.add(AtlasResourceTypes.ENTITY); + } else { + LOG.error("Unable to find Atlas Resource corresponding to : " + api + "\nSetting " + + AtlasResourceTypes.UNKNOWN.name()); + resourceTypes.add(AtlasResourceTypes.UNKNOWN); + } + + if (isDebugEnabled) { + LOG.debug("<== Returning AtlasResources " + resourceTypes + " for api " + api); + } + return resourceTypes; + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/simple/FileReaderUtil.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/simple/FileReaderUtil.java b/authorization/src/main/java/org/apache/atlas/authorize/simple/FileReaderUtil.java new file mode 100644 index 0000000..cda0b1c --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/simple/FileReaderUtil.java @@ -0,0 +1,56 @@ +/** + * 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.atlas.authorize.simple; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; + +public class FileReaderUtil { + private static Logger LOG = Logger.getLogger(FileReaderUtil.class); + private static boolean isDebugEnabled = LOG.isDebugEnabled(); + + public static List<String> readFile(String path) throws IOException { + if (isDebugEnabled) { + LOG.debug("==> FileReaderUtil readFile"); + } + List<String> list = new ArrayList<String>(); + LOG.info("reading the file" + path); + List<String> fileLines = Files.readAllLines(Paths.get(path), Charset.forName("UTF-8")); + if (fileLines != null) { + for (String line : fileLines) { + if ((!line.startsWith("##")) && Pattern.matches(".+;;.*;;.*;;.+", line)) + list.add(line); + } + } + + if (isDebugEnabled) { + LOG.debug("<== FileReaderUtil readFile"); + LOG.debug("Policies read :: " + list); + } + + return list; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyDef.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyDef.java b/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyDef.java new file mode 100644 index 0000000..6b2b8b3 --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyDef.java @@ -0,0 +1,70 @@ +/** 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.atlas.authorize.simple; + +import java.util.List; +import java.util.Map; + +import org.apache.atlas.authorize.AtlasActionTypes; +import org.apache.atlas.authorize.AtlasResourceTypes; + +public class PolicyDef { + + private String policyName; + private Map<String, List<AtlasActionTypes>> users; + private Map<String, List<AtlasActionTypes>> groups; + private Map<AtlasResourceTypes, List<String>> resources; + + public String getPolicyName() { + return policyName; + } + + public void setPolicyName(String policyName) { + this.policyName = policyName; + } + + public Map<String, List<AtlasActionTypes>> getUsers() { + return users; + } + + public void setUsers(Map<String, List<AtlasActionTypes>> users) { + this.users = users; + } + + public Map<String, List<AtlasActionTypes>> getGroups() { + return groups; + } + + public void setGroups(Map<String, List<AtlasActionTypes>> groups) { + this.groups = groups; + } + + public Map<AtlasResourceTypes, List<String>> getResources() { + return resources; + } + + public void setResources(Map<AtlasResourceTypes, List<String>> resources) { + this.resources = resources; + } + + @Override + public String toString() { + return "PolicyDef [policyName=" + policyName + ", users=" + users + ", groups=" + groups + ", resources=" + + resources + "]"; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyParser.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyParser.java b/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyParser.java new file mode 100644 index 0000000..25692e1 --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyParser.java @@ -0,0 +1,265 @@ +/** + * 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.atlas.authorize.simple; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import org.apache.atlas.authorize.AtlasActionTypes; +import org.apache.atlas.authorize.AtlasResourceTypes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import scala.tools.jline.internal.Log; + +public class PolicyParser { + + private static Logger LOG = LoggerFactory.getLogger(PolicyParser.class); + private static boolean isDebugEnabled = LOG.isDebugEnabled(); + public static final int POLICYNAME = 0; + + public static final int USER_INDEX = 1; + public static final int USERNAME = 0; + public static final int USER_AUTHORITIES = 1; + + public static final int GROUP_INDEX = 2; + public static final int GROUPNAME = 0; + public static final int GROUP_AUTHORITIES = 1; + + public static final int RESOURCE_INDEX = 3; + public static final int RESOURCE_TYPE = 0; + public static final int RESOURCE_NAME = 1; + + private List<AtlasActionTypes> getListOfAutorities(String auth) { + if (isDebugEnabled) { + LOG.debug("==> PolicyParser getListOfAutorities"); + } + List<AtlasActionTypes> authorities = new ArrayList<AtlasActionTypes>(); + + for (int i = 0; i < auth.length(); i++) { + char access = auth.toLowerCase().charAt(i); + switch (access) { + case 'r': + authorities.add(AtlasActionTypes.READ); + break; + case 'w': + authorities.add(AtlasActionTypes.CREATE); + break; + case 'u': + authorities.add(AtlasActionTypes.UPDATE); + break; + case 'd': + authorities.add(AtlasActionTypes.DELETE); + break; + + default: + if (LOG.isErrorEnabled()) { + LOG.error("Invalid action: '" + access + "'"); + } + break; + } + } + if (isDebugEnabled) { + LOG.debug("<== PolicyParser getListOfAutorities"); + } + return authorities; + } + + public List<PolicyDef> parsePolicies(List<String> policies) { + if (isDebugEnabled) { + LOG.debug("==> PolicyParser parsePolicies"); + } + List<PolicyDef> policyDefs = new ArrayList<PolicyDef>(); + for (String policy : policies) { + PolicyDef policyDef = parsePolicy(policy); + if (policyDef != null) { + policyDefs.add(policyDef); + } + } + if (isDebugEnabled) { + LOG.debug("<== PolicyParser parsePolicies"); + LOG.debug(policyDefs.toString()); + } + return policyDefs; + } + + private PolicyDef parsePolicy(String data) { + if (isDebugEnabled) { + LOG.debug("==> PolicyParser parsePolicy"); + } + PolicyDef def = null; + String[] props = data.split(";;"); + + if (props.length < RESOURCE_INDEX) { + LOG.warn("skipping invalid policy line: " + data); + } else { + def = new PolicyDef(); + def.setPolicyName(props[POLICYNAME]); + parseUsers(props[USER_INDEX], def); + parseGroups(props[GROUP_INDEX], def); + parseResources(props[RESOURCE_INDEX], def); + if (isDebugEnabled) { + LOG.debug("policy successfully parsed!!!"); + LOG.debug("<== PolicyParser parsePolicy"); + } + } + return def; + } + + private boolean validateEntity(String entity) { + if (isDebugEnabled) { + LOG.debug("==> PolicyParser validateEntity"); + } + boolean isValidEntity = Pattern.matches("(.+:.+)+", entity); + boolean isEmpty = entity.isEmpty(); + if (isValidEntity == false || isEmpty == true) { + if (isDebugEnabled) { + LOG.debug("group/user/resource not properly define in Policy"); + LOG.debug("<== PolicyParser validateEntity"); + } + return false; + } else { + if (isDebugEnabled) { + LOG.debug("<== PolicyParser validateEntity"); + } + return true; + } + + } + + private void parseUsers(String usersDef, PolicyDef def) { + if (isDebugEnabled) { + LOG.debug("==> PolicyParser parseUsers"); + } + String[] users = usersDef.split(","); + String[] userAndRole = null; + Map<String, List<AtlasActionTypes>> usersMap = new HashMap<String, List<AtlasActionTypes>>(); + if (validateEntity(usersDef)) { + for (String user : users) { + if (!Pattern.matches("(.+:.+)+", user)) { + continue; + } + userAndRole = user.split(":"); + if (def.getUsers() != null) { + usersMap = def.getUsers(); + } + List<AtlasActionTypes> userAutorities = usersMap.get(userAndRole[USERNAME]); + if (userAutorities == null) { + + userAutorities = new ArrayList<AtlasActionTypes>(); + } + userAutorities = getListOfAutorities(userAndRole[USER_AUTHORITIES]); + usersMap.put(userAndRole[USERNAME], userAutorities); + def.setUsers(usersMap); + } + + } else { + def.setUsers(usersMap); + } + if (isDebugEnabled) { + LOG.debug("<== PolicyParser parseUsers"); + } + } + + private void parseGroups(String groupsDef, PolicyDef def) { + if (isDebugEnabled) { + LOG.debug("==> PolicyParser parseGroups"); + } + String[] groups = groupsDef.split("\\,"); + String[] groupAndRole = null; + Map<String, List<AtlasActionTypes>> groupsMap = new HashMap<String, List<AtlasActionTypes>>(); + if (validateEntity(groupsDef.trim())) { + for (String group : groups) { + if (!Pattern.matches("(.+:.+)+", group)) { + continue; + } + groupAndRole = group.split("[:]"); + if (def.getGroups() != null) { + groupsMap = def.getGroups(); + } + List<AtlasActionTypes> groupAutorities = groupsMap.get(groupAndRole[GROUPNAME]); + if (groupAutorities == null) { + groupAutorities = new ArrayList<AtlasActionTypes>(); + } + groupAutorities = getListOfAutorities(groupAndRole[GROUP_AUTHORITIES]); + groupsMap.put(groupAndRole[GROUPNAME], groupAutorities); + def.setGroups(groupsMap); + } + + } else { + def.setGroups(groupsMap); + } + if (isDebugEnabled) { + LOG.debug("<== PolicyParser parseGroups"); + } + + } + + private void parseResources(String resourceDef, PolicyDef def) { + if (isDebugEnabled) { + LOG.debug("==> PolicyParser parseResources"); + } + String[] resources = resourceDef.split(","); + String[] resourceTypeAndName = null; + Map<AtlasResourceTypes, List<String>> resourcesMap = new HashMap<AtlasResourceTypes, List<String>>(); + if (validateEntity(resourceDef)) { + for (String resource : resources) { + if (!Pattern.matches("(.+:.+)+", resource)) { + continue; + } + resourceTypeAndName = resource.split("[:]"); + if (def.getResources() != null) { + resourcesMap = def.getResources(); + } + AtlasResourceTypes resourceType = null; + String type = resourceTypeAndName[RESOURCE_TYPE].toUpperCase(); + if (type.equalsIgnoreCase("ENTITY")) { + resourceType = AtlasResourceTypes.ENTITY; + } else if (type.equalsIgnoreCase("OPERATION")) { + resourceType = AtlasResourceTypes.OPERATION; + } else if (type.equalsIgnoreCase("TYPE")) { + resourceType = AtlasResourceTypes.TYPE; + } else if (type.equalsIgnoreCase("TAXONOMY")) { + resourceType = AtlasResourceTypes.TAXONOMY; + } else if (type.equalsIgnoreCase("TERM")) { + resourceType = AtlasResourceTypes.TERM; + } else { + Log.warn(type + " is invalid resource please check PolicyStore file"); + continue; + } + + List<String> resourceList = resourcesMap.get(resourceType); + if (resourceList == null) { + resourceList = new ArrayList<String>(); + } + resourceList.add(resourceTypeAndName[RESOURCE_NAME]); + resourcesMap.put(resourceType, resourceList); + def.setResources(resourcesMap); + } + } else { + def.setResources(resourcesMap); + } + if (isDebugEnabled) { + LOG.debug("<== PolicyParser parseResources"); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyUtil.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyUtil.java b/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyUtil.java new file mode 100644 index 0000000..9508eb3 --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyUtil.java @@ -0,0 +1,103 @@ +/** 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.atlas.authorize.simple; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.atlas.authorize.AtlasActionTypes; +import org.apache.atlas.authorize.AtlasResourceTypes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PolicyUtil { + + private static Logger LOG = LoggerFactory.getLogger(PolicyUtil.class); + private static boolean isDebugEnabled = LOG.isDebugEnabled(); + + + public Map<String, Map<AtlasResourceTypes, List<String>>> createPermissionMap(List<PolicyDef> policyDefList, + AtlasActionTypes permissionType, SimpleAtlasAuthorizer.AtlasAccessorTypes principalType) { + if (isDebugEnabled) { + LOG.debug("==> PolicyUtil createPermissionMap" + "\nCreating Permission Map for :: " + permissionType + + " & " + principalType); + } + Map<String, Map<AtlasResourceTypes, List<String>>> userReadMap = + new HashMap<String, Map<AtlasResourceTypes, List<String>>>(); + + // Iterate over the list of policies to create map + for (PolicyDef policyDef : policyDefList) { + LOG.info("Processing policy def : " + policyDef); + Map<String, List<AtlasActionTypes>> principalMap = + principalType.equals(SimpleAtlasAuthorizer.AtlasAccessorTypes.USER) ? policyDef.getUsers() : policyDef + .getGroups(); + // For every policy extract the resource list and populate the user map + for (Entry<String, List<AtlasActionTypes>> e : principalMap.entrySet()) { + // Check if the user has passed permission type like READ + if (!e.getValue().contains(permissionType)) { + continue; + } + // See if the current user is already added to map + String username = e.getKey(); + Map<AtlasResourceTypes, List<String>> userResourceList = userReadMap.get(username); + + // If its not added then create a new resource list + if (userResourceList == null) { + if (isDebugEnabled) { + LOG.debug("Resource list not found for " + username + ", creating it"); + } + userResourceList = new HashMap<AtlasResourceTypes, List<String>>(); + } + /* + * Iterate over resources from the current policy def and update the resource list for the current user + */ + for (Entry<AtlasResourceTypes, List<String>> resourceTypeMap : policyDef.getResources().entrySet()) { + // For the current resourceType in the policyDef, get the + // current list of resources already added + AtlasResourceTypes type = resourceTypeMap.getKey(); + List<String> resourceList = userResourceList.get(type); + + if (resourceList == null) { + // if the resource list was not added for this type then + // create and add all the resources in this policy + resourceList = new ArrayList<String>(); + resourceList.addAll(resourceTypeMap.getValue()); + } else { + // if the resource list is present then merge both the + // list + resourceList.removeAll(resourceTypeMap.getValue()); + resourceList.addAll(resourceTypeMap.getValue()); + } + + userResourceList.put(type, resourceList); + } + userReadMap.put(username, userResourceList); + LOG.info("userReadMap " + userReadMap); + } + } + if (isDebugEnabled) { + LOG.debug("Returning Map for " + principalType + " :: " + userReadMap); + LOG.debug("<== PolicyUtil createPermissionMap"); + } + return userReadMap; + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/main/java/org/apache/atlas/authorize/simple/SimpleAtlasAuthorizer.java ---------------------------------------------------------------------- diff --git a/authorization/src/main/java/org/apache/atlas/authorize/simple/SimpleAtlasAuthorizer.java b/authorization/src/main/java/org/apache/atlas/authorize/simple/SimpleAtlasAuthorizer.java new file mode 100644 index 0000000..23fc924 --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/simple/SimpleAtlasAuthorizer.java @@ -0,0 +1,387 @@ +/** + * 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.atlas.authorize.simple; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.Map; + +import org.apache.atlas.ApplicationProperties; +import org.apache.atlas.AtlasException; +import org.apache.atlas.authorize.AtlasAccessRequest; +import org.apache.atlas.authorize.AtlasActionTypes; +import org.apache.atlas.authorize.AtlasAuthorizationException; +import org.apache.atlas.authorize.AtlasAuthorizer; +import org.apache.atlas.authorize.AtlasResourceTypes; +import org.apache.atlas.utils.PropertiesUtil; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOCase; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.annotations.VisibleForTesting; + +public final class SimpleAtlasAuthorizer implements AtlasAuthorizer { + + public enum AtlasAccessorTypes { + USER, GROUP; + } + + private static final Logger LOG = LoggerFactory.getLogger(SimpleAtlasAuthorizer.class); + private boolean isDebugEnabled = LOG.isDebugEnabled(); + private final static String WILDCARD_ASTERISK = "*"; + private final static String WILDCARDS = "*?"; + private boolean optIgnoreCase = false; + + private Map<String, Map<AtlasResourceTypes, List<String>>> userReadMap = null; + private Map<String, Map<AtlasResourceTypes, List<String>>> userWriteMap = null; + private Map<String, Map<AtlasResourceTypes, List<String>>> userUpdateMap = null; + private Map<String, Map<AtlasResourceTypes, List<String>>> userDeleteMap = null; + private Map<String, Map<AtlasResourceTypes, List<String>>> groupReadMap = null; + private Map<String, Map<AtlasResourceTypes, List<String>>> groupWriteMap = null; + private Map<String, Map<AtlasResourceTypes, List<String>>> groupUpdateMap = null; + private Map<String, Map<AtlasResourceTypes, List<String>>> groupDeleteMap = null; + + public SimpleAtlasAuthorizer() { + } + + + @Override + public void init() { + if (isDebugEnabled) { + LOG.debug("==> SimpleAtlasAuthorizer init"); + } + try { + + PolicyUtil util = new PolicyUtil(); + PolicyParser parser = new PolicyParser(); + optIgnoreCase = Boolean.valueOf(PropertiesUtil.getProperty("optIgnoreCase", "false")); + + if (isDebugEnabled) { + LOG.debug("Read from PropertiesUtil --> optIgnoreCase :: " + optIgnoreCase); + } + + Configuration configuration = ApplicationProperties.get(); + String policyStorePath = configuration.getString("atlas.auth.policy.file", System.getProperty("atlas.conf")+"/policy-store.txt"); + + if (isDebugEnabled) { + LOG.debug("Loading Apache Atlas policies from : " + policyStorePath); + } + + List<String> policies = FileReaderUtil.readFile(policyStorePath); + List<PolicyDef> policyDef = parser.parsePolicies(policies); + + userReadMap = util.createPermissionMap(policyDef, AtlasActionTypes.READ, AtlasAccessorTypes.USER); + userWriteMap = util.createPermissionMap(policyDef, AtlasActionTypes.CREATE, AtlasAccessorTypes.USER); + userUpdateMap = util.createPermissionMap(policyDef, AtlasActionTypes.UPDATE, AtlasAccessorTypes.USER); + userDeleteMap = util.createPermissionMap(policyDef, AtlasActionTypes.DELETE, AtlasAccessorTypes.USER); + + groupReadMap = util.createPermissionMap(policyDef, AtlasActionTypes.READ, AtlasAccessorTypes.GROUP); + groupWriteMap = util.createPermissionMap(policyDef, AtlasActionTypes.CREATE, AtlasAccessorTypes.GROUP); + groupUpdateMap = util.createPermissionMap(policyDef, AtlasActionTypes.UPDATE, AtlasAccessorTypes.GROUP); + groupDeleteMap = util.createPermissionMap(policyDef, AtlasActionTypes.DELETE, AtlasAccessorTypes.GROUP); + + if (isDebugEnabled) { + LOG.debug("\n\nUserReadMap :: " + userReadMap + "\nGroupReadMap :: " + groupReadMap); + LOG.debug("\n\nUserWriteMap :: " + userWriteMap + "\nGroupWriteMap :: " + groupWriteMap); + LOG.debug("\n\nUserUpdateMap :: " + userUpdateMap + "\nGroupUpdateMap :: " + groupUpdateMap); + LOG.debug("\n\nUserDeleteMap :: " + userDeleteMap + "\nGroupDeleteMap :: " + groupDeleteMap); + } + + } catch (IOException | AtlasException e) { + if (LOG.isErrorEnabled()) { + LOG.error("SimpleAtlasAuthorizer could not be initialized properly due to : ", e); + } + } + } + + @Override + public boolean isAccessAllowed(AtlasAccessRequest request) throws AtlasAuthorizationException { + if (isDebugEnabled) { + LOG.debug("==> SimpleAtlasAuthorizer isAccessAllowed"); + LOG.debug("isAccessAllowd(" + request + ")"); + } + String user = request.getUser(); + Set<String> groups = request.getUserGroups(); + AtlasActionTypes action = request.getAction(); + String resource = request.getResource(); + Set<AtlasResourceTypes> resourceTypes = request.getResourceTypes(); + if (isDebugEnabled) + LOG.debug("Checking for :: \nUser :: " + user + "\nGroups :: " + groups + "\nAction :: " + action + + "\nResource :: " + resource); + + boolean isAccessAllowed = false; + boolean isUser = user == null ? false : true; + boolean isGroup = groups == null ? false : true; + + if ((!isUser && !isGroup) || action == null || resource == null) { + if (isDebugEnabled) { + LOG.debug("Please check the formation AtlasAccessRequest."); + } + return isAccessAllowed; + } else { + if (isDebugEnabled) { + LOG.debug("checkAccess for Operation :: " + action + " on Resource " + resourceTypes + ":" + resource); + } + switch (action) { + case READ: + isAccessAllowed = checkAccess(user, resourceTypes, resource, userReadMap); + isAccessAllowed = + isAccessAllowed == false ? checkAccessForGroups(groups, resourceTypes, resource, groupReadMap) + : isAccessAllowed; + break; + case CREATE: + isAccessAllowed = checkAccess(user, resourceTypes, resource, userWriteMap); + isAccessAllowed = + isAccessAllowed == false ? checkAccessForGroups(groups, resourceTypes, resource, groupWriteMap) + : isAccessAllowed; + break; + case UPDATE: + isAccessAllowed = checkAccess(user, resourceTypes, resource, userUpdateMap); + isAccessAllowed = + isAccessAllowed == false + ? checkAccessForGroups(groups, resourceTypes, resource, groupUpdateMap) : isAccessAllowed; + break; + case DELETE: + isAccessAllowed = checkAccess(user, resourceTypes, resource, userDeleteMap); + isAccessAllowed = + isAccessAllowed == false + ? checkAccessForGroups(groups, resourceTypes, resource, groupDeleteMap) : isAccessAllowed; + break; + default: + if (isDebugEnabled) { + LOG.debug("Invalid Action " + action+"\nRaising AtlasAuthorizationException!!!"); + } + throw new AtlasAuthorizationException("Invalid Action :: " + action); + } + } + + if (isDebugEnabled) { + LOG.debug("<== SimpleAtlasAuthorizer isAccessAllowed = " + isAccessAllowed); + } + + return isAccessAllowed; + } + + private boolean checkAccess(String accessor, Set<AtlasResourceTypes> resourceTypes, String resource, + Map<String, Map<AtlasResourceTypes, List<String>>> map) { + if (isDebugEnabled) { + LOG.debug("==> SimpleAtlasAuthorizer checkAccess"); + LOG.debug("Now checking access for accessor : " + accessor + "\nResource Types : " + resourceTypes + + "\nResource : " + resource + "\nMap : " + map); + } + boolean result = true; + Map<AtlasResourceTypes, List<String>> rescMap = map.get(accessor); + if (rescMap != null) { + for (AtlasResourceTypes resourceType : resourceTypes) { + List<String> accessList = rescMap.get(resourceType); + if (isDebugEnabled) { + LOG.debug("\nChecking for resource : " + resource + " in list : " + accessList + "\n"); + } + if (accessList != null) { + result = result && isMatch(resource, accessList); + } else { + result = false; + } + } + } else { + result = false; + if (isDebugEnabled) + LOG.debug("Key " + accessor + " missing. Returning with result : " + result); + } + + if (isDebugEnabled) { + LOG.debug("Check for " + accessor + " :: " + result); + LOG.debug("<== SimpleAtlasAuthorizer checkAccess"); + } + return result; + } + + private boolean checkAccessForGroups(Set<String> groups, Set<AtlasResourceTypes> resourceType, String resource, + Map<String, Map<AtlasResourceTypes, List<String>>> map) { + boolean isAccessAllowed = false; + if (isDebugEnabled) { + LOG.debug("==> SimpleAtlasAuthorizer checkAccessForGroups"); + } + + for (String group : groups) { + isAccessAllowed = checkAccess(group, resourceType, resource, map); + if (isAccessAllowed) { + break; + } + } + + if (isDebugEnabled) { + LOG.debug("<== SimpleAtlasAuthorizer checkAccessForGroups"); + } + return isAccessAllowed; + } + + private boolean resourceMatchHelper(List<String> policyResource) { + boolean isMatchAny = false; + if (isDebugEnabled) { + LOG.debug("==> SimpleAtlasAuthorizer resourceMatchHelper"); + } + + boolean optWildCard = true; + + List<String> policyValues = new ArrayList<String>(); + + if (policyResource != null) { + boolean isWildCardPresent = !optWildCard; + for (String policyValue : policyResource) { + if (StringUtils.isEmpty(policyValue)) { + continue; + } + if (StringUtils.containsOnly(policyValue, WILDCARD_ASTERISK)) { + isMatchAny = true; + } else if (!isWildCardPresent && StringUtils.containsAny(policyValue, WILDCARDS)) { + isWildCardPresent = true; + } + policyValues.add(policyValue); + } + optWildCard = optWildCard && isWildCardPresent; + } else { + isMatchAny = false; + } + + if (isDebugEnabled) { + LOG.debug("<== SimpleAtlasAuthorizer resourceMatchHelper"); + } + return isMatchAny; + } + + private boolean isMatch(String resource, List<String> policyValues) { + if (isDebugEnabled) { + LOG.debug("==> SimpleAtlasAuthorizer isMatch"); + } + boolean isMatchAny = resourceMatchHelper(policyValues); + boolean isMatch = false; + boolean allValuesRequested = isAllValuesRequested(resource); + + if (allValuesRequested || isMatchAny) { + isMatch = isMatchAny; + } else { + for (String policyValue : policyValues) { + if (policyValue.contains("*")) { + isMatch = + optIgnoreCase ? FilenameUtils.wildcardMatch(resource, policyValue, IOCase.INSENSITIVE) + : FilenameUtils.wildcardMatch(resource, policyValue, IOCase.SENSITIVE); + } else { + isMatch = + optIgnoreCase ? StringUtils.equalsIgnoreCase(resource, policyValue) : StringUtils.equals( + resource, policyValue); + } + if (isMatch) { + break; + } + } + } + + if (isMatch == false) { + + if (isDebugEnabled) { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (String policyValue : policyValues) { + sb.append(policyValue); + sb.append(" "); + } + sb.append("]"); + + LOG.debug("AtlasDefaultResourceMatcher.isMatch returns FALSE, (resource=" + resource + + ", policyValues=" + sb.toString() + ")"); + } + + } + + if (isDebugEnabled) { + LOG.debug("<== SimpleAtlasAuthorizer isMatch(" + resource + "): " + isMatch); + } + + return isMatch; + } + + private boolean isAllValuesRequested(String resource) { + boolean result = StringUtils.isEmpty(resource) || WILDCARD_ASTERISK.equals(resource); + return result; + } + + @Override + public void cleanUp() { + if (isDebugEnabled) { + LOG.debug("==> +SimpleAtlasAuthorizer cleanUp"); + } + userReadMap = null; + userWriteMap = null; + userUpdateMap = null; + userDeleteMap = null; + groupReadMap = null; + groupWriteMap = null; + groupUpdateMap = null; + groupDeleteMap = null; + if (isDebugEnabled) { + LOG.debug("<== +SimpleAtlasAuthorizer cleanUp"); + } + } + + /* + * NOTE :: This method is added for setting the maps for testing purpose. + */ + @VisibleForTesting + public void setResourcesForTesting(Map<String, Map<AtlasResourceTypes, List<String>>> userMap, + Map<String, Map<AtlasResourceTypes, List<String>>> groupMap, AtlasActionTypes actionTypes) { + + switch (actionTypes) { + case READ: + this.userReadMap = userMap; + this.groupReadMap = groupMap; + break; + + case CREATE: + + this.userWriteMap = userMap; + this.groupWriteMap = groupMap; + break; + case UPDATE: + + this.userUpdateMap = userMap; + this.groupUpdateMap = groupMap; + break; + case DELETE: + + this.userDeleteMap = userMap; + this.groupDeleteMap = groupMap; + break; + + default: + if (isDebugEnabled) { + LOG.debug("No such action available"); + } + break; + } + } + +} + + http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/test/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtilsTest.java ---------------------------------------------------------------------- diff --git a/authorization/src/test/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtilsTest.java b/authorization/src/test/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtilsTest.java new file mode 100644 index 0000000..326cb3c --- /dev/null +++ b/authorization/src/test/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtilsTest.java @@ -0,0 +1,118 @@ +/** + * 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.atlas.authorize.simple; + +import org.apache.atlas.authorize.AtlasResourceTypes; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/** + * Unit tests for AtlasAuthorizationUtils. + */ +public class AtlasAuthorizationUtilsTest { + @Test + public void testGetApi() { + String contextPath = "/api/atlas/entities"; + assertEquals(AtlasAuthorizationUtils.getApi(contextPath), "entities"); + + contextPath = "/api/atlas/entities/111/traits"; + assertEquals(AtlasAuthorizationUtils.getApi(contextPath), "entities"); + + contextPath = "/api/atlas/v1/entities"; + assertEquals(AtlasAuthorizationUtils.getApi(contextPath), "v1/entities"); + + contextPath = "/api/atlas/v1/entities/111/tags"; + assertEquals(AtlasAuthorizationUtils.getApi(contextPath), "v1/entities"); + + // not sure of this use case but the code appears to support url's that don't + // begin with base url. + contextPath = "/foo/bar"; + assertEquals(AtlasAuthorizationUtils.getApi(contextPath), "foo"); + } + + @Test + public void testGetAtlasResourceType() throws Exception { + String contextPath = "/api/atlas/types"; + Set<AtlasResourceTypes> resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 1); + assertTrue(resourceTypes.contains(AtlasResourceTypes.TYPE)); + + contextPath = "/api/atlas/admin/foo"; + resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 1); + assertTrue(resourceTypes.contains(AtlasResourceTypes.OPERATION)); + + contextPath = "/api/atlas/graph/foo"; + resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 1); + assertTrue(resourceTypes.contains(AtlasResourceTypes.OPERATION)); + + contextPath = "/api/atlas/discovery/search/gremlin"; + resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 1); + assertTrue(resourceTypes.contains(AtlasResourceTypes.OPERATION)); + + contextPath = "/api/atlas/entities/111/traits"; + resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 1); + assertTrue(resourceTypes.contains(AtlasResourceTypes.ENTITY)); + + contextPath = "/api/atlas/discovery/search"; + resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 1); + assertTrue(resourceTypes.contains(AtlasResourceTypes.ENTITY)); + + contextPath = "/api/atlas/entities?type=Column"; + resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 1); + assertTrue(resourceTypes.contains(AtlasResourceTypes.ENTITY)); + + contextPath = "/api/atlas/lineage"; + resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 1); + assertTrue(resourceTypes.contains(AtlasResourceTypes.ENTITY)); + + contextPath = "/api/atlas/v1/taxonomies"; + resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 2); + assertTrue(resourceTypes.contains(AtlasResourceTypes.TAXONOMY)); + assertTrue(resourceTypes.contains(AtlasResourceTypes.ENTITY)); + + contextPath = "/api/atlas/v1/taxonomies/taxonomy1/terms"; + resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 3); + assertTrue(resourceTypes.contains(AtlasResourceTypes.TAXONOMY)); + assertTrue(resourceTypes.contains(AtlasResourceTypes.ENTITY)); + assertTrue(resourceTypes.contains(AtlasResourceTypes.TERM)); + + contextPath = "/api/atlas/v1/entities/111"; + resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 1); + assertTrue(resourceTypes.contains(AtlasResourceTypes.ENTITY)); + + contextPath = "/api/atlas/v1/entities/111/tags/foo"; + resourceTypes = AtlasAuthorizationUtils.getAtlasResourceType(contextPath); + assertEquals(resourceTypes.size(), 1); + assertTrue(resourceTypes.contains(AtlasResourceTypes.ENTITY)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/test/java/org/apache/atlas/authorize/simple/PolicyParserTest.java ---------------------------------------------------------------------- diff --git a/authorization/src/test/java/org/apache/atlas/authorize/simple/PolicyParserTest.java b/authorization/src/test/java/org/apache/atlas/authorize/simple/PolicyParserTest.java new file mode 100644 index 0000000..453364d --- /dev/null +++ b/authorization/src/test/java/org/apache/atlas/authorize/simple/PolicyParserTest.java @@ -0,0 +1,172 @@ +/* + * 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.atlas.authorize.simple; + +import static org.testng.AssertJUnit.assertEquals; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.atlas.authorize.AtlasActionTypes; +import org.apache.atlas.authorize.AtlasResourceTypes; +import org.apache.atlas.authorize.simple.PolicyDef; +import org.apache.atlas.authorize.simple.PolicyParser; +import org.testng.annotations.Test; + +public class PolicyParserTest { + + @Test + public void testParsePoliciesWithAllProperties() { + List<String> policies = new ArrayList<String>(); + policies.add("hivePolicy;;usr1:r,usr2:rw;;grp1:rwu,grp2:u;;entity:*abc,operation:*xyz,type:PII"); + /* Creating group data */ + Map<String, List<AtlasActionTypes>> groupMap = new HashMap<String, List<AtlasActionTypes>>(); + List<AtlasActionTypes> accessList1 = new ArrayList<AtlasActionTypes>(); + accessList1.add(AtlasActionTypes.READ); + accessList1.add(AtlasActionTypes.CREATE); + accessList1.add(AtlasActionTypes.UPDATE); + + groupMap.put("grp1", accessList1); + List<AtlasActionTypes> accessList2 = new ArrayList<AtlasActionTypes>(); + accessList2.add(AtlasActionTypes.UPDATE); + groupMap.put("grp2", accessList2); + + /* Creating user data */ + Map<String, List<AtlasActionTypes>> usersMap = new HashMap<String, List<AtlasActionTypes>>(); + List<AtlasActionTypes> usr1AccessList = new ArrayList<AtlasActionTypes>(); + usr1AccessList.add(AtlasActionTypes.READ); + usersMap.put("usr1", usr1AccessList); + + List<AtlasActionTypes> usr2AccessList = new ArrayList<AtlasActionTypes>(); + usr2AccessList.add(AtlasActionTypes.READ); + usr2AccessList.add(AtlasActionTypes.CREATE); + usersMap.put("usr2", usr2AccessList); + + /* Creating resources data */ + Map<AtlasResourceTypes, List<String>> resourceMap = new HashMap<AtlasResourceTypes, List<String>>(); + List<String> resource1List = new ArrayList<String>(); + resource1List.add("*abc"); + resourceMap.put(AtlasResourceTypes.ENTITY, resource1List); + + List<String> resource2List = new ArrayList<String>(); + resource2List.add("*xyz"); + resourceMap.put(AtlasResourceTypes.OPERATION, resource2List); + + List<String> resource3List = new ArrayList<String>(); + resource3List.add("PII"); + resourceMap.put(AtlasResourceTypes.TYPE, resource3List); + + List<PolicyDef> policyDefs = new PolicyParser().parsePolicies(policies); + for (PolicyDef def : policyDefs) { + + assertEquals(def.getPolicyName(), "hivePolicy"); + assertEquals(def.getGroups(), groupMap); + assertEquals(def.getUsers(), usersMap); + assertEquals(def.getResources(), resourceMap); + + } + + } + + @Test + public void testParsePoliciesWithOutUserProperties() { + List<String> policies = new ArrayList<String>(); + policies.add("hivePolicy;;;;grp1:rwu,grp2:u;;entity:*abc,operation:*xyz,type:PII"); + // Creating group data + Map<String, List<AtlasActionTypes>> groupMap = new HashMap<String, List<AtlasActionTypes>>(); + List<AtlasActionTypes> accessList1 = new ArrayList<AtlasActionTypes>(); + accessList1.add(AtlasActionTypes.READ); + accessList1.add(AtlasActionTypes.CREATE); + accessList1.add(AtlasActionTypes.UPDATE); + + groupMap.put("grp1", accessList1); + List<AtlasActionTypes> accessList2 = new ArrayList<AtlasActionTypes>(); + accessList2.add(AtlasActionTypes.UPDATE); + groupMap.put("grp2", accessList2); + + // Creating user data + Map<String, List<AtlasActionTypes>> usersMap = new HashMap<String, List<AtlasActionTypes>>(); + + // Creating resources data + Map<AtlasResourceTypes, List<String>> resourceMap = new HashMap<AtlasResourceTypes, List<String>>(); + List<String> resource1List = new ArrayList<String>(); + resource1List.add("*abc"); + resourceMap.put(AtlasResourceTypes.ENTITY, resource1List); + + List<String> resource2List = new ArrayList<String>(); + resource2List.add("*xyz"); + resourceMap.put(AtlasResourceTypes.OPERATION, resource2List); + + List<String> resource3List = new ArrayList<String>(); + resource3List.add("PII"); + resourceMap.put(AtlasResourceTypes.TYPE, resource3List); + + List<PolicyDef> policyDefs = new PolicyParser().parsePolicies(policies); + for (PolicyDef def : policyDefs) { + + assertEquals(def.getPolicyName(), "hivePolicy"); + assertEquals(def.getGroups(), groupMap); + assertEquals(def.getUsers(), usersMap); + assertEquals(def.getResources(), resourceMap); + + } + + } + + @Test + public void testParsePoliciesWithOutGroupProperties() { + List<String> policies = new ArrayList<String>(); + policies.add("hivePolicy;;usr1:r,usr2:rw;;;;entity:*abc,operation:*xyz,type:PII"); + // Creating group data + Map<String, List<AtlasActionTypes>> groupMap = new HashMap<String, List<AtlasActionTypes>>(); + + // Creating user data + Map<String, List<AtlasActionTypes>> usersMap = new HashMap<String, List<AtlasActionTypes>>(); + List<AtlasActionTypes> usr1AccessList = new ArrayList<AtlasActionTypes>(); + usr1AccessList.add(AtlasActionTypes.READ); + usersMap.put("usr1", usr1AccessList); + + List<AtlasActionTypes> usr2AccessList = new ArrayList<AtlasActionTypes>(); + usr2AccessList.add(AtlasActionTypes.READ); + usr2AccessList.add(AtlasActionTypes.CREATE); + usersMap.put("usr2", usr2AccessList); + + // Creating resources data + Map<AtlasResourceTypes, List<String>> resourceMap = new HashMap<AtlasResourceTypes, List<String>>(); + List<String> resource1List = new ArrayList<String>(); + resource1List.add("*abc"); + resourceMap.put(AtlasResourceTypes.ENTITY, resource1List); + + List<String> resource2List = new ArrayList<String>(); + resource2List.add("*xyz"); + resourceMap.put(AtlasResourceTypes.OPERATION, resource2List); + + List<String> resource3List = new ArrayList<String>(); + resource3List.add("PII"); + resourceMap.put(AtlasResourceTypes.TYPE, resource3List); + + List<PolicyDef> policyDefs = new PolicyParser().parsePolicies(policies); + for (PolicyDef def : policyDefs) { + assertEquals(def.getPolicyName(), "hivePolicy"); + assertEquals(def.getGroups(), groupMap); + assertEquals(def.getUsers(), usersMap); + assertEquals(def.getResources(), resourceMap); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/353ea964/authorization/src/test/java/org/apache/atlas/authorize/simple/PolicyUtilTest.java ---------------------------------------------------------------------- diff --git a/authorization/src/test/java/org/apache/atlas/authorize/simple/PolicyUtilTest.java b/authorization/src/test/java/org/apache/atlas/authorize/simple/PolicyUtilTest.java new file mode 100644 index 0000000..3453bf0 --- /dev/null +++ b/authorization/src/test/java/org/apache/atlas/authorize/simple/PolicyUtilTest.java @@ -0,0 +1,100 @@ +/* + * 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.atlas.authorize.simple; + +import static org.testng.AssertJUnit.assertEquals; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.atlas.authorize.simple.SimpleAtlasAuthorizer; +import org.apache.atlas.authorize.AtlasActionTypes; +import org.apache.atlas.authorize.AtlasResourceTypes; +import org.apache.atlas.authorize.simple.PolicyDef; +import org.apache.atlas.authorize.simple.PolicyParser; +import org.apache.atlas.authorize.simple.PolicyUtil; +import org.testng.annotations.Test; + +public class PolicyUtilTest { + + @Test + public void testCreatePermissionMap() { + + HashMap<AtlasResourceTypes, List<String>> resourceMap = new HashMap<AtlasResourceTypes, List<String>>(); + List<String> resource1List = new ArrayList<String>(); + resource1List.add("*abc"); + resourceMap.put(AtlasResourceTypes.ENTITY, resource1List); + + List<String> resource2List = new ArrayList<String>(); + resource2List.add("*xyz"); + resourceMap.put(AtlasResourceTypes.OPERATION, resource2List); + + List<String> resource3List = new ArrayList<String>(); + resource3List.add("PII"); + resourceMap.put(AtlasResourceTypes.TYPE, resource3List); + + Map<String, HashMap<AtlasResourceTypes, List<String>>> permissionMap = + new HashMap<String, HashMap<AtlasResourceTypes, List<String>>>(); + permissionMap.put("grp1", resourceMap); + + List<String> policies = new ArrayList<String>(); + policies.add("hivePolicy;;usr1:r,usr2:rw;;grp1:rwu,grp2:u;;entity:*abc,operation:*xyz,type:PII"); + List<PolicyDef> policyDefList = new PolicyParser().parsePolicies(policies); + + Map<String, Map<AtlasResourceTypes, List<String>>> createdPermissionMap = + new PolicyUtil().createPermissionMap(policyDefList, AtlasActionTypes.READ, SimpleAtlasAuthorizer.AtlasAccessorTypes.GROUP); + + assertEquals(permissionMap, createdPermissionMap); + + } + + @Test + public void testMergeCreatePermissionMap() { + + HashMap<AtlasResourceTypes, List<String>> resourceMap = new HashMap<AtlasResourceTypes, List<String>>(); + List<String> resource1List = new ArrayList<String>(); + resource1List.add("*abc"); + resourceMap.put(AtlasResourceTypes.ENTITY, resource1List); + + List<String> resource2List = new ArrayList<String>(); + resource2List.add("*x"); + resource2List.add("*xyz"); + resourceMap.put(AtlasResourceTypes.OPERATION, resource2List); + + List<String> resource3List = new ArrayList<String>(); + resource3List.add("PII"); + resourceMap.put(AtlasResourceTypes.TYPE, resource3List); + + Map<String, HashMap<AtlasResourceTypes, List<String>>> permissionMap = + new HashMap<String, HashMap<AtlasResourceTypes, List<String>>>(); + permissionMap.put("grp1", resourceMap); + + List<String> policies = new ArrayList<String>(); + policies.add("hivePolicys;;;;grp1:rwu;;entity:*abc,operation:*xyz,operation:*x"); + policies.add("hivePolicy;;;;grp1:rwu;;entity:*abc,operation:*xyz"); + policies.add("hivePolicy;;usr1:r,usr2:rw;;grp1:rwu;;entity:*abc,operation:*xyz"); + policies.add("hivePolicy;;usr1:r,usr2:rw;;grp1:rwu,grp2:u;;entity:*abc,operation:*xyz,type:PII"); + List<PolicyDef> policyDefList = new PolicyParser().parsePolicies(policies); + + Map<String, Map<AtlasResourceTypes, List<String>>> createdPermissionMap = + new PolicyUtil().createPermissionMap(policyDefList, AtlasActionTypes.READ, SimpleAtlasAuthorizer.AtlasAccessorTypes.GROUP); + + assertEquals(permissionMap, createdPermissionMap); + + } +}
