Repository: incubator-ranger Updated Branches: refs/heads/stack 4e121ea0d -> 6edf6d868
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6edf6d86/knox-agent/conf/xasecure-knox-security.xml ---------------------------------------------------------------------- diff --git a/knox-agent/conf/xasecure-knox-security.xml b/knox-agent/conf/xasecure-knox-security.xml deleted file mode 100644 index 61aa245..0000000 --- a/knox-agent/conf/xasecure-knox-security.xml +++ /dev/null @@ -1,69 +0,0 @@ -<?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. ---> -<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> -<configuration xmlns:xi="http://www.w3.org/2001/XInclude"> - - - <!-- The following property is used to select appropriate XASecure Authorizer Module (filebased, policymanager based) --> - <property> - <name>knox.authorization.verifier.classname</name> - <value>org.apache.ranger.pdp.knox.RangerAuthorizer</value> - <description> - Class Name of the authorization Module - </description> - </property> - - - <!-- The following properties are used only when PolicyManager is used as - main storage for all policy --> - <property> - <name>xasecure.knox.policymgr.url</name> - <value>http://policymanagerhost:port/service/assets/dev-knox</value> - <description> - Location where XASecure Role Based Authorization Info is - located. - </description> - </property> - <property> - <name>xasecure.knox.policymgr.url.saveAsFile</name> - <value>/tmp/xasecure-knox-policy.json</value> - <description> - Location where XASecure Role Based Authorization Info is - saved after successful retrieval from policymanager - </description> - </property> - <property> - <name>xasecure.knox.policymgr.url.laststoredfile</name> - <value>/home/knox/last_xasecure-knox-policy.json</value> - <description> - Location and file where last XASecure Role Based Authorization Info - is saved after successful retrieval from policymanager. - </description> - </property> - <property> - <name>xasecure.knox.policymgr.url.reloadIntervalInMillis</name> - <value>30000</value> - <description> - How often do we need to verify the changes tothe - authorization url, - to reload to memory (reloaded only if there are - changes) - </description> - </property> - -</configuration> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6edf6d86/knox-agent/conf/xasecure-policymgr-ssl-changes.cfg ---------------------------------------------------------------------- diff --git a/knox-agent/conf/xasecure-policymgr-ssl-changes.cfg b/knox-agent/conf/xasecure-policymgr-ssl-changes.cfg deleted file mode 100644 index e47a89c..0000000 --- a/knox-agent/conf/xasecure-policymgr-ssl-changes.cfg +++ /dev/null @@ -1,20 +0,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. -# -# SSL Params -# -xasecure.policymgr.clientssl.keystore %SSL_KEYSTORE_FILE_PATH% mod create-if-not-exists -xasecure.policymgr.clientssl.truststore %SSL_TRUSTSTORE_FILE_PATH% mod create-if-not-exists -xasecure.knox.credential.provider.file jceks://file%CREDENTIAL_PROVIDER_FILE% mod create-if-not-exists http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6edf6d86/knox-agent/conf/xasecure-policymgr-ssl.xml ---------------------------------------------------------------------- diff --git a/knox-agent/conf/xasecure-policymgr-ssl.xml b/knox-agent/conf/xasecure-policymgr-ssl.xml deleted file mode 100644 index 0b41ed3..0000000 --- a/knox-agent/conf/xasecure-policymgr-ssl.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?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. ---> -<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> -<configuration xmlns:xi="http://www.w3.org/2001/XInclude"> - <!-- The following properties are used for 2-way SSL client server validation --> - <property> - <name>xasecure.policymgr.clientssl.keystore</name> - <value>/usr/lib/knox/conf/knox-clientcert.jks</value> - <description> - Java Keystore files - </description> - </property> - <property> - <name>xasecure.policymgr.clientssl.truststore</name> - <value>/usr/lib/knox/conf/knox-cacets.jks</value> - <description> - java truststore file - </description> - </property> -</configuration> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6edf6d86/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxAccessVerifier.java ---------------------------------------------------------------------- diff --git a/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxAccessVerifier.java b/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxAccessVerifier.java deleted file mode 100644 index 89265cb..0000000 --- a/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxAccessVerifier.java +++ /dev/null @@ -1,30 +0,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. - */ - -package org.apache.ranger.authorization.knox; - -import java.util.Set; - -public interface KnoxAccessVerifier { - - - public boolean isAccessAllowed(String topologyName, String serviceName, String accessTypes, String userName, Set<String> groups, String requestIp) ; - - public boolean isAuditEnabled(String topologyName, String serviceName) ; - -} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6edf6d86/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxAccessVerifierFactory.java ---------------------------------------------------------------------- diff --git a/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxAccessVerifierFactory.java b/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxAccessVerifierFactory.java deleted file mode 100644 index 25e1e28..0000000 --- a/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxAccessVerifierFactory.java +++ /dev/null @@ -1,65 +0,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. - */ - -package org.apache.ranger.authorization.knox; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.ranger.authorization.hadoop.config.RangerConfiguration; -import org.apache.ranger.authorization.hadoop.constants.RangerHadoopConstants; - -public class KnoxAccessVerifierFactory { - - private static final Log LOG = LogFactory.getLog(KnoxAccessVerifierFactory.class) ; - - private static KnoxAccessVerifier knoxAccessVerififer = null ; - - public static KnoxAccessVerifier getInstance() { - if (knoxAccessVerififer == null) { - synchronized(KnoxAccessVerifierFactory.class) { - KnoxAccessVerifier temp = knoxAccessVerififer ; - if (temp == null) { - String knoxAccessVerifierClassName = RangerConfiguration.getInstance().get(RangerHadoopConstants.KNOX_ACCESS_VERIFIER_CLASS_NAME_PROP, RangerHadoopConstants.KNOX_ACCESS_VERIFIER_CLASS_NAME_DEFAULT_VALUE ) ; - - if (knoxAccessVerifierClassName != null) { - LOG.info("Knox Access Verification class [" + knoxAccessVerifierClassName + "] - Being build"); - try { - knoxAccessVerififer = (KnoxAccessVerifier) (Class.forName(knoxAccessVerifierClassName).newInstance()) ; - LOG.info("Created a new instance of class: [" + knoxAccessVerifierClassName + "] for Knox Access verification."); - } catch (InstantiationException e) { - LOG.error("Unable to create KnoxAccess Verifier: [" + knoxAccessVerifierClassName + "]", e); - } catch (IllegalAccessException e) { - LOG.error("Unable to create KnoxAccess Verifier: [" + knoxAccessVerifierClassName + "]", e); - } catch (ClassNotFoundException e) { - LOG.error("Unable to create KnoxAccess Verifier: [" + knoxAccessVerifierClassName + "]", e); - } catch (Throwable t) { - LOG.error("Unable to create KnoxAccess Verifier: [" + knoxAccessVerifierClassName + "]", t); - } - finally { - LOG.info("Created a new instance of class: [" + knoxAccessVerifierClassName + "] for Knox Access verification. (" + knoxAccessVerififer + ")"); - } - } - } - else { - LOG.error("Unable to obtain knoxAccessVerifier [" + RangerHadoopConstants.KNOX_ACCESS_VERIFIER_CLASS_NAME_PROP + "]"); - } - } - } - return knoxAccessVerififer ; - } -} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6edf6d86/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxRangerPlugin.java ---------------------------------------------------------------------- diff --git a/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxRangerPlugin.java b/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxRangerPlugin.java new file mode 100644 index 0000000..5eee332 --- /dev/null +++ b/knox-agent/src/main/java/org/apache/ranger/authorization/knox/KnoxRangerPlugin.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.ranger.authorization.knox; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import org.apache.ranger.authorization.knox.KnoxRangerPlugin.KnoxConstants.AccessType; +import org.apache.ranger.authorization.knox.KnoxRangerPlugin.KnoxConstants.Condition; +import org.apache.ranger.authorization.knox.KnoxRangerPlugin.KnoxConstants.PluginConfiguration; +import org.apache.ranger.authorization.knox.KnoxRangerPlugin.KnoxConstants.ResourceName; +import org.apache.ranger.plugin.policyengine.RangerAccessRequest; +import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl; +import org.apache.ranger.plugin.policyengine.RangerResourceImpl; +import org.apache.ranger.plugin.service.RangerBasePlugin; + +public class KnoxRangerPlugin extends RangerBasePlugin { + + boolean initialized = false; + public KnoxRangerPlugin() { + super(PluginConfiguration.ServiceType, PluginConfiguration.AuditApplicationType); + } + + // must be synchroized so that accidental double init of plugin does not happen .. in case servlet instantiates multiple filters. + @Override + synchronized public void init() { + if (!initialized) { + super.init(); + initialized = true; + } + } + + public static class RequestBuilder { + String _service; + String _topology; + String _user; + Set<String> _groups; + String _clientIp; + RequestBuilder service(String service) { + _service = service; + return this; + } + RequestBuilder topology(String topology) { + _topology = topology; + return this; + } + RequestBuilder user(String user) { + _user = user; + return this; + } + RequestBuilder groups(Set<String> groups) { + _groups = groups; + return this; + } + RequestBuilder clientIp(String clientIp) { + _clientIp = clientIp; + return this; + } + + void verifyBuildable() { + if (_topology == null) throw new IllegalStateException("_topology can't be null!"); + if (_service == null) throw new IllegalStateException("_service can't be null!"); + if (_user == null) throw new IllegalStateException("_user can't be null!"); + return; + } + + RangerAccessRequest build() { + // build resource + RangerResourceImpl resource = new RangerResourceImpl(); + resource.setValue(ResourceName.Service, _service); + resource.setValue(ResourceName.Topology, _topology); + // build request + RangerAccessRequestImpl request = new RangerAccessRequestImpl(); + request.setAccessType(AccessType.Allow); + request.setClientIPAddress(_clientIp); + request.setUser(_user); + request.setUserGroups(_groups); + request.setResource(resource); + // build condition for IP address + Map<String, String> conditions = Collections.singletonMap(Condition.IpRange, _clientIp); + request.setConditions(conditions); + + return request; + } + } + + public static class KnoxConstants { + + // Plugin parameters + static class PluginConfiguration { + static final String ServiceType = "knox"; + static final String AuditApplicationType = "knox"; + } + + // must match the corresponding string used in service definition file + static class ResourceName { + static final String Topology = "topology"; + static final String Service = "service"; + } + + // must match the corresponding string used in service definition file + static class AccessType { + static final String Allow = "allow"; + } + + // must match the corresponding string used in service definition file + static class Condition { + static final String IpRange = "ip-range"; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6edf6d86/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java ---------------------------------------------------------------------- diff --git a/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java b/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java new file mode 100644 index 0000000..9809b3f --- /dev/null +++ b/knox-agent/src/main/java/org/apache/ranger/authorization/knox/RangerPDPKnoxFilter.java @@ -0,0 +1,160 @@ +/** + * 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.ranger.authorization.knox; + +import java.io.IOException; +import java.security.AccessController; +import java.security.Principal; +import java.util.HashSet; +import java.util.Set; + +import javax.security.auth.Subject; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.gateway.filter.AbstractGatewayFilter; +import org.apache.hadoop.gateway.security.GroupPrincipal; +import org.apache.hadoop.gateway.security.ImpersonatedPrincipal; +import org.apache.hadoop.gateway.security.PrimaryPrincipal; +import org.apache.ranger.plugin.policyengine.RangerAccessRequest; +import org.apache.ranger.plugin.policyengine.RangerAccessResult; + +public class RangerPDPKnoxFilter implements Filter { + + private static final Log LOG = LogFactory.getLog(RangerPDPKnoxFilter.class); + private String resourceRole = null; + static final KnoxRangerPlugin plugin = new KnoxRangerPlugin(); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + resourceRole = getInitParameter(filterConfig, "resource.role"); + plugin.init(); + } + + private String getInitParameter(FilterConfig filterConfig, String paramName) { + return filterConfig.getInitParameter(paramName.toLowerCase()); + } + + public void destroy() { + } + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + String sourceUrl = (String) request + .getAttribute(AbstractGatewayFilter.SOURCE_REQUEST_CONTEXT_URL_ATTRIBUTE_NAME); + String topologyName = getTopologyName(sourceUrl); + String serviceName = getServiceName(); + + Subject subject = Subject.getSubject(AccessController.getContext()); + + Principal primaryPrincipal = (Principal) subject.getPrincipals( + PrimaryPrincipal.class).toArray()[0]; + String primaryUser = primaryPrincipal.getName(); + + String impersonatedUser = null; + Object[] impersonations = subject.getPrincipals( + ImpersonatedPrincipal.class).toArray(); + if (impersonations != null && impersonations.length > 0) { + impersonatedUser = ((Principal) impersonations[0]).getName(); + } + + String user = (impersonatedUser != null) ? impersonatedUser + : primaryUser; + if (LOG.isDebugEnabled()) { + LOG.debug("Checking access primaryUser: " + primaryUser + ", impersonatedUser: " + + impersonatedUser + ", effectiveUser: " + user); + } + + Object[] groupObjects = subject.getPrincipals(GroupPrincipal.class) + .toArray(); + Set<String> groups = new HashSet<String>(); + for (Object obj : groupObjects) { + groups.add(((Principal) obj).getName()); + } + + String clientIp = request.getRemoteAddr(); + + if (LOG.isDebugEnabled()) { + LOG.debug("Checking access primaryUser: " + primaryUser + ", impersonatedUser: " + + impersonatedUser + ", effectiveUser: " + user + + ", groups: " + groups + ", clientIp: " + clientIp); + } + RangerAccessRequest accessRequest = new KnoxRangerPlugin.RequestBuilder() + .service(serviceName) + .topology(topologyName) + .user(user) + .groups(groups) + .clientIp(clientIp) + .build(); + + RangerAccessResult result = plugin.isAccessAllowed(accessRequest); + + boolean accessAllowed = result.getIsAllowed(); + boolean audited = result.getIsAudited(); + + if (LOG.isDebugEnabled()) { + LOG.debug("Access allowed: " + accessAllowed); + LOG.debug("Audit enabled: " + audited); + } + if (accessAllowed) { + chain.doFilter(request, response); + } else { + sendForbidden((HttpServletResponse) response); + } + } + + private void sendForbidden(HttpServletResponse res) { + sendErrorCode(res, 403); + } + + private void sendErrorCode(HttpServletResponse res, int code) { + try { + res.sendError(code); + } catch (IOException e) { + LOG.error("Error while redireting:", e); + } + } + + private String getTopologyName(String requestUrl) { + if (requestUrl == null) { + return null; + } + String url = requestUrl.trim(); + String[] tokens = url.split("/"); + if (tokens.length > 2) { + return tokens[2]; + } else { + return null; + } + } + + private String getServiceName() { + return resourceRole; + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/6edf6d86/security-admin/src/main/java/org/apache/ranger/common/ServiceUtil.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/common/ServiceUtil.java b/security-admin/src/main/java/org/apache/ranger/common/ServiceUtil.java index fa74642..5bb624f 100644 --- a/security-admin/src/main/java/org/apache/ranger/common/ServiceUtil.java +++ b/security-admin/src/main/java/org/apache/ranger/common/ServiceUtil.java @@ -20,11 +20,13 @@ package org.apache.ranger.common; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import org.apache.commons.collections.CollectionUtils; import org.apache.ranger.db.RangerDaoManager; import org.apache.ranger.entity.XXGroup; import org.apache.ranger.entity.XXUser; @@ -212,7 +214,7 @@ public class ServiceUtil { policyItem.setAccesses(accessList); if(ipAddress != null && !ipAddress.isEmpty()) { - RangerPolicy.RangerPolicyItemCondition ipCondition = new RangerPolicy.RangerPolicyItemCondition("ipaddress", ipAddress); + RangerPolicy.RangerPolicyItemCondition ipCondition = new RangerPolicy.RangerPolicyItemCondition("ipaddress", Collections.singletonList(ipAddress)); policyItem.getConditions().add(ipCondition); } @@ -286,7 +288,11 @@ public class ServiceUtil { for(RangerPolicy.RangerPolicyItemCondition condition : policyItem.getConditions()) { if(condition.getType() == "ipaddress") { - ipAddress = condition.getValue(); + List<String> values = condition.getValues(); + if (CollectionUtils.isNotEmpty(values)) { + // TODO changes this to properly deal with collection for now just returning 1st item + ipAddress = values.get(0); + } } if(ipAddress != null && !ipAddress.isEmpty()) {
