You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ab...@apache.org on 2020/11/26 06:54:47 UTC

[ranger] branch master updated: RANGER-3082: User with delegated-admin is unable to create policy

This is an automated email from the ASF dual-hosted git repository.

abhay pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new 6b5d5fb  RANGER-3082: User with delegated-admin is unable to create policy
6b5d5fb is described below

commit 6b5d5fb3469df532df4528e1c4cd8cb503f44eba
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 39869d3..5202587 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;
@@ -3533,6 +3534,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);
@@ -3592,7 +3596,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);
@@ -3687,9 +3691,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;