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 696d4340b RANGER-4378: Expand implied grants in the policy-items for being able to compare policy-cache dumps from server and client 696d4340b is described below commit 696d4340bfdf6c38f7cb4f53fc31b14e1ffaa0e7 Author: Abhay Kulkarni <ab...@apache.org> AuthorDate: Mon Sep 25 09:01:33 2023 -0700 RANGER-4378: Expand implied grants in the policy-items for being able to compare policy-cache dumps from server and client --- .../apache/ranger/plugin/model/RangerPolicy.java | 4 + .../ranger/plugin/policyengine/PolicyEngine.java | 44 +++++++++ .../RangerAbstractPolicyItemEvaluator.java | 59 ++++++++++++ .../RangerAuditPolicyEvaluator.java | 2 +- .../RangerDefaultPolicyEvaluator.java | 51 ++++------ .../RangerDefaultPolicyItemEvaluator.java | 107 ++++++++++++--------- .../RangerOptimizedPolicyEvaluator.java | 106 ++++++++++++++------ .../policyevaluator/RangerPolicyEvaluator.java | 43 +++++++-- .../policyevaluator/RangerPolicyItemEvaluator.java | 1 + 9 files changed, 298 insertions(+), 119 deletions(-) diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java index 9e5a94b1a..ec0618421 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java @@ -959,6 +959,10 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria this(null, null, null, null, null, null); } + public RangerPolicyItem(RangerPolicyItem other) { + this(other.accesses, other.users, other.groups, other.roles, other.conditions, other.delegateAdmin); + } + public RangerPolicyItem(List<RangerPolicyItemAccess> accessTypes, List<String> users, List<String> groups, List<String> roles, List<RangerPolicyItemCondition> conditions, Boolean delegateAdmin) { setAccesses(accessTypes); setUsers(users); 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 1e99b5824..4a5406301 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 @@ -71,6 +71,13 @@ public class PolicyEngine { private final RangerReadWriteLock lock; + static private Map<String, Map<String, Collection<String>>> impliedAccessGrants = null; + + static public Map<String, Collection<String>> getImpliedAccessGrants(RangerServiceDef serviceDef) { + return impliedAccessGrants == null ? null : impliedAccessGrants.get(serviceDef.getName()); + } + + public RangerReadWriteLock.RangerLock getReadLock() { return lock.getReadLock(); } @@ -197,6 +204,8 @@ public class PolicyEngine { PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory - freeMemory) + ", Free memory:" + freeMemory); } + buildImpliedAccessGrants(servicePolicies); + this.pluginContext = pluginContext; this.lock = new RangerReadWriteLock(isUseReadWriteLock); @@ -471,6 +480,41 @@ public class PolicyEngine { } } + synchronized static private void buildImpliedAccessGrants(ServicePolicies servicePolicies) { + buildImpliedAccessGrants(servicePolicies.getServiceDef()); + if (servicePolicies.getTagPolicies() != null) { + buildImpliedAccessGrants(servicePolicies.getTagPolicies().getServiceDef()); + } + } + + static private void buildImpliedAccessGrants(RangerServiceDef serviceDef) { + Map<String, Collection<String>> ret = null; + + if (serviceDef != null && !CollectionUtils.isEmpty(serviceDef.getAccessTypes())) { + for (RangerServiceDef.RangerAccessTypeDef accessTypeDef : serviceDef.getAccessTypes()) { + if (!CollectionUtils.isEmpty(accessTypeDef.getImpliedGrants())) { + if (ret == null) { + ret = new HashMap<>(); + } + + Collection<String> impliedGrants = ret.get(accessTypeDef.getName()); + + if (impliedGrants == null) { + impliedGrants = new HashSet<>(); + + ret.put(accessTypeDef.getName(), impliedGrants); + } + + impliedGrants.addAll(accessTypeDef.getImpliedGrants()); + } + } + + if (impliedAccessGrants == null) { + impliedAccessGrants = Collections.synchronizedMap(new HashMap<>()); + } + impliedAccessGrants.put(serviceDef.getName(), ret); + } + } private Set<String> getMatchedZonesForResourceAndChildren(Map<String, ?> resource, RangerAccessResource accessResource) { if (LOG.isDebugEnabled()) { LOG.debug("==> PolicyEngine.getMatchedZonesForResourceAndChildren(" + resource + ", " + accessResource + ")"); diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java index 0f09952f7..a3e3806ec 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java @@ -19,14 +19,17 @@ package org.apache.ranger.plugin.policyevaluator; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; import org.apache.commons.collections.CollectionUtils; import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator; import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.policyengine.PolicyEngine; import org.apache.ranger.plugin.policyengine.RangerPolicyEngine; import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; @@ -50,6 +53,7 @@ public abstract class RangerAbstractPolicyItemEvaluator implements RangerPolicyI final int evalOrder; List<RangerConditionEvaluator> conditionEvaluators = Collections.<RangerConditionEvaluator>emptyList(); + RangerPolicyItem withImpliedGrants; RangerAbstractPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, int policyItemType, int policyItemIndex, RangerPolicyEngineOptions options) { this.serviceDef = serviceDef; @@ -100,6 +104,61 @@ public abstract class RangerAbstractPolicyItemEvaluator implements RangerPolicyI return options != null && options.disableCustomConditions; } + @Override + public RangerPolicyItem getWithImpliedGrants() { + return withImpliedGrants; + } + + protected RangerPolicyItem computeWithImpliedGrants() { + + final RangerPolicyItem ret; + + if (withImpliedGrants == null) { + if (CollectionUtils.isEmpty(policyItem.getAccesses())) { + ret = policyItem; + } else { + // Compute implied-accesses + Map<String, Collection<String>> impliedAccessGrants = PolicyEngine.getImpliedAccessGrants(serviceDef); + + if (impliedAccessGrants != null && !impliedAccessGrants.isEmpty()) { + ret = new RangerPolicyItem(policyItem); + + // Only one round of 'expansion' is done; multi-level impliedGrants (like shown below) are not handled for now + // multi-level impliedGrants: given admin=>write; write=>read: must imply admin=>read,write + for (Map.Entry<String, Collection<String>> e : impliedAccessGrants.entrySet()) { + String implyingAccessType = e.getKey(); + Collection<String> impliedGrants = e.getValue(); + + RangerPolicy.RangerPolicyItemAccess access = RangerDefaultPolicyEvaluator.getAccess(ret, implyingAccessType); + + if (access == null) { + continue; + } + + for (String impliedGrant : impliedGrants) { + RangerPolicy.RangerPolicyItemAccess impliedAccess = RangerDefaultPolicyEvaluator.getAccess(ret, impliedGrant); + + if (impliedAccess == null) { + impliedAccess = new RangerPolicy.RangerPolicyItemAccess(impliedGrant, access.getIsAllowed()); + + ret.getAccesses().add(impliedAccess); + } else { + if (!impliedAccess.getIsAllowed()) { + impliedAccess.setIsAllowed(access.getIsAllowed()); + } + } + } + } + } else { + ret = policyItem; + } + } + } else { + ret = withImpliedGrants; + } + return ret; + } + private int computeEvalOrder() { int evalOrder = RANGER_POLICY_ITEM_EVAL_ORDER_DEFAULT; diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAuditPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAuditPolicyEvaluator.java index ba24b8c3e..9051a8ce4 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAuditPolicyEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAuditPolicyEvaluator.java @@ -103,7 +103,7 @@ public class RangerAuditPolicyEvaluator extends RangerDefaultPolicyEvaluator { protected void preprocessPolicy(RangerPolicy policy, RangerServiceDef serviceDef) { super.preprocessPolicy(policy, serviceDef); - Map<String, Collection<String>> impliedAccessGrants = getImpliedAccessGrants(serviceDef); + Map<String, Collection<String>> impliedAccessGrants = PolicyEngine.getImpliedAccessGrants(serviceDef); if (impliedAccessGrants == null || impliedAccessGrants.isEmpty()) { return; 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 4ad2944a8..bf7ebe86a 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 @@ -42,6 +42,7 @@ import org.apache.ranger.plugin.model.RangerPolicy.RangerRowFilterPolicyItem; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef; import org.apache.ranger.plugin.model.RangerValiditySchedule; +import org.apache.ranger.plugin.policyengine.PolicyEngine; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.policyengine.RangerAccessRequestWrapper; import org.apache.ranger.plugin.policyengine.RangerAccessResource; @@ -80,6 +81,15 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator private boolean useAclSummaryForEvaluation = false; private boolean disableRoleResolution = true; + List<RangerPolicyItemEvaluator> getAllowEvaluators() { return allowEvaluators; } + List<RangerPolicyItemEvaluator> getAllowExceptionEvaluators() { return allowExceptionEvaluators; } + List<RangerPolicyItemEvaluator> getDenyEvaluators() { return denyEvaluators; } + List<RangerPolicyItemEvaluator> getDenyExceptionEvaluators() { return denyExceptionEvaluators; } + List<RangerDataMaskPolicyItemEvaluator> getDataMaskEvaluators() { return dataMaskEvaluators; } + List<RangerRowFilterPolicyItemEvaluator> getRowFilterEvaluators() { return rowFilterEvaluators; } + + boolean isUseAclSummaryForEvaluation() { return useAclSummaryForEvaluation; } + @Override public int getCustomConditionsCount() { return customConditionsCount; @@ -610,24 +620,26 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator if (isUsableForEvaluation || isCreationForced) { ret = new PolicyACLSummary(); + Map<String, Collection<String>> impliedAccessGrants = PolicyEngine.getImpliedAccessGrants(getServiceDef()); + for (RangerPolicyItem policyItem : policy.getDenyPolicyItems()) { - ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY, hasNonPublicGroupOrConditionsInDenyExceptions || hasPublicGroupInDenyAndUsersInDenyExceptions); + ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY, hasNonPublicGroupOrConditionsInDenyExceptions || hasPublicGroupInDenyAndUsersInDenyExceptions, impliedAccessGrants); } if (!hasNonPublicGroupOrConditionsInDenyExceptions && !hasPublicGroupInDenyAndUsersInDenyExceptions) { for (RangerPolicyItem policyItem : policy.getDenyExceptions()) { - ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS, false); + ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS, false, impliedAccessGrants); } } for (RangerPolicyItem policyItem : policy.getPolicyItems()) { - ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW, hasNonPublicGroupOrConditionsInAllowExceptions || hasPublicGroupInAllowAndUsersInAllowExceptions); + ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW, hasNonPublicGroupOrConditionsInAllowExceptions || hasPublicGroupInAllowAndUsersInAllowExceptions, impliedAccessGrants); } if (!hasNonPublicGroupOrConditionsInAllowExceptions && !hasPublicGroupInAllowAndUsersInAllowExceptions) { for (RangerPolicyItem policyItem : policy.getAllowExceptions()) { - ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS, false); + ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS, false, impliedAccessGrants); } } @@ -1153,6 +1165,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator if(policy == null || (!hasAllow() && !hasDeny()) || serviceDef == null) { return; } + /* Map<String, Collection<String>> impliedAccessGrants = getImpliedAccessGrants(serviceDef); @@ -1166,6 +1179,8 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator preprocessPolicyItems(policy.getDenyExceptions(), impliedAccessGrants); preprocessPolicyItems(policy.getDataMaskPolicyItems(), impliedAccessGrants); preprocessPolicyItems(policy.getRowFilterPolicyItems(), impliedAccessGrants); + + */ } protected void preprocessPolicyItems(List<? extends RangerPolicyItem> policyItems, Map<String, Collection<String>> impliedAccessGrants) { @@ -1203,33 +1218,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator } } - protected Map<String, Collection<String>> getImpliedAccessGrants(RangerServiceDef serviceDef) { - Map<String, Collection<String>> ret = null; - - if(serviceDef != null && !CollectionUtils.isEmpty(serviceDef.getAccessTypes())) { - for(RangerAccessTypeDef accessTypeDef : serviceDef.getAccessTypes()) { - if(!CollectionUtils.isEmpty(accessTypeDef.getImpliedGrants())) { - if(ret == null) { - ret = new HashMap<>(); - } - - Collection<String> impliedAccessGrants = ret.get(accessTypeDef.getName()); - - if(impliedAccessGrants == null) { - impliedAccessGrants = new HashSet<>(); - - ret.put(accessTypeDef.getName(), impliedAccessGrants); - } - - impliedAccessGrants.addAll(accessTypeDef.getImpliedGrants()); - } - } - } - - return ret; - } - - private RangerPolicyItemAccess getAccess(RangerPolicyItem policyItem, String accessType) { + static RangerPolicyItemAccess getAccess(RangerPolicyItem policyItem, String accessType) { RangerPolicyItemAccess ret = null; if(policyItem != null && CollectionUtils.isNotEmpty(policyItem.getAccesses())) { diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java index 3510ad144..2528aeafa 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java @@ -57,26 +57,26 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv } public void init() { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator(policyId=" + policyId + ", policyItem=" + policyItem + ", serviceType=" + getServiceType() + ", conditionsDisabled=" + getConditionsDisabledOption() + ")"); } RangerCustomConditionEvaluator rangerCustomConditionEvaluator = new RangerCustomConditionEvaluator(); - conditionEvaluators = rangerCustomConditionEvaluator.getPolicyItemConditionEvaluator(policy,policyItem,serviceDef,options,policyItemIndex); + conditionEvaluators = rangerCustomConditionEvaluator.getPolicyItemConditionEvaluator(policy, policyItem, serviceDef, options, policyItemIndex); List<String> users = policyItem.getUsers(); this.hasCurrentUser = CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.USER_CURRENT); this.hasResourceOwner = CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.RESOURCE_OWNER); - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator(policyId=" + policyId + ", conditionsCount=" + getConditionEvaluators().size() + ")"); } } @Override public boolean isMatch(RangerAccessRequest request) { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.isMatch(" + request + ")"); } @@ -84,29 +84,35 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv RangerPerfTracer perf = null; - if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYITEM_REQUEST_LOG)) { - perf = RangerPerfTracer.getPerfTracer(PERF_POLICYITEM_REQUEST_LOG, "RangerPolicyItemEvaluator.isMatch(resource=" + request.getResource().getAsString() + ")"); + if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYITEM_REQUEST_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYITEM_REQUEST_LOG, "RangerPolicyItemEvaluator.isMatch(resource=" + request.getResource().getAsString() + ")"); } - if(policyItem != null) { - if(matchUserGroupAndOwner(request)) { + if (policyItem != null) { + if (matchUserGroupAndOwner(request)) { if (request.isAccessTypeDelegatedAdmin()) { // used only in grant/revoke scenario if (policyItem.getDelegateAdmin()) { ret = true; } - } else if (CollectionUtils.isNotEmpty(policyItem.getAccesses())) { - boolean isAccessTypeMatched = false; + } else { + if (withImpliedGrants == null) { + withImpliedGrants = computeWithImpliedGrants(); + } - for (RangerPolicy.RangerPolicyItemAccess access : policyItem.getAccesses()) { - if (access.getIsAllowed() && StringUtils.equalsIgnoreCase(access.getType(), request.getAccessType())) { - isAccessTypeMatched = true; - break; + if (withImpliedGrants != null && CollectionUtils.isNotEmpty(withImpliedGrants.getAccesses())) { + boolean isAccessTypeMatched = false; + + for (RangerPolicy.RangerPolicyItemAccess access : withImpliedGrants.getAccesses()) { + if (access.getIsAllowed() && StringUtils.equalsIgnoreCase(access.getType(), request.getAccessType())) { + isAccessTypeMatched = true; + break; + } } - } - if(isAccessTypeMatched) { - if(matchCustomConditions(request)) { - ret = true; + if (isAccessTypeMatched) { + if (matchCustomConditions(request)) { + ret = true; + } } } } @@ -115,7 +121,7 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv RangerPerfTracer.log(perf); - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.isMatch(" + request + "): " + ret); } @@ -124,17 +130,17 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv @Override public boolean matchUserGroupAndOwner(String user, Set<String> userGroups, Set<String> roles, String owner) { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchUserGroup(" + policyItem + ", " + user + ", " + userGroups + ", " + roles + ", " + owner + ")"); } boolean ret = false; - if(policyItem != null) { - if(!ret && user != null && policyItem.getUsers() != null) { + if (policyItem != null) { + if (!ret && user != null && policyItem.getUsers() != null) { ret = hasCurrentUser || policyItem.getUsers().contains(user); } - if(!ret && userGroups != null && policyItem.getGroups() != null) { + if (!ret && userGroups != null && policyItem.getGroups() != null) { ret = policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC) || !Collections.disjoint(policyItem.getGroups(), userGroups); } @@ -146,7 +152,7 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv } } - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchUserGroup(" + policyItem + ", " + user + ", " + userGroups + ", " + roles + ", " + owner + "): " + ret); } @@ -154,7 +160,7 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv } private boolean matchUserGroupAndOwner(RangerAccessRequest request) { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchUserGroupAndOwner(" + request + ")"); } @@ -174,39 +180,44 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv ret = matchUserGroupAndOwner(user, userGroups, roles, resourceOwner); } - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchUserGroupAndOwner(" + request + "): " + ret); } return ret; } + @Override public boolean matchAccessType(String accessType) { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchAccessType(" + accessType + ")"); } boolean ret = false; - if(policyItem != null) { + if (policyItem != null) { boolean isAdminAccess = StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS); - if(isAdminAccess) { + if (isAdminAccess) { ret = policyItem.getDelegateAdmin(); } else { - if(CollectionUtils.isNotEmpty(policyItem.getAccesses())) { + if (withImpliedGrants == null) { + withImpliedGrants = computeWithImpliedGrants(); + } + + if (CollectionUtils.isNotEmpty(withImpliedGrants.getAccesses())) { boolean isAnyAccess = StringUtils.equals(accessType, RangerPolicyEngine.ANY_ACCESS); - for(RangerPolicyItemAccess itemAccess : policyItem.getAccesses()) { - if(! itemAccess.getIsAllowed()) { + for (RangerPolicyItemAccess itemAccess : withImpliedGrants.getAccesses()) { + if (!itemAccess.getIsAllowed()) { continue; } - if(isAnyAccess) { + if (isAnyAccess) { ret = true; break; - } else if(StringUtils.equalsIgnoreCase(itemAccess.getType(), accessType)) { + } else if (StringUtils.equalsIgnoreCase(itemAccess.getType(), accessType)) { ret = true; break; @@ -217,8 +228,8 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv } } } - - if(LOG.isDebugEnabled()) { + + if (LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchAccessType(" + accessType + "): " + ret); } @@ -227,27 +238,27 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv @Override public boolean matchCustomConditions(RangerAccessRequest request) { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchCustomConditions(" + request + ")"); } boolean ret = true; if (CollectionUtils.isNotEmpty(conditionEvaluators)) { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("RangerDefaultPolicyItemEvaluator.matchCustomConditions(): conditionCount=" + conditionEvaluators.size()); } - for(RangerConditionEvaluator conditionEvaluator : conditionEvaluators) { - if(LOG.isDebugEnabled()) { + for (RangerConditionEvaluator conditionEvaluator : conditionEvaluators) { + if (LOG.isDebugEnabled()) { LOG.debug("evaluating condition: " + conditionEvaluator); } RangerPerfTracer perf = null; - if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYCONDITION_REQUEST_LOG)) { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYCONDITION_REQUEST_LOG)) { String conditionType = null; if (conditionEvaluator instanceof RangerAbstractConditionEvaluator) { - conditionType = ((RangerAbstractConditionEvaluator)conditionEvaluator).getPolicyItemCondition().getType(); + conditionType = ((RangerAbstractConditionEvaluator) conditionEvaluator).getPolicyItemCondition().getType(); } perf = RangerPerfTracer.getPerfTracer(PERF_POLICYCONDITION_REQUEST_LOG, "RangerConditionEvaluator.matchCondition(policyId=" + policyId + ",policyItemIndex=" + getPolicyItemIndex() + ",policyConditionType=" + conditionType + ")"); @@ -258,7 +269,7 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv RangerPerfTracer.log(perf); if (!conditionEvalResult) { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug(conditionEvaluator + " returned false"); } @@ -269,7 +280,7 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv } } - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchCustomConditions(" + request + "): " + ret); } @@ -282,15 +293,15 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv } RangerPolicyConditionDef getConditionDef(String conditionName) { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.getConditionDef(" + conditionName + ")"); } RangerPolicyConditionDef ret = null; if (serviceDef != null && CollectionUtils.isNotEmpty(serviceDef.getPolicyConditions())) { - for(RangerPolicyConditionDef conditionDef : serviceDef.getPolicyConditions()) { - if(StringUtils.equals(conditionName, conditionDef.getName())) { + for (RangerPolicyConditionDef conditionDef : serviceDef.getPolicyConditions()) { + if (StringUtils.equals(conditionName, conditionDef.getName())) { ret = conditionDef; break; @@ -298,7 +309,7 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv } } - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.getConditionDef(" + conditionName + "): " + ret); } diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java index e50eb5f54..6d6169309 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java @@ -45,6 +45,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator private boolean hasPublicGroup; private boolean hasCurrentUser; private boolean hasResourceOwner; + private boolean hasAllEvaluatorsInitialized; // For computation of priority private static final String RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING = "*"; @@ -252,23 +253,29 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator protected boolean hasMatchablePolicyItem(RangerAccessRequest request) { boolean ret = false; - if (hasPublicGroup || hasCurrentUser || isOwnerMatch(request) || users.contains(request.getUser()) || CollectionUtils.containsAny(groups, request.getUserGroups()) || (CollectionUtils.isNotEmpty(roles) && CollectionUtils.containsAny(roles, RangerAccessRequestUtil.getCurrentUserRolesFromContext(request.getContext())))) { - if (hasAllPerms || request.isAccessTypeAny()) { - ret = true; - } else { - ret = accessPerms.contains(request.getAccessType()); - - if (!ret) { - Set<String> allRequestedAccesses = RangerAccessRequestUtil.getAllRequestedAccessTypes(request); - ret = CollectionUtils.containsAny(accessPerms, allRequestedAccesses); - } - - if (!ret) { - if (request.isAccessTypeDelegatedAdmin()) { - ret = delegateAdmin; - } - } - } + if (isUseAclSummaryForEvaluation()) { + ret = true; + } else if (checkIfAllEvaluatorsInitialized()) { + if (hasPublicGroup || hasCurrentUser || isOwnerMatch(request) || users.contains(request.getUser()) || CollectionUtils.containsAny(groups, request.getUserGroups()) || (CollectionUtils.isNotEmpty(roles) && CollectionUtils.containsAny(roles, RangerAccessRequestUtil.getCurrentUserRolesFromContext(request.getContext())))) { + if (hasAllPerms || request.isAccessTypeAny()) { + ret = true; + } else { + ret = accessPerms.contains(request.getAccessType()); + + if (!ret) { + Set<String> allRequestedAccesses = RangerAccessRequestUtil.getAllRequestedAccessTypes(request); + ret = CollectionUtils.containsAny(accessPerms, allRequestedAccesses); + } + + if (!ret) { + if (request.isAccessTypeDelegatedAdmin()) { + ret = delegateAdmin; + } + } + } + } + } else { + ret = true; } return ret; @@ -293,26 +300,32 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator private boolean hasMatchablePolicyItem(String user, Set<String> userGroups, Set<String> rolesFromContext, String owner, String accessType) { boolean ret = false; - boolean hasRole = false; - if (CollectionUtils.isNotEmpty(roles)) { - if (CollectionUtils.isNotEmpty(rolesFromContext)) { - hasRole = CollectionUtils.containsAny(roles, rolesFromContext); + if (isUseAclSummaryForEvaluation()) { + ret = true; + } else if (checkIfAllEvaluatorsInitialized()) { + boolean hasRole = false; + if (CollectionUtils.isNotEmpty(roles)) { + if (CollectionUtils.isNotEmpty(rolesFromContext)) { + hasRole = CollectionUtils.containsAny(roles, rolesFromContext); + } } - } - - if (hasPublicGroup || hasCurrentUser || users.contains(user) || CollectionUtils.containsAny(groups, userGroups) || hasRole || (hasResourceOwner && StringUtils.equals(user, owner))) { - if (hasAllPerms) { - ret = true; - } else { - boolean isAccessTypeAny = StringUtils.isEmpty(accessType) || StringUtils.equals(accessType, RangerPolicyEngine.ANY_ACCESS); - ret = isAccessTypeAny || accessPerms.contains(accessType); - if (!ret) { - if (StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS)) { - ret = delegateAdmin; + if (hasPublicGroup || hasCurrentUser || users.contains(user) || CollectionUtils.containsAny(groups, userGroups) || hasRole || (hasResourceOwner && StringUtils.equals(user, owner))) { + if (hasAllPerms) { + ret = true; + } else { + boolean isAccessTypeAny = StringUtils.isEmpty(accessType) || StringUtils.equals(accessType, RangerPolicyEngine.ANY_ACCESS); + ret = isAccessTypeAny || accessPerms.contains(accessType); + + if (!ret) { + if (StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS)) { + ret = delegateAdmin; + } } } } + } else { + ret = true; } return ret; @@ -365,4 +378,33 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator return result; } + private boolean checkIfAllEvaluatorsInitialized() { + if (!hasAllEvaluatorsInitialized) { + hasAllEvaluatorsInitialized = checkIfWithImpliedGrantsInitialized (getAllowEvaluators()) && + checkIfWithImpliedGrantsInitialized(getAllowExceptionEvaluators()) && + checkIfWithImpliedGrantsInitialized(getDenyEvaluators()) && + checkIfWithImpliedGrantsInitialized(getDenyExceptionEvaluators()) && + checkIfWithImpliedGrantsInitialized(getDataMaskEvaluators()) && + checkIfWithImpliedGrantsInitialized(getRowFilterEvaluators()); + } + return hasAllEvaluatorsInitialized; + } + + private boolean checkIfWithImpliedGrantsInitialized(List<? extends RangerPolicyItemEvaluator> evaluators) { + boolean ret = true; + for (RangerPolicyItemEvaluator evaluator: evaluators) { + if (evaluator.getWithImpliedGrants() == null) { + ret = false; + break; + } else { + for (RangerPolicy.RangerPolicyItemAccess access : evaluator.getWithImpliedGrants().getAccesses()) { + if (access.getIsAllowed()) { + accessPerms.add(access.getType()); + } + } + } + } + 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 f130e2491..dcaae9ff1 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 @@ -22,6 +22,7 @@ package org.apache.ranger.plugin.policyevaluator; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collection; import java.util.Comparator; import java.util.Date; import java.util.HashMap; @@ -308,7 +309,7 @@ public interface RangerPolicyEvaluator { public List<DataMaskResult> getDataMasks() { return dataMasks; } - void processPolicyItem(RangerPolicyItem policyItem, int policyItemType, boolean isConditional) { + void processPolicyItem(RangerPolicyItem policyItem, int policyItemType, boolean isConditional, Map<String, Collection<String>> impliedAccessGrants) { final Integer result; final boolean hasContextSensitiveSpecification = CollectionUtils.isNotEmpty(policyItem.getConditions()); @@ -335,15 +336,43 @@ public interface RangerPolicyEvaluator { } if (result != null) { - final List<RangerPolicyItemAccess> accesses; + List<RangerPolicyItemAccess> accesses = new ArrayList<>(); + accesses.addAll(policyItem.getAccesses()); if (policyItem.getDelegateAdmin()) { - accesses = new ArrayList<>(); - accesses.add(new RangerPolicyItemAccess(RangerPolicyEngine.ADMIN_ACCESS, policyItem.getDelegateAdmin())); - accesses.addAll(policyItem.getAccesses()); - } else { - accesses = policyItem.getAccesses(); + } + + if(impliedAccessGrants != null && !impliedAccessGrants.isEmpty()) { + if (CollectionUtils.isNotEmpty(policyItem.getAccesses())) { + + // Only one round of 'expansion' is done; multi-level impliedGrants (like shown below) are not handled for now + // multi-level impliedGrants: given admin=>write; write=>read: must imply admin=>read,write + for (Map.Entry<String, Collection<String>> e : impliedAccessGrants.entrySet()) { + String implyingAccessType = e.getKey(); + Collection<String> impliedGrants = e.getValue(); + + RangerPolicyItemAccess access = RangerDefaultPolicyEvaluator.getAccess(policyItem, implyingAccessType); + + if (access == null) { + continue; + } + + for (String impliedGrant : impliedGrants) { + RangerPolicyItemAccess impliedAccess = RangerDefaultPolicyEvaluator.getAccess(policyItem, impliedGrant); + + if (impliedAccess == null) { + impliedAccess = new RangerPolicyItemAccess(impliedGrant, access.getIsAllowed()); + + accesses.add(impliedAccess); + } else { + if (!impliedAccess.getIsAllowed()) { + impliedAccess.setIsAllowed(access.getIsAllowed()); + } + } + } + } + } } final List<String> groups = policyItem.getGroups(); diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java index 1a2ea4c9e..38d2129df 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java @@ -66,4 +66,5 @@ public interface RangerPolicyItemEvaluator { } } void updateAccessResult(RangerPolicyEvaluator policyEvaluator, RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType); + RangerPolicyItem getWithImpliedGrants(); }