http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/java/org/apache/ranger/pdp/knox/URLBasedAuthDB.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/java/org/apache/ranger/pdp/knox/URLBasedAuthDB.java b/agents-impl/src/main/java/org/apache/ranger/pdp/knox/URLBasedAuthDB.java new file mode 100644 index 0000000..d5aa16e --- /dev/null +++ b/agents-impl/src/main/java/org/apache/ranger/pdp/knox/URLBasedAuthDB.java @@ -0,0 +1,452 @@ +/** + * 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.pdp.knox; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.ranger.authorization.hadoop.config.RangerConfiguration; +import org.apache.ranger.pdp.config.Jersey2PolicyRefresher; +import org.apache.ranger.pdp.config.PolicyChangeListener; +import org.apache.ranger.pdp.constants.RangerConstants; +import org.apache.ranger.pdp.model.Policy; +import org.apache.ranger.pdp.model.PolicyContainer; +import org.apache.ranger.pdp.model.RolePermission; + +public class URLBasedAuthDB implements PolicyChangeListener { + + private static final Log LOG = LogFactory.getLog(URLBasedAuthDB.class) ; + + private static URLBasedAuthDB me = null; + + private Jersey2PolicyRefresher refresher = null ; + + private PolicyContainer policyContainer = null; + + private HashMap<String,Boolean> cachedAuditFlag = new HashMap<String,Boolean>() ; // needs to be cleaned when ruleList changes + + public static URLBasedAuthDB getInstance() { + if (me == null) { + synchronized (URLBasedAuthDB.class) { + URLBasedAuthDB temp = me; + if (temp == null) { + me = new URLBasedAuthDB(); + me.init() ; + } + } + } + return me; + } + + public static URLBasedAuthDB getInstanceWithBackEndMocked() { + return new URLBasedAuthDB("instanceWithBackednMocked"); + } + + private URLBasedAuthDB() { + String url = RangerConfiguration.getInstance().get(RangerConstants.RANGER_KNOX_POLICYMGR_URL_PROP); + long refreshInMilli = RangerConfiguration.getInstance().getLong( + RangerConstants.RANGER_KNOX_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_PROP , + RangerConstants.RANGER_KNOX_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_DEFAULT); + String sslConfigFileName = RangerConfiguration.getInstance().get(RangerConstants.RANGER_KNOX_POLICYMGR_SSL_CONFIG_FILE_PROP) ; + + String lastStoredFileName = RangerConfiguration.getInstance().get(RangerConstants.RANGER_KNOX_LAST_SAVED_POLICY_FILE_PROP) ; + + refresher = new Jersey2PolicyRefresher(url, refreshInMilli,sslConfigFileName,lastStoredFileName) ; + + String saveAsFileName = RangerConfiguration.getInstance().get(RangerConstants.RANGER_KNOX_POLICYMGR_URL_SAVE_FILE_PROP) ; + if (saveAsFileName != null) { + refresher.setSaveAsFileName(saveAsFileName) ; + } + + if (lastStoredFileName != null) { + refresher.setLastStoredFileName(lastStoredFileName); + } + } + + private URLBasedAuthDB(String mockName) { + } + + private void init() { + refresher.setPolicyChangeListener(this); + } + + + @Override + public void OnPolicyChange(PolicyContainer aPolicyContainer) { + setPolicyContainer(aPolicyContainer); + } + + + public boolean isAccessGranted(String topology, String service, String access, String userName, Set<String> groups, + String requestIp) { + + boolean accessGranted = false; + + if (LOG.isDebugEnabled()) { + LOG.debug("Evaluating access for topology: " + topology + + ", service: " + service + + ", access: " + access + + ", requestingIp: " +requestIp + + ", requestingUser: " + userName + + ", requestingUserGroups: " + groups); + } + PolicyContainer policyContainer = getPolicyContainer() ; + + if (policyContainer == null) { + LOG.warn("Denying access: policyContainer is null") ; + return false ; + } + + for(Policy policy : policyContainer.getAcl()) { + + if (LOG.isDebugEnabled()) { + LOG.debug("Evaluating policy: " + policy.toString() ) ; + } + + if (!policy.isEnabled()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Skipping policy: " + policy + ", policy disabled") ; + } + continue; // jump to next policy + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Evaluating topology match for policyTopologyList: " + policy.getTopologyList() + + ", requestTopology: " + topology) ; + } + + boolean topologyMatched = false; + + List<String> topologyList = policy.getTopologyList(); + if (topologyList == null || topologyList.isEmpty()) { + LOG.debug("Denying access: policy topologyList is empty") ; + continue; // jump to next policy + } + + if (topologyList.contains("*") || topologyList.contains(topology)) { + topologyMatched = true; + LOG.debug("Policy topologyList matches requested topology"); + } + + if (!topologyMatched) { + for (String policyTopology : topologyList) { + if (FilenameUtils.wildcardMatch(topology, policyTopology)) { + topologyMatched = true; + LOG.debug("Policy topologyList matches requested topology"); + break; // break out of topologyList + } + } + } + if (!topologyMatched) { + LOG.debug("Denying access: policy topologyList does not match requested topology") ; + continue; // jump to next policy + } else { + LOG.debug("policy topologyList matches requested topology"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Evaluating service match for policyServiceList: " + policy.getServiceList() + + ", requestService: " + service) ; + } + + boolean serviceMatched = false; + + List<String> serviceList = policy.getServiceList(); + if (serviceList == null || serviceList.isEmpty()) { + LOG.debug("Denying access: policy serviceList is empty") ; + continue; // jump to next policy + } + + if (serviceList.contains("*") || serviceList.contains(service)) { + serviceMatched = true; + LOG.debug("Policy serviceList matches requested service"); + } + + if (!serviceMatched) { + for (String policyService : serviceList) { + if (FilenameUtils.wildcardMatch(service, policyService)) { + serviceMatched = true; + LOG.debug("Policy serviceList matches requested service"); + break; // break out of serviceList + } + } + } + if (!serviceMatched) { + LOG.debug("Denying access: policy serviceList does not match requested service") ; + continue; // jump to next policy + } else { + LOG.debug("Policy serviceList matches requested service"); + } + + LOG.debug("Checking accessType, IP, User, Group based permission"); + if ( policy.getPermissions() == null + || policy.getPermissions().isEmpty()) { + LOG.debug("Policy not applicable, no user or group based permission"); + } + + for (RolePermission rp : policy.getPermissions()) { + + if (LOG.isDebugEnabled()) { + LOG.debug("Evaluating RolePermission: " + rp); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Checking accessTypeMatch for rolePermissionAccesType: " + + rp.getAccess() + ", requestAccessType: " + access); + } + + if (rp.getAccess().contains(access)) { + + LOG.debug("RolePermission accessType matches request accessType"); + + boolean ipMatched = false; + List<String> ipList = rp.getIpAddress(); + if (LOG.isDebugEnabled()) { + LOG.debug("Checking ipMatch for rolePermissionIpList: " + ipList + + ", requestIP: " + requestIp); + } + + if (ipList == null || ipList.isEmpty()) { + LOG.debug("RolePermission does not require IP Matching"); + ipMatched = true; + } else if ( ipList.contains("*") ) { + LOG.debug("RolePermission allows any IP: *"); + ipMatched = true; + } else { + for (String ip : ipList) { + if (ipMatches(ip, requestIp)) { + LOG.debug("RolePermission IP matches request IP"); + ipMatched = true; + break;// break out of ipList + } + } + } + + if (!ipMatched) { + // ip not matched, jump to next RolePermission check + LOG.debug("Request IP does not match RolePermission"); + continue; // jump to next rolePermission + } else { + LOG.debug("Request IP matches RolePermission"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Checking userMatch for rolePermissionUsers: " + + rp.getUsers() + ", requestUser: " + userName); + } + + if ( rp.getUsers() != null && rp.getUsers().contains(userName) ) { + LOG.debug("Request user matches RolePermission"); + return true ; + } + LOG.debug("RolePermission does not permit request by request user, would check by groups"); + + if (LOG.isDebugEnabled()) { + LOG.debug("Checking groupMatch for rolePermissionGroups: " + + rp.getGroups() + ", requestGroups: " + groups); + } + + for(String ug : groups) { + if ( rp.getGroups() != null && rp.getGroups().contains(ug)) { + LOG.debug("Request userGroups matches RolePermission"); + return true ; + } + } + LOG.debug("RolePermission does not permit request by request user groups"); + + if (rp.getGroups().contains(RangerConstants.PUBLIC_ACCESS_ROLE)) { + LOG.debug("RolePermission applies to public group"); + return true ; + } + + LOG.debug("RolePermission does not permit by users, groups or public group"); + } else { + LOG.debug("rolePermissionAccessType does not match requestAccessType"); + } + } + } + LOG.debug("No matching policy permission found, denying access"); + return accessGranted; + } + + public boolean isAuditEnabled(String topology, String service) { + + boolean auditEnabled = false; + + if (LOG.isDebugEnabled()) { + LOG.debug("Checcking whether audit is enabled for topology: " + topology + + ", service: " + service ); + } + + PolicyContainer policyContainer = getPolicyContainer() ; + if (policyContainer == null) { + LOG.warn("PolicyContainer is null") ; + return false ; + } + + for(Policy policy : policyContainer.getAcl()) { + + if (LOG.isDebugEnabled()) { + LOG.debug("Evaluating policy: " + policy) ; + } + + if (!policy.isEnabled()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Skipping policy: " + policy + ", policy disabled") ; + } + continue; // jump to next policy + } + + if (policy.getAuditInd() == 0) { + if (LOG.isDebugEnabled()) { + LOG.debug("Skipping policy: " + policy + ", policy audit disabled") ; + } + continue; // jump to next policy + } + + boolean topologyMatched = false; + + List<String> topologyList = policy.getTopologyList(); + if (topologyList == null || topologyList.isEmpty()) { + LOG.debug("Policy not applicable: policy topologyList is empty") ; + continue; // jump to next policy + } + + if (topologyList.contains("*") || topologyList.contains(topology)) { + topologyMatched = true; + LOG.debug("Policy topologyList matches requested topology"); + } + + if (!topologyMatched) { + for (String policyTopology : topologyList) { + if (FilenameUtils.wildcardMatch(topology, policyTopology)) { + topologyMatched = true; + LOG.debug("Policy topologyList matches requested topology"); + break; // break out of topologyList check + } + } + } + if (!topologyMatched) { + LOG.debug("Policy not applicable: polocy topologyList does not match requested topology") ; + continue; // jump to next policy + } else { + LOG.debug("Policy topologyList matches requested topology"); + } + + boolean serviceMatched = false; + + List<String> serviceList = policy.getServiceList(); + if (serviceList == null || serviceList.isEmpty()) { + LOG.debug("Policy not applicable: serviceList is empty") ; + continue; // jump to next policy + } + + if (serviceList.contains("*") || serviceList.contains(service)) { + serviceMatched = true; + LOG.debug("Policy serviceList matches requested service"); + } + + if (!serviceMatched) { + for (String policyService : serviceList) { + if (FilenameUtils.wildcardMatch(service, policyService)) { + serviceMatched = true; + LOG.debug("Policy serviceList matches requested service"); + break; // break out of serviceList check + } + } + } + if (!serviceMatched) { + LOG.debug("Policy not applicable: policy serviceList does not match requested service") ; + continue; // jump to next policy + } else { + LOG.debug("Policy serviceList matches requested service"); + } + auditEnabled = true;; + break; // break out of policyList check + } + return auditEnabled; + } + + public PolicyContainer getPolicyContainer() { + return policyContainer; + } + + + synchronized void setPolicyContainer(PolicyContainer aPolicyContainer) { + + for(Policy p : aPolicyContainer.getAcl()) { + for(RolePermission rp : p.getPermissions()) { + // lowercase accesType value stings + List<String> rpaccess = rp.getAccess() ; + if (rpaccess != null && rpaccess.size() > 0) { + List<String> temp = new ArrayList<String>() ; + for(String s : rpaccess) { + temp.add(s.toLowerCase()) ; + } + rp.setAccess(temp); + } + } + } + + this.policyContainer = aPolicyContainer ; + this.cachedAuditFlag.clear(); + } + + + private boolean ipMatches(String policyIp, String requestIp) { + if (policyIp == null) { + return false; + } + policyIp = policyIp.trim(); + if (policyIp.isEmpty()) { + return false; + } + boolean ipMatched = false; + boolean wildEnd = false; + if (policyIp.contains(".")) { + while (policyIp.endsWith(".*")) { + wildEnd = true; + policyIp = policyIp.substring(0, policyIp.lastIndexOf(".*")); + } + if (wildEnd) { + policyIp = policyIp + "."; + } + } else if (policyIp.contains(":")) { + while (policyIp.endsWith(":*")) { + wildEnd = true; + policyIp = policyIp.substring(0, policyIp.lastIndexOf(":*")); + } + if (wildEnd) { + policyIp = policyIp + ":"; + } + } + if (wildEnd && requestIp.toLowerCase().startsWith(policyIp.toLowerCase())) { + ipMatched = true; + } else if (policyIp.equalsIgnoreCase(requestIp)) { + ipMatched = true; + } + return ipMatched; + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/java/org/apache/ranger/pdp/knox/deploy/RangerPDPKnoxDeploymentContributor.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/java/org/apache/ranger/pdp/knox/deploy/RangerPDPKnoxDeploymentContributor.java b/agents-impl/src/main/java/org/apache/ranger/pdp/knox/deploy/RangerPDPKnoxDeploymentContributor.java new file mode 100644 index 0000000..a70224f --- /dev/null +++ b/agents-impl/src/main/java/org/apache/ranger/pdp/knox/deploy/RangerPDPKnoxDeploymentContributor.java @@ -0,0 +1,73 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ranger.pdp.knox.deploy; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.hadoop.gateway.deploy.DeploymentContext; +import org.apache.hadoop.gateway.deploy.ProviderDeploymentContributorBase; +import org.apache.hadoop.gateway.descriptor.FilterParamDescriptor; +import org.apache.hadoop.gateway.descriptor.ResourceDescriptor; +import org.apache.hadoop.gateway.topology.Provider; +import org.apache.hadoop.gateway.topology.Service; + +public class RangerPDPKnoxDeploymentContributor extends ProviderDeploymentContributorBase { + + private static final String FILTER_CLASSNAME = "org.apache.ranger.pdp.knox.filter.RangerPDPKnoxFilter"; + + @Override + public String getRole() { + return "authorization"; + } + + @Override + public String getName() { + return "XASecurePDPKnox"; + } + + @Override + public void initializeContribution(DeploymentContext context) { + super.initializeContribution(context); + } + + @Override + public void contributeProvider( DeploymentContext context, Provider provider ) { + } + + @Override + public void contributeFilter( DeploymentContext context, Provider provider, Service service, + ResourceDescriptor resource, List<FilterParamDescriptor> params ) { + if (params == null) { + params = new ArrayList<FilterParamDescriptor>(); + } + // add resource role to params so that we can determine the acls to enforce at runtime + params.add( resource.createFilterParam().name( "resource.role" ).value(resource.role() ) ); + + // blindly add all the provider params as filter init params + // this will include any {resource.role}-ACLS parameters to be enforced - such as NAMENODE-ACLS + Map<String, String> providerParams = provider.getParams(); + for(Entry<String, String> entry : providerParams.entrySet()) { + params.add( resource.createFilterParam().name( entry.getKey().toLowerCase() ).value( entry.getValue() ) ); + } + + resource.addFilter().name( getName() ).role( getRole() ).impl( FILTER_CLASSNAME ).params( params ); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/java/org/apache/ranger/pdp/knox/filter/RangerPDPKnoxFilter.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/java/org/apache/ranger/pdp/knox/filter/RangerPDPKnoxFilter.java b/agents-impl/src/main/java/org/apache/ranger/pdp/knox/filter/RangerPDPKnoxFilter.java new file mode 100644 index 0000000..7eb498e --- /dev/null +++ b/agents-impl/src/main/java/org/apache/ranger/pdp/knox/filter/RangerPDPKnoxFilter.java @@ -0,0 +1,214 @@ +/** + * 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.pdp.knox.filter; + +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.audit.model.EnumRepositoryType; +import org.apache.ranger.audit.model.KnoxAuditEvent; +import org.apache.ranger.audit.provider.AuditProvider; +import org.apache.ranger.audit.provider.AuditProviderFactory; +import org.apache.ranger.authorization.hadoop.config.RangerConfiguration; +import org.apache.ranger.authorization.hadoop.constants.RangerHadoopConstants; +import org.apache.ranger.authorization.knox.KnoxAccessVerifier; +import org.apache.ranger.authorization.knox.KnoxAccessVerifierFactory; +import org.apache.ranger.authorization.utils.StringUtil; + +public class RangerPDPKnoxFilter implements Filter { + + private static final Log LOG = LogFactory.getLog(RangerPDPKnoxFilter.class); + private static final String ACL_ENFORCER = "xasecure-acl"; + private static final String PERM_ALLOW = "allow"; + private String resourceRole = null; + private KnoxAccessVerifier knoxAccessVerifier; + + + AuditProvider auditProvider = AuditProviderFactory.getAuditProvider(); + private final String REPOSITORY_NAME = RangerConfiguration.getInstance().get(RangerHadoopConstants.AUDITLOG_REPOSITORY_NAME_PROP); + + static { + RangerConfiguration.getInstance().initAudit(AuditProviderFactory.ApplicationType.Knox); + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + resourceRole = getInitParameter(filterConfig, "resource.role"); + knoxAccessVerifier = KnoxAccessVerifierFactory.getInstance(); + } + + 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); + } + boolean accessAllowed = knoxAccessVerifier.isAccessAllowed( + topologyName, serviceName, PERM_ALLOW, user, groups, clientIp); + + if (LOG.isDebugEnabled()) { + LOG.debug("Access allowed: " + accessAllowed); + } + if (accessAllowed) { + chain.doFilter(request, response); + if (knoxAccessVerifier.isAuditEnabled(topologyName, serviceName)) { + LOG.debug("Audit is enabled"); + logAuditEvent(user, clientIp, topologyName, serviceName, + "allow", true); + } else { + LOG.debug("Audit is not enabled"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Access is denied"); + } + if (knoxAccessVerifier.isAuditEnabled(topologyName, serviceName)) { + LOG.debug("Audit is enabled"); + logAuditEvent(user, clientIp, topologyName, serviceName, + "allow", false); + } else { + LOG.debug("Audit is not enabled"); + } + 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; + } + + private void logAuditEvent(String userName, String clientIp, + String topology, String service, + String accessType, boolean accessGranted) { + + KnoxAuditEvent auditEvent = new KnoxAuditEvent(); + + auditEvent.setUser(userName == null ? + RangerHadoopConstants.AUDITLOG_EMPTY_STRING : userName); + auditEvent.setResourcePath("/" + topology + "/" + service); + auditEvent.setResourceType("service"); + auditEvent.setAccessType(accessType); + auditEvent.setClientIP(clientIp); + auditEvent.setEventTime(StringUtil.getUTCDate()); + auditEvent.setAccessResult((short) (accessGranted ? 1 : 0)); + auditEvent.setResultReason(null); + auditEvent.setRepositoryType(EnumRepositoryType.KNOX); + auditEvent.setRepositoryName(REPOSITORY_NAME); + auditEvent.setAclEnforcer(ACL_ENFORCER); + + try { + LOG.debug("logEvent [" + auditEvent + "] - START"); + + AuditProvider ap = AuditProviderFactory.getAuditProvider(); + ap.log(auditEvent); + + LOG.debug("logEvent [" + auditEvent + "] - END"); + } catch (Throwable t) { + LOG.error("ERROR logEvent [" + auditEvent + "]", t); + } + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/java/org/apache/ranger/pdp/model/Policy.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/java/org/apache/ranger/pdp/model/Policy.java b/agents-impl/src/main/java/org/apache/ranger/pdp/model/Policy.java new file mode 100644 index 0000000..46ca26b --- /dev/null +++ b/agents-impl/src/main/java/org/apache/ranger/pdp/model/Policy.java @@ -0,0 +1,326 @@ +/* + * 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.pdp.model; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.ranger.pdp.config.gson.ExcludeSerialization; + +import com.google.gson.annotations.SerializedName; + +public class Policy { + + public static final String RESOURCE_SPLITER = "," ; + public static final String POLICY_ENABLED_STATUS = "Enabled" ; + public static final String SELECTION_TYPE_INCLUSIVE = "Inclusion" ; + public static final String SELECTION_TYPE_EXCLUSIVE = "Exclusion" ; + + // + // Only for HDFS policies + // + private String resource ; + @SerializedName("isRecursive") + private int recursiveInd; + + // Only for Knox Policies + // + + @SerializedName("topology_name") + private String topologies ; + + @SerializedName("service_name") + private String services ; + + + // + // Only for Hive Policies + // + + @SerializedName("database_name") + private String databases ; + + @SerializedName("table_name") + private String tables ; + + @SerializedName("udf_name") + private String udfs ; + + @SerializedName("column_name") + private String columns ; + + @SerializedName("column_families") + private String columnfamilies ; + + // + // Neede for all Policies + // + @SerializedName("permission") + private List<RolePermission> permissions ; + + @SerializedName("audit") + private int auditInd ; + + @SerializedName("encrypt") + private int encryptInd ; + + @SerializedName("policyStatus") + private String policyStatus; + + @SerializedName("tablePolicyType") + private String tableSelectionType ; + + @SerializedName("columnPolicyType") + private String columnSelectionType ; + + // Derived fields for PolicyAnalysis + @ExcludeSerialization + private List<ResourcePath> resourceList ; + @ExcludeSerialization + private List<String> databaseList ; + @ExcludeSerialization + private List<String> tableList ; + @ExcludeSerialization + private List<String> udfList ; + @ExcludeSerialization + private List<String> columnList ; + @ExcludeSerialization + private List<String> columnFamilyList ; + @ExcludeSerialization + private List<String> topologyList ; + @ExcludeSerialization + private List<String> serviceList ; + + public Policy() { + permissions = new ArrayList<RolePermission>() ; + } + + + public String getResource() { + return resource; + } + + public void setResource(String resource) { + this.resource = resource; + } + + public String getDatabases() { + return databases; + } + + public void setDatabases(String databases) { + this.databases = databases; + } + + public String getTables() { + return tables; + } + + public void setTables(String tables) { + this.tables = tables; + } + + public String gettopologies() { + return topologies; + } + + public void setTopologies(String topologies) { + this.topologies = topologies; + } + + public String getServices() { + return services; + } + + public void setServices(String services) { + this.services = services; + } + public String getUdfs() { + return udfs; + } + + public void setUdfs(String udfs) { + this.udfs = udfs; + } + + + public String getColumns() { + return columns; + } + public void setColumns(String columns) { + this.columns = columns; + } + public String getColumnfamilies() { + return columnfamilies; + } + public void setColumnfamilies(String columnfamilies) { + this.columnfamilies = columnfamilies; + } + + public List<RolePermission> getPermissions() { + return permissions; + } + public void setPermissions(List<RolePermission> permissions) { + this.permissions = permissions; + } + + public int getRecursiveInd() { + return recursiveInd; + } + public void setRecursiveInd(int recursiveInd) { + this.recursiveInd = recursiveInd; + } + + public int getAuditInd() { + return auditInd; + } + + + public void setAuditInd(int auditInd) { + this.auditInd = auditInd; + } + + + public int getEncryptInd() { + return encryptInd; + } + + + public void setEncryptInd(int encryptInd) { + this.encryptInd = encryptInd; + } + + public String getPolicyStatus() { + return policyStatus; + } + + + public void setPolicyStatus(String policyStatus) { + this.policyStatus = policyStatus; + } + + public String getTableSelectionType() { + return tableSelectionType; + } + + + public void setTableSelectionType(String tableSelectionType) { + this.tableSelectionType = tableSelectionType; + } + + + public String getColumnSelectionType() { + return columnSelectionType; + } + + + public void setColumnSelectionType(String columnSelectionType) { + this.columnSelectionType = columnSelectionType; + } + + public boolean isTableSelectionExcluded() { + return (this.tableSelectionType != null && SELECTION_TYPE_EXCLUSIVE.equalsIgnoreCase(this.tableSelectionType)) ; + } + + public boolean isColumnSelectionExcluded() { + return (this.columnSelectionType != null && SELECTION_TYPE_EXCLUSIVE.equalsIgnoreCase(this.columnSelectionType)) ; + } + + + // An older version of policy manager would show policyStatus as NULL (considered that as Enabled) + public boolean isEnabled() { + return (this.policyStatus == null || POLICY_ENABLED_STATUS.equalsIgnoreCase(this.policyStatus)) ; + } + + public List<ResourcePath> getResourceList() { + if (this.resourceList == null) { + this.resourceList = getResourceList(resource) ; + } + return this.resourceList; + } + public List<String> getDatabaseList() { + if (this.databaseList == null) { + this.databaseList = getList(this.databases) ; + } + return this.databaseList; + } + public List<String> getTableList() { + if (this.tableList == null) { + this.tableList = getList(this.tables) ; + } + return this.tableList; + } + public List<String> getColumnList() { + if (this.columnList == null) { + this.columnList = getList(this.columns) ; + } + return this.columnList; + } + public List<String> getColumnFamilyList() { + if (this.columnFamilyList == null) { + this.columnFamilyList = getList(this.columnfamilies) ; + } + return this.columnFamilyList; + } + public List<String> getUDFList() { + if (this.udfList == null && this.udfList != null) { + this.udfList = getList(this.udfs) ; + } + return this.udfList; + } + + public List<String> getTopologyList() { + if (this.topologyList == null) { + this.topologyList = getList(this.topologies) ; + } + return this.topologyList; + } + + public List<String> getServiceList() { + if (this.serviceList == null) { + this.serviceList = getList(this.services) ; + } + return this.serviceList; + } + + + private List<String> getList(String resource) { + List<String> ret = new ArrayList<String>() ; + if (resource == null || resource.trim().isEmpty()) { + resource = "*" ; + } + for(String r : resource.split(RESOURCE_SPLITER)) { + ret.add(r) ; + } + + return ret; + } + + private List<ResourcePath> getResourceList(String resource) { + List<ResourcePath> ret = new ArrayList<ResourcePath>() ; + if (resource != null && ! resource.isEmpty()) { + for(String path : resource.split(RESOURCE_SPLITER)) { + ret.add(new ResourcePath(path)) ; + } + } + return ret ; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/java/org/apache/ranger/pdp/model/PolicyContainer.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/java/org/apache/ranger/pdp/model/PolicyContainer.java b/agents-impl/src/main/java/org/apache/ranger/pdp/model/PolicyContainer.java new file mode 100644 index 0000000..3674102 --- /dev/null +++ b/agents-impl/src/main/java/org/apache/ranger/pdp/model/PolicyContainer.java @@ -0,0 +1,55 @@ +/* + * 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.pdp.model; + +import java.util.List; + +import com.google.gson.annotations.SerializedName; + +public class PolicyContainer { + + @SerializedName("repository_name") + private String repositoryName ; + + @SerializedName("last_updated") + private long lastUpdatedTimeInEpoc ; + + @SerializedName("acl") + private List<Policy> acl; + + public String getRepositoryName() { + return repositoryName; + } + public void setRepositoryName(String repositoryName) { + this.repositoryName = repositoryName; + } + public long getLastUpdatedTimeInEpoc() { + return lastUpdatedTimeInEpoc; + } + public void setLastUpdatedTimeInEpoc(long lastUpdatedTimeInEpoc) { + this.lastUpdatedTimeInEpoc = lastUpdatedTimeInEpoc; + } + public List<Policy> getAcl() { + return acl; + } + public void setAcl(List<Policy> acl) { + this.acl = acl; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/java/org/apache/ranger/pdp/model/ResourcePath.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/java/org/apache/ranger/pdp/model/ResourcePath.java b/agents-impl/src/main/java/org/apache/ranger/pdp/model/ResourcePath.java new file mode 100644 index 0000000..fa32ed8 --- /dev/null +++ b/agents-impl/src/main/java/org/apache/ranger/pdp/model/ResourcePath.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + package org.apache.ranger.pdp.model; + +public class ResourcePath { + + String path ; + boolean wildcardPath ; + + public ResourcePath(String path) { + this.path = path ; + if (this.path.contains("*") || this.path.contains("?")) { + this.wildcardPath = true ; + } + } + + public String getPath() { + return path; + } + + public boolean isWildcardPath() { + return wildcardPath; + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/java/org/apache/ranger/pdp/model/RolePermission.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/java/org/apache/ranger/pdp/model/RolePermission.java b/agents-impl/src/main/java/org/apache/ranger/pdp/model/RolePermission.java new file mode 100644 index 0000000..accee6c --- /dev/null +++ b/agents-impl/src/main/java/org/apache/ranger/pdp/model/RolePermission.java @@ -0,0 +1,71 @@ +/* + * 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.pdp.model; + +import java.util.ArrayList; +import java.util.List; + +public class RolePermission { + + private List<String> users ; + private List<String> groups ; + private List<String> access ; + private List<String> ipAddress ; + + public RolePermission() { + users = new ArrayList<String>() ; + groups = new ArrayList<String>() ; + access = new ArrayList<String>() ; + } + + + public List<String> getUsers() { + return users; + } + + public void setUsers(List<String> users) { + this.users = users; + } + + public List<String> getGroups() { + return groups; + } + + public void setGroups(List<String> groups) { + this.groups = groups; + } + + public List<String> getAccess() { + return this.access; + } + + public List<String> getIpAddress() { + return this.ipAddress; + } + + public void setIpAddress(List<String> ipAddress) { + this.ipAddress = ipAddress ; + } + + public void setAccess(List<String> access) { + this.access = access ; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/java/org/apache/ranger/pdp/storm/RangerAuthorizer.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/java/org/apache/ranger/pdp/storm/RangerAuthorizer.java b/agents-impl/src/main/java/org/apache/ranger/pdp/storm/RangerAuthorizer.java new file mode 100644 index 0000000..f7d3b0f --- /dev/null +++ b/agents-impl/src/main/java/org/apache/ranger/pdp/storm/RangerAuthorizer.java @@ -0,0 +1,61 @@ +/* + * 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.pdp.storm; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.ranger.authorization.storm.RangerStormAccessVerifier; + +public class RangerAuthorizer implements RangerStormAccessVerifier { + + private static final Log LOG = LogFactory.getLog(RangerAuthorizer.class) ; + + private static URLBasedAuthDB authDB = URLBasedAuthDB.getInstance() ; + + + @Override + public boolean isAccessAllowed(String aUserName, String[] aGroupName, String aOperationName, String aTopologyName) { + boolean ret = false ; + + if (authDB != null) { + ret = authDB.isAccessAllowed(aUserName, aGroupName, aOperationName, aTopologyName) ; + } + else { + LOG.error("Unable to find a URLBasedAuthDB for authorization - Found null"); + } + + return ret ; + } + + @Override + public boolean isAudited(String aTopologyName) { + boolean ret = false ; + + if (authDB != null) { + ret = authDB.isAudited(aTopologyName) ; + } + else { + LOG.error("Unable to find a URLBasedAuthDB for authorization - Found null"); + } + + return ret ; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/java/org/apache/ranger/pdp/storm/StormAuthRule.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/java/org/apache/ranger/pdp/storm/StormAuthRule.java b/agents-impl/src/main/java/org/apache/ranger/pdp/storm/StormAuthRule.java new file mode 100644 index 0000000..f655839 --- /dev/null +++ b/agents-impl/src/main/java/org/apache/ranger/pdp/storm/StormAuthRule.java @@ -0,0 +1,136 @@ +/* + * 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.pdp.storm; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.FilenameUtils; +import org.apache.ranger.authorization.utils.StringUtil; + +public class StormAuthRule { + private String topologyName ; + private List<String> accessTypeList ; + private List<String> groupList ; + private List<String> userList; + private boolean auditEnabled ; + + + public StormAuthRule(String topologyName, List<String> accessTypeList, + List<String> userList, List<String> groupList, boolean auditEnabled) { + super(); + this.topologyName = topologyName; + this.accessTypeList = accessTypeList; + if (this.accessTypeList == null) { + this.accessTypeList = new ArrayList<String>(); + } + this.userList = userList; + if (this.userList == null) { + this.userList = new ArrayList<String>(); + } + + this.groupList = groupList; + if (this.groupList == null) { + this.groupList = new ArrayList<String>(); + } + + this.auditEnabled = auditEnabled ; + } + + public String getTopologyName() { + return topologyName; + } + public void setTopologyName(String topologyName) { + this.topologyName = topologyName; + } + public List<String> getAccessTypeList() { + return accessTypeList; + } + public void setAccessTypeList(List<String> accessTypeList) { + this.accessTypeList = accessTypeList; + } + public List<String> getGroupList() { + return groupList; + } + public void setGroupList(List<String> groupList) { + this.groupList = groupList; + } + public List<String> getUserList() { + return userList; + } + public void setUserList(List<String> userList) { + this.userList = userList; + } + + public boolean isMatchedTopology(String aTopologyName) { + + boolean ret = false ; + + if (aTopologyName == null || aTopologyName.length() == 0) { + ret = "*".equals(this.topologyName) ; + } + else { + ret = (aTopologyName.equals(this.topologyName) || FilenameUtils.wildcardMatch(aTopologyName,this.topologyName)) ; + } + return ret ; + } + + public boolean isOperationAllowed(String aOperationName) { + return this.accessTypeList.contains(aOperationName); + } + + private static final String PUBLIC_GROUP_NAME = "public" ; + + public boolean isUserAllowed(String aUserName, String[] aGroupList) { + + boolean accessAllowed = false ; + + if ( this.userList.contains(aUserName) ) { + accessAllowed = true ; + } + else if (this.groupList.contains(PUBLIC_GROUP_NAME)) { + accessAllowed = true ; + } + else if (aGroupList != null ) { + for(String userGroup : aGroupList ) { + if (this.groupList.contains(userGroup) ) { + accessAllowed = true ; + break ; + } + } + } + + return accessAllowed ; + } + + public boolean getAuditEnabled() { + return this.auditEnabled ; + } + + @Override + public String toString() { + return "StormAuthRule: { topologyName: [" + topologyName + "]," + + "userList: [" + StringUtil.toString(userList) + "]" + + "groupList: [" + StringUtil.toString(groupList) + "]" + + "accessTypeList: [" + StringUtil.toString(accessTypeList) + "]" + + "auditEnabled: [" + auditEnabled + "] }"; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/java/org/apache/ranger/pdp/storm/URLBasedAuthDB.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/java/org/apache/ranger/pdp/storm/URLBasedAuthDB.java b/agents-impl/src/main/java/org/apache/ranger/pdp/storm/URLBasedAuthDB.java new file mode 100644 index 0000000..1977fb2 --- /dev/null +++ b/agents-impl/src/main/java/org/apache/ranger/pdp/storm/URLBasedAuthDB.java @@ -0,0 +1,176 @@ +/* + * 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.pdp.storm; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.ranger.authorization.hadoop.config.RangerConfiguration; +import org.apache.ranger.authorization.storm.RangerStormAccessVerifier; +import org.apache.ranger.pdp.config.PolicyChangeListener; +import org.apache.ranger.pdp.config.PolicyRefresher; +import org.apache.ranger.pdp.constants.RangerConstants; +import org.apache.ranger.pdp.model.Policy; +import org.apache.ranger.pdp.model.PolicyContainer; +import org.apache.ranger.pdp.model.RolePermission; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class URLBasedAuthDB implements PolicyChangeListener, RangerStormAccessVerifier { + + private static final Logger LOG = LoggerFactory.getLogger(URLBasedAuthDB.class) ; + + private static URLBasedAuthDB me = null; + + private PolicyRefresher refresher = null ; + + private PolicyContainer policyContainer = null; + + private List<StormAuthRule> stormAuthDB = null ; + + public static URLBasedAuthDB getInstance() { + if (me == null) { + synchronized (URLBasedAuthDB.class) { + URLBasedAuthDB temp = me; + if (temp == null) { + me = new URLBasedAuthDB(); + me.init() ; + } + } + } + return me; + } + + private URLBasedAuthDB() { + + String url = RangerConfiguration.getInstance().get(RangerConstants.RANGER_STORM_POLICYMGR_URL_PROP); + + long refreshInMilli = RangerConfiguration.getInstance().getLong( + RangerConstants.RANGER_STORM_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_PROP , + RangerConstants.RANGER_STORM_POLICYMGR_URL_RELOAD_INTERVAL_IN_MILLIS_DEFAULT); + + String lastStoredFileName = RangerConfiguration.getInstance().get(RangerConstants.RANGER_STORM_LAST_SAVED_POLICY_FILE_PROP) ; + + String sslConfigFileName = RangerConfiguration.getInstance().get(RangerConstants.RANGER_STORM_POLICYMGR_SSL_CONFIG_FILE_PROP) ; + + refresher = new PolicyRefresher(url, refreshInMilli,sslConfigFileName,lastStoredFileName) ; + + String saveAsFileName = RangerConfiguration.getInstance().get(RangerConstants.RANGER_STORM_POLICYMGR_URL_SAVE_FILE_PROP) ; + if (saveAsFileName != null) { + refresher.setSaveAsFileName(saveAsFileName) ; + } + + if (lastStoredFileName != null) { + refresher.setLastStoredFileName(lastStoredFileName); + } + } + + + private void init() { + refresher.setPolicyChangeListener(this); + } + + + @Override + public void OnPolicyChange(PolicyContainer aPolicyContainer) { + setPolicyContainer(aPolicyContainer); + } + + + public PolicyContainer getPolicyContainer() { + return policyContainer; + } + + + + public synchronized void setPolicyContainer(PolicyContainer aPolicyContainer) { + + if (aPolicyContainer != null) { + + List<StormAuthRule> tempStormAuthDB = new ArrayList<StormAuthRule>() ; + + for(Policy p : aPolicyContainer.getAcl()) { + + if (! p.isEnabled()) { + continue; + } + + for (String topologyName : p.getTopologyList()) { + + List<RolePermission> rpList = p.getPermissions() ; + + for(RolePermission rp : rpList) { + StormAuthRule rule = new StormAuthRule(topologyName, rp.getAccess() , rp.getUsers(), rp.getGroups(), (p.getAuditInd() == 1)) ; + tempStormAuthDB.add(rule) ; + } + } + } + + this.stormAuthDB = tempStormAuthDB ; + + this.policyContainer = aPolicyContainer ; + } + } + + @Override + public boolean isAccessAllowed(String aUserName, String[] aGroupName, String aOperationName, String aTopologyName) { + + boolean accessAllowed = false ; + + List<StormAuthRule> tempStormAuthDB = this.stormAuthDB ; + + if (tempStormAuthDB != null) { + for(StormAuthRule rule : tempStormAuthDB) { + if (rule.isMatchedTopology(aTopologyName)) { + if (rule.isOperationAllowed(aOperationName)) { + if (rule.isUserAllowed(aUserName, aGroupName)) { + accessAllowed = true ; + break ; + } + } + } + } + } + + return accessAllowed ; + } + + @Override + public boolean isAudited(String aTopologyName) { + boolean auditEnabled = false ; + + List<StormAuthRule> tempStormAuthDB = stormAuthDB ; + + if (tempStormAuthDB != null) { + for(StormAuthRule rule : tempStormAuthDB) { + if (rule.isMatchedTopology(aTopologyName)) { + auditEnabled = rule.getAuditEnabled() ; + if (auditEnabled) { + break ; + } + } + } + } + + return auditEnabled ; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/java/org/apache/ranger/pdp/utils/RangerUtils.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/java/org/apache/ranger/pdp/utils/RangerUtils.java b/agents-impl/src/main/java/org/apache/ranger/pdp/utils/RangerUtils.java new file mode 100644 index 0000000..27e7dee --- /dev/null +++ b/agents-impl/src/main/java/org/apache/ranger/pdp/utils/RangerUtils.java @@ -0,0 +1,49 @@ +/* + * 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.pdp.utils; + +import java.io.File; +import java.net.URL; + +public class RangerUtils { + + public static String getFilePathFromClassPath(String aFileName) { + String pathName = null; + + File lf = new File(aFileName) ; + + if (lf.exists()) { + pathName = lf.getAbsolutePath(); + } + else { + URL lurl = RangerUtils.class.getResource(aFileName); + if (lurl == null) { + if (!aFileName.startsWith("/")) { + lurl = RangerUtils.class.getResource("/" + aFileName); + } + } + if (lurl != null) { + pathName = lurl.getFile(); + } + } + return pathName; + + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor ---------------------------------------------------------------------- diff --git a/agents-impl/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor b/agents-impl/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor index 44483f0..6db0bdc 100644 --- a/agents-impl/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor +++ b/agents-impl/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor @@ -15,4 +15,4 @@ # See the License for the specific language governing permissions and # limitations under the License. ########################################################################## -com.xasecure.pdp.knox.deploy.XASecurePDPKnoxDeploymentContributor +org.apache.ranger.pdp.knox.deploy.RangerPDPKnoxDeploymentContributor http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/test/java/com/xasecure/pdp/hdfs/PolicyCacheStoreTest.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/test/java/com/xasecure/pdp/hdfs/PolicyCacheStoreTest.java b/agents-impl/src/test/java/com/xasecure/pdp/hdfs/PolicyCacheStoreTest.java deleted file mode 100644 index 2b1b508..0000000 --- a/agents-impl/src/test/java/com/xasecure/pdp/hdfs/PolicyCacheStoreTest.java +++ /dev/null @@ -1,169 +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 com.xasecure.pdp.hdfs; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Before; -import org.junit.After; -import org.junit.Test; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.xasecure.pdp.config.ConfigWatcher; -import com.xasecure.pdp.config.PolicyRefresher; -import com.xasecure.pdp.model.Policy; -import com.xasecure.pdp.model.PolicyContainer; -import com.xasecure.pdp.model.RolePermission; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - - -public class PolicyCacheStoreTest { - URLBasedAuthDB authDB = null; - ConfigWatcher watcherDaemon = null; - PolicyRefresher pr = null; - PolicyContainer policyContainer=null; - String url=null; - String sslConfigFileName=null; - String lastStoredFileName=null; - Long refreshInterval =0L; - private static final Log LOG = LogFactory.getLog(PolicyCacheStoreTest.class); - @Before - public void setup(){ - authDB = URLBasedAuthDB.getInstance(); - - } - - @After - public void teardown(){ - authDB = null; - PolicyRefresher pr = null; - } - - @Test - public void testHdfsPolicyCacheStore(){ - //Check if the policy cache gets created when agent get created; - url="dummyurl"; - refreshInterval=10L; - sslConfigFileName = "dummyConfigFileName.xml"; - lastStoredFileName = System.getProperty("user.home") +"/"+ "haooopPolicyCache.json"; - policyContainer = buildPolicyContainer( - "/demo/data", - 1, - asList("allow"), - asList("guest"), - asList("sales"), - null, // ipAddress - true, // policyEnabled - true); // auditEnabled - authDB.OnPolicyChange(policyContainer); - pr = spy(new PolicyRefresher(url,refreshInterval,sslConfigFileName,lastStoredFileName)); - pr.setPolicyContainer(policyContainer); - pr.setPolicyChangeListener(authDB); - PolicyContainer newPr = readPolicyCache(lastStoredFileName); - assertEquals(policyToString(policyContainer),policyToString(newPr)); - } - - private static PolicyContainer buildPolicyContainer(String resource, - int recursiveInd, List<String> accessTypes, List<String> users, - List<String> groups, List<String> ipAddresses, - boolean policyEnabled, boolean auditEnabled) { - - PolicyContainer policyContainer = new PolicyContainer(); - policyContainer.setRepositoryName("hadoopdev"); - - List<Policy> policies = new ArrayList<Policy>(); - - Policy policy = new Policy(); - policy.setResource(resource); - policy.setRecursiveInd(recursiveInd); - policy.setPolicyStatus(policyEnabled ? "Enabled" : "NotEnabled"); - policy.setAuditInd(auditEnabled ? 1 : 0); - - List<RolePermission> rolePermissions = new ArrayList<RolePermission>(); - - RolePermission rolePermission = new RolePermission(); - - rolePermissions.add(rolePermission); - rolePermission.setAccess(accessTypes); - rolePermission.setUsers(users); - rolePermission.setGroups(groups); - rolePermission.setIpAddress(ipAddresses); - - policy.setPermissions(rolePermissions); - - policies.add(policy); - - policyContainer.setAcl(policies); - - return policyContainer; - } - - private static Set<String> asSet(String... a) { - Set<String> vals = new HashSet<String>(); - for (String s : a) { - vals.add(s); - } - return vals; - } - - private static List<String> asList(String... a) { - List<String> vals = new ArrayList<String>(); - for (String s : a) { - vals.add(s); - } - return vals; - } - - - private PolicyContainer readPolicyCache(String lastStoreFileName) { - BufferedReader jsonString = null; - try { - jsonString = new BufferedReader(new FileReader(lastStoredFileName)); - } catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - Gson gson = new GsonBuilder().create(); - PolicyContainer newPolicyContainer = gson.fromJson(jsonString, PolicyContainer.class); - return newPolicyContainer; - } - - private String policyToString(PolicyContainer pc) { - Gson gson = new GsonBuilder().create() ; - String policyAsJson = gson.toJson(policyContainer) ; - return policyAsJson; - } - - -} - http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/test/java/com/xasecure/pdp/hdfs/URLBasedAuthDBTest.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/test/java/com/xasecure/pdp/hdfs/URLBasedAuthDBTest.java b/agents-impl/src/test/java/com/xasecure/pdp/hdfs/URLBasedAuthDBTest.java deleted file mode 100644 index 4a19d98..0000000 --- a/agents-impl/src/test/java/com/xasecure/pdp/hdfs/URLBasedAuthDBTest.java +++ /dev/null @@ -1,66 +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 com.xasecure.pdp.hdfs; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import com.xasecure.pdp.model.Policy; -import com.xasecure.pdp.model.PolicyContainer; -import com.xasecure.pdp.model.ResourcePath; - -public class URLBasedAuthDBTest { - - @Test - public void testIsAuditLogEnabledByACL_emptyPolicyContainer() { - - // audit can't be enabled if authdb isn't initialized - assertFalse(mAuthDB.isAuditLogEnabledByACL("blah")); - - // or if the policy container in is null! - URLBasedAuthDB spy = spy(mAuthDB); - when(spy.getPolicyContainer()).thenReturn(null); - assertFalse(mAuthDB.isAuditLogEnabledByACL("blah")); - - // of if policy container is empty, i.e. has no policies! - List<Policy> policies = new ArrayList<Policy>(); - PolicyContainer policyContainer = mock(PolicyContainer.class); - when(policyContainer.getAcl()).thenReturn(policies); - when(spy.getPolicyContainer()).thenReturn(policyContainer); - assertFalse(mAuthDB.isAuditLogEnabledByACL("blah")); - - // or if all policies are empty, i.e. no acls! - Policy aPolicy = mock(Policy.class); - when(aPolicy.getResourceList()).thenReturn(new ArrayList<ResourcePath>()); - policies.add(aPolicy); - when(policyContainer.getAcl()).thenReturn(policies); - when(spy.getPolicyContainer()).thenReturn(policyContainer); - assertFalse(spy.isAuditLogEnabledByACL("blah")); - } - - private final URLBasedAuthDB mAuthDB = URLBasedAuthDB.getInstance(); -} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/413fcb68/agents-impl/src/test/java/com/xasecure/pdp/hdfs/URLBasedAuthDB_IsAuditLogEnabledByACL_PTest.java ---------------------------------------------------------------------- diff --git a/agents-impl/src/test/java/com/xasecure/pdp/hdfs/URLBasedAuthDB_IsAuditLogEnabledByACL_PTest.java b/agents-impl/src/test/java/com/xasecure/pdp/hdfs/URLBasedAuthDB_IsAuditLogEnabledByACL_PTest.java deleted file mode 100644 index 02c81f5..0000000 --- a/agents-impl/src/test/java/com/xasecure/pdp/hdfs/URLBasedAuthDB_IsAuditLogEnabledByACL_PTest.java +++ /dev/null @@ -1,340 +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 com.xasecure.pdp.hdfs; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import com.xasecure.pdp.model.Policy; -import com.xasecure.pdp.model.PolicyContainer; -import com.xasecure.pdp.model.ResourcePath; - -@RunWith(Parameterized.class) -public class URLBasedAuthDB_IsAuditLogEnabledByACL_PTest { - - static class PolicyIs { - static final boolean wildcard = true; - static final boolean audited = true; - static final boolean recursive = true; - - static final boolean notWildcard = false; - static final boolean notAudited = false; - static final boolean notRecursive = false; - } - - static final class PolicyPath { - static final String path1 = "aPath"; - static final String path1Child1 = PolicyPath.path1 + "/" + "child1"; - static final String path1Child2 = PolicyPath.path1 + "/" + "child2"; - - static final String path2 = "anotherPath"; - } - static final class TestPath { - static final String path1 = PolicyPath.path1; - static final String beginsWithPath1 = PolicyPath.path1 + "_"; - static final String path1Child1 = PolicyPath.path1Child1; - static final String path1Child2 = PolicyPath.path1Child2; - static final String path1GrandChild1 = String.format("%s/%s/%s", path1, path1Child1, "grandChild1"); - static final String path1GrandChild2 = String.format("%s/%s/%s", path1, path1Child1, "grandChild2"); - - static final String path2 = PolicyPath.path2; - static final String beginsWithPath2 = PolicyPath.path2 + "_"; - static final String path2Child1 = PolicyPath.path2 + "/" + "child1"; - static final String path2Child2 = PolicyPath.path2 + "/" + "child2"; - } - - static class ExpectedResult { - static final class AuditEnabled { - static final boolean yes = true; - static final boolean no = false; - } - } - - static class TestDataIndex { - static final int ExpectedResult = 6; - static final int Audited = 3; - public static final int TestName = 0; - public static final int wildCard = 2; - } - - - /** - * ASSUMPTION: set of tests passed as such that they require wildcard flag to be set for them to return audit enabled. - * So turn wildcard flag of them off to assert that they no-longer work. Of course, those that don't work even with wildcard - * should also continue to not work when wildcard is turned off! - */ - private static List<Object[]> turnWildcardOffForTestsThatRequireWildcard(List<Object[]> tests) { - - // in the worse case we would generate one test for each existing test - List<Object[]> newTests = new ArrayList<Object[]>(tests.size()); - for (Object[] aTest: tests) { - boolean isPolicyWildcard = (Boolean) aTest[TestDataIndex.wildCard]; - if (isPolicyWildcard == PolicyIs.wildcard) { - Object[] newTest = Arrays.copyOf(aTest, aTest.length); - // Change the policy of this test so that Audit is disabled at policy level and accordingly change the expected result - newTest[TestDataIndex.wildCard] = PolicyIs.notWildcard; - newTest[TestDataIndex.ExpectedResult] = ExpectedResult.AuditEnabled.no; - // for debugging purposes alter the test description, too - String testName = (String) newTest[TestDataIndex.TestName]; - newTest[TestDataIndex.TestName] = "[Wildcard-ed base test with wildcard flag turned off] " + testName; - newTests.add(newTest); - } - } - return newTests; - } - - /** - * wildcard - policy flag says wildcard by the policy path itself does not have any wildcards worth expanding. - * This should work exactly the same as if wildcard was turned off! - */ - private static List<Object[]> turnWildcardOnForNonWildcardTests(List<Object[]> tests) { - - // in the worse case we would generate one test for each existing test - List<Object[]> newTests = new ArrayList<Object[]>(tests.size()); - /* - * If a test currently does not have wildcard set on it, then expectation is changing wildcard flag - * true shouldn't change the result. ASSUMPTION here, of course, is that "base tests" don't use any - * wild-card characters in their resource paths that would make an otherwise disabled audit to return enabled. - */ - for (Object[] aTest: tests) { - boolean isPolicyWildcard = (Boolean) aTest[TestDataIndex.wildCard]; - if (isPolicyWildcard == PolicyIs.notWildcard) { - Object[] newTest = Arrays.copyOf(aTest, aTest.length); - // Change the policy of this test so that Audit is disabled at policy level and accordingly change the expected result - newTest[TestDataIndex.wildCard] = PolicyIs.wildcard; - // for debugging purposes alter the test description, too - String testName = (String) newTest[TestDataIndex.TestName]; - newTest[TestDataIndex.TestName] = "[Base test with wildcard enabled] " + testName; - newTests.add(newTest); - } - } - return newTests; - } - - /** - * Disabled audit on every test that expects result to be yes to ensure that no matter what answer should be false if policy says that audit is disabled! - */ - private static List<Object[]> disableAuditForBaseTests(List<Object[]> tests) { - - List<Object[]> newTests = new ArrayList<Object[]>(tests.size()); - - for (Object[] aTest : tests) { - boolean expectedResult = (Boolean) aTest[TestDataIndex.ExpectedResult]; - boolean isPolicyAuditEnabled = (Boolean) aTest[TestDataIndex.Audited]; - - if (expectedResult == ExpectedResult.AuditEnabled.yes - && isPolicyAuditEnabled == PolicyIs.audited) { - Object[] newTest = Arrays.copyOf(aTest, aTest.length); - // Change the policy of this test so that Audit is disabled at policy level and accordingly change the expected result - newTest[TestDataIndex.Audited] = PolicyIs.notAudited; - newTest[TestDataIndex.ExpectedResult] = ExpectedResult.AuditEnabled.no; - // for debugging purposes alter the test description, too - String testName = (String) newTest[TestDataIndex.TestName]; - newTest[TestDataIndex.TestName] = "[Base tests with audit disabled] " + testName; - newTests.add(newTest); - } - } - - return newTests; - } - - @Parameters - public static Collection<Object[]> data() { - Object[][] baseTestData = new Object[][] { - - // no-recursive paths - return true if paths match - {"policypath(path1) == testpath(path1) => yes", - PolicyPath.path1, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.notRecursive, TestPath.path1, ExpectedResult.AuditEnabled.yes}, - {"policypath(path2) == testpath(path2) => yes", - PolicyPath.path2, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.notRecursive, TestPath.path2, ExpectedResult.AuditEnabled.yes}, - - // no-recursive paths - return false if paths don't match! - {"policypath(path1) != testPath(path2) => no", - PolicyPath.path1, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.notRecursive, TestPath.path2, ExpectedResult.AuditEnabled.no}, - {"policypath(path2) != testPath(path1) => no", - PolicyPath.path2, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.notRecursive, TestPath.path1, ExpectedResult.AuditEnabled.no}, - - // recursive path policy - should work at least as well as non-recursive, i.e. match when same and not otherwise! - {"recursive, policypath(path1) == testpath(path1)", - PolicyPath.path1, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path1, ExpectedResult.AuditEnabled.yes}, - {"recursive, policypath(path2) == testpath(path2)", - PolicyPath.path2, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path2, ExpectedResult.AuditEnabled.yes}, - {"recursive, policypath(path1) == testpath(path2)", - PolicyPath.path1, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path2, ExpectedResult.AuditEnabled.no}, - {"recursive, policypath(path1) == testpath(path2)", - PolicyPath.path2, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path1, ExpectedResult.AuditEnabled.no}, - - // recursive path policy - should match children - {"recursive, policypath(path1) == testpath(path1/child1)", - PolicyPath.path1, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path1Child1, ExpectedResult.AuditEnabled.yes}, - {"recursive, policypath(path1) == testpath(path1/child2)", - PolicyPath.path1, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path1Child2, ExpectedResult.AuditEnabled.yes}, - {"recursive, policypath(path1) == testpath(path1/child1)", - PolicyPath.path2, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path2Child1, ExpectedResult.AuditEnabled.yes}, - {"recursive, policypath(path1) == testpath(path1/child2)", - PolicyPath.path2, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path2Child2, ExpectedResult.AuditEnabled.yes}, - - // recursive path policy - should match grand children, too! - {"recursive, policypath(path1) == testpath(path1/child1/grandChild1)", - PolicyPath.path1, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path1GrandChild1, ExpectedResult.AuditEnabled.yes}, - {"recursive, policypath(path1) == testpath(path1/child1/grandChild2)", - PolicyPath.path1, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path1GrandChild2, ExpectedResult.AuditEnabled.yes}, - - // recursive path policy - shouldn't match child in some other directory - {"recursive, policypath(path1) == testpath(path1/child1)", - PolicyPath.path1, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path2Child1, ExpectedResult.AuditEnabled.no}, - {"recursive, policypath(path1) == testpath(path1/child2)", - PolicyPath.path1, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path2Child2, ExpectedResult.AuditEnabled.no}, - {"recursive, policypath(path1) == testpath(path1/child1)", - PolicyPath.path2, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path1Child1, ExpectedResult.AuditEnabled.no}, - {"recursive, policypath(path1) == testpath(path1/child2)", - PolicyPath.path2, PolicyIs.notWildcard, PolicyIs.audited, PolicyIs.recursive, TestPath.path1Child2, ExpectedResult.AuditEnabled.no}, - - }; - - Object[][] wildCardTestData = new Object[][] { - // Pattern contains exact substring - {"Wildcard, Pattern contains substring of tested path - 1", - "aPath*", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "aPath", ExpectedResult.AuditEnabled.yes}, - {"Wildcard, Pattern contains substring of tested path - 2", - "*aPath", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "aPath", ExpectedResult.AuditEnabled.yes}, - {"Wildcard, Pattern contains substring of tested path - 3", - "aPa*th", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "aPath", ExpectedResult.AuditEnabled.yes}, - {"Wildcard, Pattern contains substring of tested path - 4", - "aP*at*h", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "aPath", ExpectedResult.AuditEnabled.yes}, - - // Pattern should match - {"Wildcard, Pattern should match - 1", - "aPath*", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "aPath_", ExpectedResult.AuditEnabled.yes}, - {"Wildcard, Pattern should match - 2", - "aPath*", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "aPath_longSuffix", ExpectedResult.AuditEnabled.yes}, - {"Wildcard, Pattern should match - 3", - "*aPath", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "_aPath", ExpectedResult.AuditEnabled.yes}, - {"Wildcard, Pattern should match - 4", - "*aPath", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "longPrefix_aPath", ExpectedResult.AuditEnabled.yes}, - {"Wildcard, Pattern should match - 5", - "*aPath", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "_aPath", ExpectedResult.AuditEnabled.yes}, - {"Wildcard, Pattern should match - 6", - "*aPath", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "longPrefix_aPath", ExpectedResult.AuditEnabled.yes}, - {"Wildcard, Pattern should match - 5", - "a*Path", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "a___Path", ExpectedResult.AuditEnabled.yes}, - {"Wildcard, Pattern should match - 6", - "a*Path", PolicyIs.wildcard, PolicyIs.audited, PolicyIs.recursive, "aMiddlePath", ExpectedResult.AuditEnabled.yes}, - }; - - // in the worst case all tests have a corresponding audit disabled test - List<Object[]> baseTests = Arrays.asList(baseTestData); - List<Object[]> result = new ArrayList<Object[]>(baseTests); - - // answer is false no matter what if policy is set to not audit - List<Object[]> additionalTests = disableAuditForBaseTests(baseTests); - result.addAll(additionalTests); - - // turning wildcard flag on when policy path itself does not have wildcard characters in it shouldn't change the result! - additionalTests = turnWildcardOnForNonWildcardTests(baseTests); - result.addAll(additionalTests); - - List<Object[]> wildcardBaseTests = Arrays.asList(wildCardTestData); - result.addAll(wildcardBaseTests); - - additionalTests = turnWildcardOffForTestsThatRequireWildcard(wildcardBaseTests); - result.addAll(additionalTests); - return result; - } - - public URLBasedAuthDB_IsAuditLogEnabledByACL_PTest(String testName, String policyPath, boolean wildCard, boolean audited, boolean recursive, String testPath, boolean expectedResult) { - _testName = testName; - _policyPath = policyPath; - _policyPathWildcard = wildCard; - _policyAudited = audited; - _policyRecursive = recursive; - _testPath = testPath; - _expectedResult = expectedResult; - } - - private final String _testName; - private final String _policyPath; - private final boolean _policyPathWildcard; - private final boolean _policyAudited; - private final boolean _policyRecursive; - private final String _testPath; - private final boolean _expectedResult; - - @Test - public void testIsAuditLogEnabledByACL() { - - if (LOG.isDebugEnabled()) { - LOG.debug(String.format("Test: %sPolicy Path: %s, isWildcard: %b, isAudited: %b, isRecursive: %b, TestPath: %s", - _testName, _policyPath, _policyPathWildcard, _policyAudited, _policyRecursive, _testPath)); - } - - // A policy can have several paths, so let's first stuff our path into a collection - ResourcePath path = mock(ResourcePath.class); - when(path.getPath()).thenReturn(_policyPath); - when(path.isWildcardPath()).thenReturn(_policyPathWildcard); - List<ResourcePath> resourcePaths = new ArrayList<ResourcePath>(); - resourcePaths.add(path); - - // wire it into the policy and set other aspects of the policy - Policy aPolicy = mock(Policy.class); - when(aPolicy.getResourceList()).thenReturn(resourcePaths); - - int recursiveIndicator = _policyRecursive ? 1 : 0; - when(aPolicy.getRecursiveInd()).thenReturn(recursiveIndicator); - - int auditedIndicator = _policyAudited ? 1 : 0; - when(aPolicy.getAuditInd()).thenReturn(auditedIndicator); - - // a container can have several policies to first we stuff our policy into a container - List<Policy> policies = new ArrayList<Policy>(); - policies.add(aPolicy); - // now wire the policy into the container - PolicyContainer policyContainer = mock(PolicyContainer.class); - when(policyContainer.getAcl()).thenReturn(policies); - - // finally wire the policy container into the authdb - URLBasedAuthDB spy = spy(mAuthDB); - when(spy.getPolicyContainer()).thenReturn(policyContainer); - - // assert the result - boolean result = spy.isAuditLogEnabledByACL(_testPath); - assertThat(_testName, result, is(_expectedResult)); - if (LOG.isDebugEnabled()) { - LOG.debug(String.format(", Expected Result (Audit enabled?): %b Result: %b\n", _expectedResult, result)); - } - } - - private final URLBasedAuthDB mAuthDB = URLBasedAuthDB.getInstance(); - private static final Log LOG = LogFactory.getLog(URLBasedAuthDB_IsAuditLogEnabledByACL_PTest.class) ; -}
