This is an automated email from the ASF dual-hosted git repository. abhay pushed a commit to branch ranger-2.2 in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.2 by this push: new af38489 RANGER-3082: User with delegated-admin is unable to create policy af38489 is described below commit af384899abda5888414700beff26fc67a518b7e3 Author: Abhay Kulkarni <ab...@apache.org> AuthorDate: Wed Nov 25 22:42:06 2020 -0800 RANGER-3082: User with delegated-admin is unable to create policy --- .../ranger/plugin/policyengine/PolicyEngine.java | 25 +++++++- .../RangerDefaultPolicyEvaluator.java | 8 +-- .../policyevaluator/RangerPolicyEvaluator.java | 2 +- .../org/apache/ranger/biz/RangerPolicyAdmin.java | 2 +- .../apache/ranger/biz/RangerPolicyAdminImpl.java | 72 ++++++++++++++++++++-- .../java/org/apache/ranger/rest/ServiceREST.java | 11 +++- 6 files changed, 106 insertions(+), 14 deletions(-) diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java index 3250719..2742312 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java @@ -40,12 +40,14 @@ import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.model.validation.RangerZoneResourceMatcher; import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator; import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.ranger.plugin.resourcematcher.RangerAbstractResourceMatcher; import org.apache.ranger.plugin.service.RangerAuthContext; import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; import org.apache.ranger.plugin.util.RangerPerfTracer; import org.apache.ranger.plugin.util.RangerPolicyDeltaUtil; import org.apache.ranger.plugin.util.RangerRoles; import org.apache.ranger.plugin.util.ServicePolicies; +import org.apache.ranger.plugin.util.StringTokenReplacer; public class PolicyEngine { private static final Log LOG = LogFactory.getLog(PolicyEngine.class); @@ -62,6 +64,7 @@ public class PolicyEngine { private final Map<String, String> zoneTagServiceMap = new HashMap<>(); private boolean useForwardedIPAddress; private String[] trustedProxyAddresses; + private final Map<String, StringTokenReplacer> tokenReplacers = new HashMap<>(); public boolean getUseForwardedIPAddress() { return useForwardedIPAddress; @@ -109,6 +112,10 @@ public class PolicyEngine { public RangerPluginContext getPluginContext() { return pluginContext; } + public StringTokenReplacer getStringTokenReplacer(String resourceName) { + return tokenReplacers.get(resourceName); + } + @Override public String toString() { return toString(new StringBuilder()).toString(); @@ -159,7 +166,7 @@ public class PolicyEngine { return resourceZoneTrie; } - public PolicyEngine(ServicePolicies servicePolicies, RangerPluginContext pluginContext, RangerRoles roles) { + public PolicyEngine(ServicePolicies servicePolicies, RangerPluginContext pluginContext, RangerRoles roles) { if (LOG.isDebugEnabled()) { LOG.debug("==> PolicyEngine(" + ", " + servicePolicies + ", " + pluginContext + ")"); } @@ -233,6 +240,20 @@ public class PolicyEngine { } } + for (RangerServiceDef.RangerResourceDef resourceDef : getServiceDef().getResources()) { + Map<String, String> matchOptions = resourceDef.getMatcherOptions(); + + if (RangerAbstractResourceMatcher.getOptionReplaceTokens(matchOptions)) { + String delimiterPrefix = RangerAbstractResourceMatcher.getOptionDelimiterPrefix(matchOptions); + char delimiterStart = RangerAbstractResourceMatcher.getOptionDelimiterStart(matchOptions); + char delimiterEnd = RangerAbstractResourceMatcher.getOptionDelimiterEnd(matchOptions); + char escapeChar = RangerAbstractResourceMatcher.getOptionDelimiterEscape(matchOptions); + + StringTokenReplacer tokenReplacer = new StringTokenReplacer(delimiterStart, delimiterEnd, escapeChar, delimiterPrefix); + tokenReplacers.put(resourceDef.getName(), tokenReplacer); + } + } + RangerPerfTracer.log(perf); if (PERF_POLICYENGINE_INIT_LOG.isDebugEnabled()) { @@ -639,7 +660,7 @@ public class PolicyEngine { List<RangerContextEnricher> tmpList; List<RangerContextEnricher> tagContextEnrichers = tagPolicyRepository == null ? null :tagPolicyRepository.getContextEnrichers(); - List<RangerContextEnricher> resourceContextEnrichers = policyRepository.getContextEnrichers(); + List<RangerContextEnricher> resourceContextEnrichers = policyRepository == null ? null : policyRepository.getContextEnrichers(); if (CollectionUtils.isEmpty(tagContextEnrichers)) { tmpList = resourceContextEnrichers; diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java index f3e0dab..07fb638 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java @@ -369,15 +369,15 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator } @Override - public boolean isAccessAllowed(RangerPolicy policy, String user, Set<String> userGroups, Set<String> roles, String accessType) { + public boolean isAccessAllowed(Long policyId, Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, Set<String> roles, String accessType, Map<String, Object> evalContext) { if(LOG.isDebugEnabled()) { - LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ")"); + LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + policyId + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ", " + evalContext + ")"); } - boolean ret = isAccessAllowed(user, userGroups, roles, null, accessType) && isMatch(policy, null); + boolean ret = isAccessAllowed(user, userGroups, roles, null, accessType) && isMatch(resources, evalContext); if(LOG.isDebugEnabled()) { - LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + "): " + ret); + LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + policyId + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ", " + evalContext + "): " + ret); } return ret; diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java index 14b626d..236f998 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java @@ -98,7 +98,7 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator { boolean isAccessAllowed(Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, String accessType); - boolean isAccessAllowed(RangerPolicy policy, String user, Set<String> userGroups, Set<String> roles, String accessType); + boolean isAccessAllowed(Long policyId, Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, Set<String> roles, String accessType, Map<String, Object> evalContext); void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, boolean isAllowed, String reason); diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdmin.java b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdmin.java index e011c0b..891c800 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdmin.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdmin.java @@ -33,7 +33,7 @@ public interface RangerPolicyAdmin { boolean isAccessAllowed(RangerAccessResource resource, String zoneName, String user, Set<String> userGroups, String accessType); - boolean isAccessAllowed(RangerPolicy policy, String user, Set<String> userGroups, Set<String> roles, String accessType); + boolean isAccessAllowed(RangerPolicy policy, String user, Set<String> userGroups, Set<String> roles, String accessType, Map<String, Object> evalContext); List<RangerPolicy> getExactMatchPolicies(RangerAccessResource resource, String zoneName, Map<String, Object> evalContext); diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java index 6fc0abf..cd566bc 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java @@ -37,14 +37,18 @@ import org.apache.ranger.plugin.policyengine.RangerPolicyRepository; import org.apache.ranger.plugin.policyengine.RangerTagResource; import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator; import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.ranger.plugin.resourcematcher.RangerAbstractResourceMatcher; import org.apache.ranger.plugin.service.RangerDefaultRequestProcessor; import org.apache.ranger.plugin.util.GrantRevokeRequest; import org.apache.ranger.plugin.util.RangerAccessRequestUtil; import org.apache.ranger.plugin.util.RangerPerfTracer; import org.apache.ranger.plugin.util.RangerRoles; import org.apache.ranger.plugin.util.ServicePolicies; +import org.apache.ranger.plugin.util.StringTokenReplacer; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -56,6 +60,14 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin { private final PolicyEngine policyEngine; private final RangerAccessRequestProcessor requestProcessor; + private final static Map<String, Object> wildcardEvalContext = new HashMap<String, Object>() { + @Override + public Object get(Object key) { return RangerAbstractResourceMatcher.WILDCARD_ASTERISK; } + }; + + static { + wildcardEvalContext.put(RangerAbstractResourceMatcher.WILDCARD_ASTERISK, RangerAbstractResourceMatcher.WILDCARD_ASTERISK); + } static public RangerPolicyAdmin getPolicyAdmin(final RangerPolicyAdminImpl other, final ServicePolicies servicePolicies) { RangerPolicyAdmin ret = null; @@ -123,9 +135,9 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin { } @Override - public boolean isAccessAllowed(RangerPolicy policy, String user, Set<String> userGroups, Set<String> roles, String accessType) { + public boolean isAccessAllowed(RangerPolicy policy, String user, Set<String> userGroups, Set<String> roles, String accessType, Map<String, Object> evalContext) { if (LOG.isDebugEnabled()) { - LOG.debug("==> RangerPolicyAdminImpl.isAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ")"); + LOG.debug("==> RangerPolicyAdminImpl.isAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ", " + evalContext + ")"); } boolean ret = false; @@ -138,8 +150,12 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin { final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForMatchedZone(policy); if (matchedRepository != null) { + // RANGER-3082 + // Convert policy resources to by substituting macros with ASTERISK + Map<String, RangerPolicyResource> modifiedPolicyResources = getPolicyResourcesWithMacrosReplaced(policy.getResources(), wildcardEvalContext); + for (RangerPolicyEvaluator evaluator : matchedRepository.getPolicyEvaluators()) { - ret = evaluator.isAccessAllowed(policy, user, userGroups, roles, accessType); + ret = evaluator.isAccessAllowed(policy.getId(), modifiedPolicyResources, user, userGroups, roles, accessType, evalContext); if (ret) { break; @@ -150,7 +166,7 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin { RangerPerfTracer.log(perf); if (LOG.isDebugEnabled()) { - LOG.debug("<== RangerPolicyAdminImpl.isAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + "): " + ret); + LOG.debug("<== RangerPolicyAdminImpl.isAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ", " + evalContext + "): " + ret); } return ret; @@ -421,5 +437,53 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin { } } + + private Map<String, RangerPolicyResource> getPolicyResourcesWithMacrosReplaced(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyAdminImpl.getPolicyResourcesWithMacrosReplaced(" + resources + ", " + evalContext + ")"); + } + + final Map<String, RangerPolicyResource> ret; + + Collection<String> resourceKeys = resources == null ? null : resources.keySet(); + + if (CollectionUtils.isNotEmpty(resourceKeys)) { + ret = new HashMap<>(); + + for (String resourceName : resourceKeys) { + RangerPolicyResource resourceValues = resources.get(resourceName); + List<String> values = resourceValues == null ? null : resourceValues.getValues(); + + if (CollectionUtils.isNotEmpty(values)) { + StringTokenReplacer tokenReplacer = policyEngine.getStringTokenReplacer(resourceName); + + if (tokenReplacer != null) { + List<String> modifiedValues = new ArrayList<>(); + + for (String value : values) { + // RANGER-3082 - replace macros in value with ASTERISK + String modifiedValue = tokenReplacer.replaceTokens(value, evalContext); + modifiedValues.add(modifiedValue); + } + + RangerPolicyResource modifiedPolicyResource = new RangerPolicyResource(modifiedValues, resourceValues.getIsExcludes(), resourceValues.getIsRecursive()); + ret.put(resourceName, modifiedPolicyResource); + } else { + ret.put(resourceName, resourceValues); + } + } else { + ret.put(resourceName, resourceValues); + } + } + } else { + ret = resources; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.getPolicyResourcesWithMacrosReplaced(" + resources + ", " + evalContext + "): " + ret); + } + + return ret; + } } diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java index 3a1510c..9aad6db 100644 --- a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java +++ b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java @@ -120,6 +120,7 @@ import org.apache.ranger.plugin.store.PList; import org.apache.ranger.plugin.store.ServiceStore; import org.apache.ranger.plugin.util.GrantRevokeRequest; import org.apache.ranger.plugin.util.JsonUtilsV2; +import org.apache.ranger.plugin.util.RangerAccessRequestUtil; import org.apache.ranger.plugin.util.RangerPerfTracer; import org.apache.ranger.plugin.util.SearchFilter; import org.apache.ranger.plugin.util.ServicePolicies; @@ -3550,6 +3551,9 @@ public class ServiceREST { Set<String> userGroups = null; Map<String, List<RangerPolicy>> servicePoliciesMap = new HashMap<String, List<RangerPolicy>>(); + Map<String, Object> evalContext = new HashMap<>(); + + RangerAccessRequestUtil.setCurrentUserInContext(evalContext, userName); for (int i = 0; i < policies.size(); i++) { RangerPolicy policy = policies.get(i); @@ -3609,7 +3613,7 @@ public class ServiceREST { Set<String> roles = policyAdmin.getRolesFromUserAndGroups(userName, userGroups); for (RangerPolicy policy : listToFilter) { - if (policyAdmin.isAccessAllowed(policy, userName, userGroups, roles, RangerPolicyEngine.ADMIN_ACCESS) + if (policyAdmin.isAccessAllowed(policy, userName, userGroups, roles, RangerPolicyEngine.ADMIN_ACCESS, evalContext) || (!StringUtils.isEmpty(policy.getZoneName()) && (serviceMgr.isZoneAdmin(policy.getZoneName()) || serviceMgr.isZoneAuditor(policy.getZoneName()))) || isServiceAdminUser) { ret.add(policy); @@ -3704,9 +3708,12 @@ public class ServiceREST { RangerPolicyAdmin policyAdmin = getPolicyAdminForDelegatedAdmin(policy.getService()); if(policyAdmin != null) { + Map evalContext = new HashMap<>(); + RangerAccessRequestUtil.setCurrentUserInContext(evalContext, userName); + Set<String> roles = policyAdmin.getRolesFromUserAndGroups(userName, userGroups); - isAllowed = policyAdmin.isAccessAllowed(policy, userName, userGroups, roles, RangerPolicyEngine.ADMIN_ACCESS); + isAllowed = policyAdmin.isAccessAllowed(policy, userName, userGroups, roles, RangerPolicyEngine.ADMIN_ACCESS, evalContext); } return isAllowed;