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 fe27e0b RANGER-3397: Update ACL computation to (optionally) expand Ranger Roles to users and groups and include chained-plugins in ACL computation fe27e0b is described below commit fe27e0b32d388033d305b6e58b9686566ee40eb1 Author: Abhay Kulkarni <ab...@apache.org> AuthorDate: Fri Sep 3 16:50:29 2021 -0700 RANGER-3397: Update ACL computation to (optionally) expand Ranger Roles to users and groups and include chained-plugins in ACL computation --- .../plugin/policyengine/RangerPolicyEngine.java | 2 + .../policyengine/RangerPolicyEngineImpl.java | 23 ++-- .../policyengine/RangerPolicyEngineOptions.java | 11 +- .../RangerDefaultPolicyEvaluator.java | 131 ++++++++++++++++--- .../policyevaluator/RangerPolicyEvaluator.java | 8 +- .../ranger/plugin/service/RangerBasePlugin.java | 127 +++++++++++++++++- .../ranger/plugin/service/RangerChainedPlugin.java | 7 + .../apache/ranger/plugin/util/RangerRolesUtil.java | 64 ++++++---- .../ranger/plugin/policyengine/TestPolicyACLs.java | 14 +- .../policyengine/test_aclprovider_hdfs.json | 131 +++++++++++++++++++ .../aclprovider/test_aclprovider_default.json | 142 +++++++++++++++++++++ 11 files changed, 597 insertions(+), 63 deletions(-) diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java index 7a4bb12..7bf8c7c 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java @@ -70,6 +70,8 @@ public interface RangerPolicyEngine { RangerResourceACLs getResourceACLs(RangerAccessRequest request); + RangerResourceACLs getResourceACLs(RangerAccessRequest request, Integer requestedPolicyType); + Set<String> getRolesFromUserAndGroups(String user, Set<String> groups); RangerRoles getRangerRoles(); diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java index 9e0a89e..c92b550 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java @@ -243,8 +243,13 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { @Override public RangerResourceACLs getResourceACLs(RangerAccessRequest request) { + return getResourceACLs(request, null); + } + + @Override + public RangerResourceACLs getResourceACLs(RangerAccessRequest request, Integer requestedPolicyType) { if (LOG.isDebugEnabled()) { - LOG.debug("==> RangerPolicyEngineImpl.getResourceACLs(request=" + request + ")"); + LOG.debug("==> RangerPolicyEngineImpl.getResourceACLs(request=" + request + ", policyType=" + requestedPolicyType + ")"); } RangerResourceACLs ret = new RangerResourceACLs(); @@ -269,7 +274,10 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { LOG.debug("zoneName:[" + zoneName + "]"); } - for (int policyType : RangerPolicy.POLICY_TYPES) { + int[] policyTypes = requestedPolicyType == null ? RangerPolicy.POLICY_TYPES : new int[] { requestedPolicyType }; + + + for (int policyType : policyTypes) { List<RangerPolicyEvaluator> allEvaluators = new ArrayList<>(); Map<Long, MatchType> tagMatchTypeMap = new HashMap<>(); Set<Long> policyIdForTemporalTags = new HashSet<>(); @@ -331,7 +339,7 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { RangerPerfTracer.logAlways(perf); if (LOG.isDebugEnabled()) { - LOG.debug("<== RangerPolicyEngineImpl.getResourceACLs(request=" + request + ") : ret=" + ret); + LOG.debug("<== RangerPolicyEngineImpl.getResourceACLs(request=" + request + ", policyType=" + requestedPolicyType + ") : ret=" + ret); } return ret; @@ -773,7 +781,6 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { if (ret.getIsAuditedDetermined() && ret.getIsAccessDetermined()) { break; // Break out of policy-evaluation loop } - } if (!ret.getIsAccessDetermined()) { @@ -1136,6 +1143,10 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { return ret; } + private boolean getIsFallbackSupported() { + return policyEngine.getPluginContext().getConfig().getIsFallbackSupported(); + } + private void updateFromPolicyACLs(RangerPolicyEvaluator evaluator, Set<Long> policyIdForTemporalTags, RangerResourceACLs resourceACLs) { PolicyACLSummary aclSummary = evaluator.getPolicyACLSummary(); @@ -1248,10 +1259,6 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { } } - private boolean getIsFallbackSupported() { - return policyEngine.getPluginContext().getConfig().getIsFallbackSupported(); - } - private static class ServiceConfig { private final Set<String> auditExcludedUsers; private final Set<String> auditExcludedGroups; diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineOptions.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineOptions.java index 0816ec1..07d0a39 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineOptions.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineOptions.java @@ -36,6 +36,7 @@ public class RangerPolicyEngineOptions { public boolean enableTagEnricherWithLocalRefresher = false; public boolean disableAccessEvaluationWithPolicyACLSummary = true; public boolean optimizeTrieForRetrieval = false; + public boolean disableRoleResolution = true; private RangerServiceDefHelper serviceDefHelper; @@ -53,6 +54,7 @@ public class RangerPolicyEngineOptions { this.enableTagEnricherWithLocalRefresher = other.enableTagEnricherWithLocalRefresher; this.disableAccessEvaluationWithPolicyACLSummary = other.disableAccessEvaluationWithPolicyACLSummary; this.optimizeTrieForRetrieval = other.optimizeTrieForRetrieval; + this.disableRoleResolution = other.disableRoleResolution; this.serviceDefHelper = null; } @@ -73,6 +75,7 @@ public class RangerPolicyEngineOptions { enableTagEnricherWithLocalRefresher = false; disableAccessEvaluationWithPolicyACLSummary = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.access.evaluation.with.policy.acl.summary", true); optimizeTrieForRetrieval = conf.getBoolean(propertyPrefix + ".policyengine.option.optimize.trie.for.retrieval", false); + disableRoleResolution = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.role.resolution", true); } @@ -89,6 +92,7 @@ public class RangerPolicyEngineOptions { enableTagEnricherWithLocalRefresher = false; disableAccessEvaluationWithPolicyACLSummary = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.access.evaluation.with.policy.acl.summary", true); optimizeTrieForRetrieval = conf.getBoolean(propertyPrefix + ".policyengine.option.optimize.trie.for.retrieval", false); + disableRoleResolution = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.role.resolution", true); } @@ -150,7 +154,8 @@ public class RangerPolicyEngineOptions { && this.cacheAuditResults == that.cacheAuditResults && this.evaluateDelegateAdminOnly == that.evaluateDelegateAdminOnly && this.enableTagEnricherWithLocalRefresher == that.enableTagEnricherWithLocalRefresher - && this.optimizeTrieForRetrieval == that.optimizeTrieForRetrieval; + && this.optimizeTrieForRetrieval == that.optimizeTrieForRetrieval + && this.disableRoleResolution == that.disableRoleResolution; } return ret; } @@ -178,7 +183,8 @@ public class RangerPolicyEngineOptions { ret *= 2; ret += optimizeTrieForRetrieval ? 1 : 0; ret *= 2; - return ret; + ret += disableRoleResolution ? 1 : 0; + ret *= 2; return ret; } @Override @@ -195,6 +201,7 @@ public class RangerPolicyEngineOptions { ", disableTrieLookupPrefilter: " + disableTrieLookupPrefilter + ", optimizeTrieForRetrieval: " + optimizeTrieForRetrieval + ", cacheAuditResult: " + cacheAuditResults + + ", disableRoleResolution: " + disableRoleResolution + " }"; } 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 02a096f..9f0abf2 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 @@ -81,6 +81,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator private String perfTag; private PolicyACLSummary aclSummary = null; private boolean useAclSummaryForEvaluation = false; + private boolean disableRoleResolution = true; protected boolean needsDynamicEval() { return resourceMatcher != null && resourceMatcher.getNeedsDynamicEval(); } @@ -160,7 +161,6 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator allowExceptionEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); denyExceptionEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); } - } dataMaskEvaluators = createDataMaskPolicyItemEvaluators(policy, serviceDef, options, policy.getDataMaskPolicyItems()); @@ -544,51 +544,58 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_INIT_ACLSUMMARY_LOG, "RangerPolicyEvaluator.init.ACLSummary(" + perfTag + ")"); } - final boolean hasNonPublicGroupOrConditionsInAllowExceptions = hasNonPublicGroupOrConditions(getPolicy().getAllowExceptions()); - final boolean hasNonPublicGroupOrConditionsInDenyExceptions = hasNonPublicGroupOrConditions(getPolicy().getDenyExceptions()); - final boolean hasPublicGroupInAllowAndUsersInAllowExceptions = hasPublicGroupAndUserInException(getPolicy().getPolicyItems(), getPolicy().getAllowExceptions()); - final boolean hasPublicGroupInDenyAndUsersInDenyExceptions = hasPublicGroupAndUserInException(getPolicy().getDenyPolicyItems(), getPolicy().getDenyExceptions()); + RangerPolicy policy; + if (!disableRoleResolution && hasRoles(getPolicy())) { + policy = getPolicyWithRolesResolved(getPolicy()); + } else { + policy = getPolicy(); + } + + final boolean hasNonPublicGroupOrConditionsInAllowExceptions = hasNonPublicGroupOrConditions(policy.getAllowExceptions()); + final boolean hasNonPublicGroupOrConditionsInDenyExceptions = hasNonPublicGroupOrConditions(policy.getDenyExceptions()); + final boolean hasPublicGroupInAllowAndUsersInAllowExceptions = hasPublicGroupAndUserInException(policy.getPolicyItems(), policy.getAllowExceptions()); + final boolean hasPublicGroupInDenyAndUsersInDenyExceptions = hasPublicGroupAndUserInException(policy.getDenyPolicyItems(), policy.getDenyExceptions()); final boolean hasContextSensitiveSpecification = hasContextSensitiveSpecification(); - final boolean hasRoles = hasRoles(); + final boolean hasRoles = hasRoles(policy); final boolean isUsableForEvaluation = !hasNonPublicGroupOrConditionsInAllowExceptions && !hasNonPublicGroupOrConditionsInDenyExceptions && !hasPublicGroupInAllowAndUsersInAllowExceptions && !hasPublicGroupInDenyAndUsersInDenyExceptions - && !hasContextSensitiveSpecification - && !hasRoles; + && !hasContextSensitiveSpecification + && !hasRoles; if (isUsableForEvaluation || isCreationForced) { ret = new PolicyACLSummary(); - for (RangerPolicyItem policyItem : getPolicy().getDenyPolicyItems()) { + for (RangerPolicyItem policyItem : policy.getDenyPolicyItems()) { ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY, hasNonPublicGroupOrConditionsInDenyExceptions || hasPublicGroupInDenyAndUsersInDenyExceptions); } if (!hasNonPublicGroupOrConditionsInDenyExceptions && !hasPublicGroupInDenyAndUsersInDenyExceptions) { - for (RangerPolicyItem policyItem : getPolicy().getDenyExceptions()) { + for (RangerPolicyItem policyItem : policy.getDenyExceptions()) { ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS, false); } } - for (RangerPolicyItem policyItem : getPolicy().getPolicyItems()) { + for (RangerPolicyItem policyItem : policy.getPolicyItems()) { ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW, hasNonPublicGroupOrConditionsInAllowExceptions || hasPublicGroupInAllowAndUsersInAllowExceptions); } if (!hasNonPublicGroupOrConditionsInAllowExceptions && !hasPublicGroupInAllowAndUsersInAllowExceptions) { - for (RangerPolicyItem policyItem : getPolicy().getAllowExceptions()) { + for (RangerPolicyItem policyItem : policy.getAllowExceptions()) { ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS, false); } } - for (RangerRowFilterPolicyItem policyItem : getPolicy().getRowFilterPolicyItems()) { + for (RangerRowFilterPolicyItem policyItem : policy.getRowFilterPolicyItems()) { ret.processRowFilterPolicyItem(policyItem); } - for (RangerDataMaskPolicyItem policyItem : getPolicy().getDataMaskPolicyItems()) { + for (RangerDataMaskPolicyItem policyItem : policy.getDataMaskPolicyItems()) { ret.processDataMaskPolicyItem(policyItem); } - final boolean isDenyAllElse = Boolean.TRUE.equals(getPolicy().getIsDenyAllElse()); + final boolean isDenyAllElse = Boolean.TRUE.equals(policy.getIsDenyAllElse()); final Set<String> allAccessTypeNames; @@ -612,6 +619,100 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator return ret; } + private RangerPolicy getPolicyWithRolesResolved(final RangerPolicy policy) { + // Create new policy with no roles in it + // For each policyItem, expand roles into users and groups; and replace all policyItems with expanded roles - TBD + + RangerPolicy ret = new RangerPolicy(); + ret.updateFrom(policy); + ret.setId(policy.getId()); + ret.setGuid(policy.getGuid()); + ret.setVersion(policy.getVersion()); + + List<RangerPolicyItem> policyItems = new ArrayList<>(); + List<RangerPolicyItem> denyPolicyItems = new ArrayList<>(); + List<RangerPolicyItem> allowExceptions = new ArrayList<>(); + List<RangerPolicyItem> denyExceptions = new ArrayList<>(); + List<RangerDataMaskPolicyItem> dataMaskPolicyItems = new ArrayList<>(); + List<RangerRowFilterPolicyItem> rowFilterPolicyItems = new ArrayList<>(); + + for (RangerPolicyItem policyItem : policy.getPolicyItems()) { + RangerPolicyItem newPolicyItem = new RangerPolicyItem(policyItem.getAccesses(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + policyItems.add(newPolicyItem); + } + ret.setPolicyItems(policyItems); + + for (RangerPolicyItem policyItem : policy.getDenyPolicyItems()) { + RangerPolicyItem newPolicyItem = new RangerPolicyItem(policyItem.getAccesses(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + denyPolicyItems.add(newPolicyItem); + } + ret.setDenyPolicyItems(denyPolicyItems); + + for (RangerPolicyItem policyItem : policy.getAllowExceptions()) { + RangerPolicyItem newPolicyItem = new RangerPolicyItem(policyItem.getAccesses(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + allowExceptions.add(newPolicyItem); + } + ret.setAllowExceptions(allowExceptions); + + for (RangerPolicyItem policyItem : policy.getDenyExceptions()) { + RangerPolicyItem newPolicyItem = new RangerPolicyItem(policyItem.getAccesses(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + denyExceptions.add(newPolicyItem); + } + ret.setDenyExceptions(denyExceptions); + + for (RangerDataMaskPolicyItem policyItem : policy.getDataMaskPolicyItems()) { + RangerDataMaskPolicyItem newPolicyItem = new RangerDataMaskPolicyItem(policyItem.getAccesses(), policyItem.getDataMaskInfo(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + dataMaskPolicyItems.add(newPolicyItem); + } + ret.setDataMaskPolicyItems(dataMaskPolicyItems); + + for (RangerRowFilterPolicyItem policyItem : policy.getRowFilterPolicyItems()) { + RangerRowFilterPolicyItem newPolicyItem = new RangerRowFilterPolicyItem(policyItem.getRowFilterInfo(), policyItem.getAccesses(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + rowFilterPolicyItems.add(newPolicyItem); + } + ret.setRowFilterPolicyItems(rowFilterPolicyItems); + + return ret; + } + + private void getPolicyItemWithRolesResolved(RangerPolicyItem newPolicyItem, final RangerPolicyItem policyItem) { + Set<String> usersFromRoles = new HashSet<>(); + Set<String> groupsFromRoles = new HashSet<>(); + + List<String> roles = policyItem.getRoles(); + + for (String role : roles) { + Set<String> users = getPluginContext().getAuthContext().getRangerRolesUtil().getRoleToUserMapping().get(role); + Set<String> groups = getPluginContext().getAuthContext().getRangerRolesUtil().getRoleToGroupMapping().get(role); + if (CollectionUtils.isNotEmpty(users)) { + usersFromRoles.addAll(users); + } + if (CollectionUtils.isNotEmpty(groups)) { + groupsFromRoles.addAll(groups); + } + if (CollectionUtils.isNotEmpty(usersFromRoles) || CollectionUtils.isNotEmpty(groupsFromRoles)) { + usersFromRoles.addAll(policyItem.getUsers()); + groupsFromRoles.addAll(policyItem.getGroups()); + + newPolicyItem.setUsers(new ArrayList<>(usersFromRoles)); + newPolicyItem.setGroups(new ArrayList<>(groupsFromRoles)); + newPolicyItem.setRoles(null); + } + } + } + private boolean hasPublicGroupAndUserInException(List<RangerPolicyItem> grants, List<RangerPolicyItem> exceptionItems) { boolean ret = false; 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 0157c00..15a6465 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 @@ -55,8 +55,10 @@ import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatche import static org.apache.ranger.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW; import static org.apache.ranger.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS; +import static org.apache.ranger.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DATAMASK; import static org.apache.ranger.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY; import static org.apache.ranger.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS; +import static org.apache.ranger.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ROWFILTER; public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator { Comparator<RangerPolicyEvaluator> EVAL_ORDER_COMPARATOR = new RangerPolicyEvaluator.PolicyEvalOrderComparator(); @@ -140,9 +142,7 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator { return false; } - default boolean hasRoles() { - RangerPolicy policy = getPolicy(); - + default boolean hasRoles(final RangerPolicy policy) { for (RangerPolicyItem policyItem : policy.getPolicyItems()) { if (hasRoles(policyItem)) { return true; @@ -297,7 +297,7 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator { void processPolicyItem(RangerPolicyItem policyItem, int policyItemType, boolean isConditional) { final Integer result; - final boolean hasContextSensitiveSpecification = RangerPolicyEvaluator.hasContextSensitiveSpecification(policyItem); + final boolean hasContextSensitiveSpecification = CollectionUtils.isNotEmpty(policyItem.getConditions()); switch (policyItemType) { case POLICY_ITEM_TYPE_ALLOW: diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java index 7e0894d..3ad74e5 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java @@ -49,6 +49,7 @@ import org.apache.ranger.plugin.policyengine.RangerPolicyEngine; import org.apache.ranger.plugin.policyengine.RangerPolicyEngineImpl; import org.apache.ranger.plugin.policyengine.RangerResourceACLs; import org.apache.ranger.plugin.policyengine.RangerResourceAccessInfo; +import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator; import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; import org.apache.ranger.plugin.util.*; @@ -539,13 +540,43 @@ public class RangerBasePlugin { } public RangerResourceACLs getResourceACLs(RangerAccessRequest request) { + return getResourceACLs(request, null); + } + + public RangerResourceACLs getResourceACLs(RangerAccessRequest request, Integer policyType) { + RangerResourceACLs ret = null; RangerPolicyEngine policyEngine = this.policyEngine; if(policyEngine != null) { - return policyEngine.getResourceACLs(request); + ret = policyEngine.getResourceACLs(request, policyType); } - return null; + for (RangerChainedPlugin chainedPlugin : chainedPlugins) { + RangerResourceACLs chainedResourceACLs = chainedPlugin.getResourceACLs(request, policyType); + + if (chainedResourceACLs != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Chained-plugin returned non-null ACLs!!"); + } + if (chainedPlugin.isAuthorizeOnlyWithChainedPlugin()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Chained-plugin is configured to ignore Base-plugin's ACLs"); + } + ret = chainedResourceACLs; + break; + } else { + if (ret != null) { + ret = getMergedResourceACLs(ret, chainedResourceACLs); + } + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Chained-plugin returned null ACLs!!"); + } + } + } + + return ret; } public Set<String> getRolesFromUserAndGroups(String user, Set<String> groups) { @@ -1035,6 +1066,98 @@ public class RangerBasePlugin { } } + private RangerResourceACLs getMergedResourceACLs(RangerResourceACLs baseACLs, RangerResourceACLs chainedACLs) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerBasePlugin.getMergedResourceACLs()"); + LOG.debug("baseACLs:[" + baseACLs + "]"); + LOG.debug("chainedACLS:[" + chainedACLs + "]"); + } + + overrideACLs(chainedACLs, baseACLs, RangerRolesUtil.ROLES_FOR.USER); + overrideACLs(chainedACLs, baseACLs, RangerRolesUtil.ROLES_FOR.GROUP); + overrideACLs(chainedACLs, baseACLs, RangerRolesUtil.ROLES_FOR.ROLE); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerBasePlugin.getMergedResourceACLs() : ret:[" + baseACLs + "]"); + } + return baseACLs; + } + + private void overrideACLs(final RangerResourceACLs chainedResourceACLs, RangerResourceACLs baseResourceACLs, final RangerRolesUtil.ROLES_FOR userType) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerBasePlugin.overrideACLs(isUser=" + userType.name() + ")"); + } + Map<String, Map<String, RangerResourceACLs.AccessResult>> chainedACLs = null; + Map<String, Map<String, RangerResourceACLs.AccessResult>> baseACLs = null; + + switch (userType) { + case USER: + chainedACLs = chainedResourceACLs.getUserACLs(); + baseACLs = baseResourceACLs.getUserACLs(); + break; + case GROUP: + chainedACLs = chainedResourceACLs.getGroupACLs(); + baseACLs = baseResourceACLs.getGroupACLs(); + break; + case ROLE: + chainedACLs = chainedResourceACLs.getRoleACLs(); + baseACLs = baseResourceACLs.getRoleACLs(); + break; + default: + break; + } + + for (Map.Entry<String, Map<String, RangerResourceACLs.AccessResult>> chainedPermissionsMap : chainedACLs.entrySet()) { + String name = chainedPermissionsMap.getKey(); + Map<String, RangerResourceACLs.AccessResult> chainedPermissions = chainedPermissionsMap.getValue(); + Map<String, RangerResourceACLs.AccessResult> basePermissions = baseACLs.get(name); + + for (Map.Entry<String, RangerResourceACLs.AccessResult> chainedPermission : chainedPermissions.entrySet()) { + String chainedAccessType = chainedPermission.getKey(); + RangerResourceACLs.AccessResult chainedAccessResult = chainedPermission.getValue(); + RangerResourceACLs.AccessResult baseAccessResult = basePermissions == null ? null : basePermissions.get(chainedAccessType); + + final boolean useChainedAccessResult; + + if (baseAccessResult == null) { + useChainedAccessResult = true; + } else { + if (chainedAccessResult.getPolicy().getPolicyPriority() > baseAccessResult.getPolicy().getPolicyPriority()) { + useChainedAccessResult = true; + } else if (chainedAccessResult.getPolicy().getPolicyPriority().equals(baseAccessResult.getPolicy().getPolicyPriority())) { + if (chainedAccessResult.getResult() == baseAccessResult.getResult()) { + useChainedAccessResult = true; + } else { + useChainedAccessResult = chainedAccessResult.getResult() == RangerPolicyEvaluator.ACCESS_DENIED; + } + } else { // chainedAccessResult.getPolicy().getPolicyPriority() < baseAccessResult.getPolicy().getPolicyPriority() + useChainedAccessResult = false; + } + } + + final RangerResourceACLs.AccessResult finalAccessResult = useChainedAccessResult ? chainedAccessResult : baseAccessResult; + + switch (userType) { + case USER: + baseResourceACLs.setUserAccessInfo(name, chainedAccessType, finalAccessResult.getResult(), finalAccessResult.getPolicy()); + break; + case GROUP: + baseResourceACLs.setGroupAccessInfo(name, chainedAccessType, finalAccessResult.getResult(), finalAccessResult.getPolicy()); + break; + case ROLE: + baseResourceACLs.setRoleAccessInfo(name, chainedAccessType, finalAccessResult.getResult(), finalAccessResult.getPolicy()); + break; + default: + break; + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerBasePlugin.mergeACLsOneWay(isUser=" + userType.name() + ")"); + } + } + private static AuditProviderFactory getAuditProviderFactory(String serviceName) { AuditProviderFactory ret = AuditProviderFactory.getInstance(); diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerChainedPlugin.java b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerChainedPlugin.java index 0fca2d9..7a48a09 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerChainedPlugin.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerChainedPlugin.java @@ -23,6 +23,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.policyengine.RangerAccessResult; +import org.apache.ranger.plugin.policyengine.RangerResourceACLs; import java.util.Collection; @@ -59,4 +60,10 @@ public abstract class RangerChainedPlugin { public abstract Collection<RangerAccessResult> isAccessAllowed(Collection<RangerAccessRequest> requests); + public abstract RangerResourceACLs getResourceACLs(RangerAccessRequest request); + + public abstract RangerResourceACLs getResourceACLs(RangerAccessRequest request, Integer policyType); + + public boolean isAuthorizeOnlyWithChainedPlugin() { return false; } + } diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRolesUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRolesUtil.java index a6e461c..f785e11 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRolesUtil.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRolesUtil.java @@ -34,8 +34,12 @@ public class RangerRolesUtil { private final Map<String, Set<String>> userRoleMapping = new HashMap<>(); private final Map<String, Set<String>> groupRoleMapping = new HashMap<>(); private final Map<String, Set<String>> roleRoleMapping = new HashMap<>(); + + private final Map<String, Set<String>> roleToUserMapping = new HashMap<>(); + private final Map<String, Set<String>> roleToGroupMapping = new HashMap<>(); + private RangerRoles roles = null; - private enum ROLES_FOR {USER, GROUP, ROLE}; + public enum ROLES_FOR {USER, GROUP, ROLE} public RangerRolesUtil(RangerRoles roles) { if (roles != null) { @@ -49,7 +53,22 @@ public class RangerRolesUtil { buildMap(userRoleMapping, role, containedRoles, ROLES_FOR.USER); buildMap(groupRoleMapping, role, containedRoles, ROLES_FOR.GROUP); buildMap(roleRoleMapping, role, containedRoles, ROLES_FOR.ROLE); + + Set<String> roleUsers = new HashSet<>(); + Set<String> roleGroups = new HashSet<>(); + + addMemberNames(role.getUsers(), roleUsers); + addMemberNames(role.getGroups(), roleGroups); + + for (RangerRole containedRole : containedRoles) { + addMemberNames(containedRole.getUsers(), roleUsers); + addMemberNames(containedRole.getGroups(), roleGroups); + } + + roleToUserMapping.put(role.getName(), roleUsers); + roleToGroupMapping.put(role.getName(), roleGroups); } + } } else { roleVersion = -1L; @@ -74,6 +93,14 @@ public class RangerRolesUtil { return this.roleRoleMapping; } + public Map<String, Set<String>> getRoleToUserMapping() { + return this.roleToUserMapping; + } + + public Map<String, Set<String>> getRoleToGroupMapping() { + return this.roleToGroupMapping; + } + private Set<RangerRole> getAllContainedRoles(Set<RangerRole> roles, RangerRole role) { Set<RangerRole> allRoles = new HashSet<>(); @@ -104,22 +131,6 @@ public class RangerRolesUtil { } } - private void buildMap(Map<String, Set<String>> map, RangerRole role, String roleName, boolean isUser) { - for (RangerRole.RoleMember userOrGroup : isUser ? role.getUsers() : role.getGroups()) { - if (StringUtils.isNotEmpty(userOrGroup.getName())) { - Set<String> roleNames = map.get(userOrGroup.getName()); - - if (roleNames == null) { - roleNames = new HashSet<>(); - - map.put(userOrGroup.getName(), roleNames); - } - - roleNames.add(roleName); - } - } - } - private void buildMap(Map<String, Set<String>> map, RangerRole role, String roleName, ROLES_FOR roles_for) { List<RangerRole.RoleMember> userOrGroupOrRole = null; switch(roles_for) { @@ -141,23 +152,20 @@ public class RangerRolesUtil { private void getRoleMap(Map<String, Set<String>> map, String roleName, List<RangerRole.RoleMember> userOrGroupOrRole) { for (RangerRole.RoleMember roleMember : userOrGroupOrRole) { if (StringUtils.isNotEmpty(roleMember.getName())) { - Set<String> roleNames = map.get(roleMember.getName()); - if (roleNames == null) { - roleNames = new HashSet<>(); - - map.put(roleMember.getName(), roleNames); - } + Set<String> roleNames = map.computeIfAbsent(roleMember.getName(), k -> new HashSet<>()); roleNames.add(roleName); } } } private RangerRole getContainedRole(Set<RangerRole> roles, String role) { - return (roles - .stream() - .filter(containedRole -> role.equals(containedRole.getName())) - .findAny() - .orElse(null)); + return (roles.stream().filter(containedRole -> role.equals(containedRole.getName())).findAny().orElse(null)); + } + + private void addMemberNames(List<RangerRole.RoleMember> members, Set<String> names) { + for (RangerRole.RoleMember member : members) { + names.add(member.getName()); + } } } diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyACLs.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyACLs.java index d2983a2..b6135b0 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyACLs.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyACLs.java @@ -86,6 +86,13 @@ public class TestPolicyACLs { runTestsFromResourceFiles(tests); } + @Test + public void testResourceACLs_hdfs() throws Exception { + String[] tests = {"/policyengine/test_aclprovider_hdfs.json"}; + + runTestsFromResourceFiles(tests); + } + private void runTestsFromResourceFiles(String[] resourceNames) throws Exception { for(String resourceName : resourceNames) { InputStream inStream = this.getClass().getResourceAsStream(resourceName); @@ -101,8 +108,9 @@ public class TestPolicyACLs { assertTrue("invalid input: " + testName, testCases != null && testCases.testCases != null); for(PolicyACLsTests.TestCase testCase : testCases.testCases) { + String serviceType = testCase.servicePolicies.getServiceDef().getName(); RangerPolicyEngineOptions policyEngineOptions = new RangerPolicyEngineOptions(); - RangerPluginContext pluginContext = new RangerPluginContext(new RangerPluginConfig("hive", null, "test-policy-acls", "cl1", "on-prem", policyEngineOptions)); + RangerPluginContext pluginContext = new RangerPluginContext(new RangerPluginConfig(serviceType, null, "test-policy-acls", "cl1", "on-prem", policyEngineOptions)); RangerPolicyEngine policyEngine = new RangerPolicyEngineImpl(testCase.servicePolicies, pluginContext, null); for(PolicyACLsTests.TestCase.OneTest oneTest : testCase.tests) { @@ -259,9 +267,7 @@ public class TestPolicyACLs { } else if (!(MapUtils.isEmpty(acls.getRoleACLs()) && MapUtils.isEmpty(oneTest.rolePermissions))) { roleACLsMatched = false; } - - assertTrue("getResourceACLs() failed! " + testCase.name + ":" + oneTest.name + " - userACLsMatched=" + userACLsMatched + "; groupACLsMatched=" + groupACLsMatched + "; roleACLsMatched=" + roleACLsMatched + "; rowFiltersMatched=" + rowFiltersMatched + "; dataMaskingMatched=" + dataMaskingMatched, - userACLsMatched && groupACLsMatched && roleACLsMatched && rowFiltersMatched && dataMaskingMatched); + assertTrue("getResourceACLs() failed! " + testCase.name + ":" + oneTest.name, userACLsMatched && groupACLsMatched && roleACLsMatched && rowFiltersMatched && dataMaskingMatched); } } } diff --git a/agents-common/src/test/resources/policyengine/test_aclprovider_hdfs.json b/agents-common/src/test/resources/policyengine/test_aclprovider_hdfs.json new file mode 100644 index 0000000..9526763 --- /dev/null +++ b/agents-common/src/test/resources/policyengine/test_aclprovider_hdfs.json @@ -0,0 +1,131 @@ +{ + "testCases": [ + { + "name": "Test-ACL-Provider-for-HDFS", + + "servicePolicies": { + "serviceName": "hivedev", + "serviceDef": { + "name": "hdfs", + "id": 1, + "resources": [ + { + "name": "path", + "type": "path", + "level": 1, + "mandatory": true, + "lookupSupported": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher", + "matcherOptions": { + "wildCard": true, + "ignoreCase": true + }, + "label": "Resource Path", + "description": "HDFS file or directory path" + } + ], + "accessTypes": [ + { + "name": "read", + "label": "Read" + }, + { + "name": "write", + "label": "Write" + }, + { + "name": "execute", + "label": "Execute" + } + ], + "contextEnrichers": [ + { + "itemId": 1, + "name": "GeolocationEnricher", + "enricher": "org.apache.ranger.plugin.contextenricher.RangerFileBasedGeolocationProvider", + "enricherOptions": { + "FilePath": "/etc/ranger/geo/geo.txt", + "ForceRead": "false", + "IPInDotFormat": "true", + "geolocation.meta.prefix": "TEST_" + } + } + ], + "policyConditions": [ + { + "itemId": 1, + "name": "ScriptConditionEvaluator", + "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator", + "evaluatorOptions": { + "engineName": "JavaScript" + }, + "label": "Script", + "description": "Script to execute" + } + ] + }, + "policies": [ + { + "id": 1, "name": "audit-all-access under /finance/restricted/", + "resources": { + "path": {"values": ["/finance/restricted/"], "isRecursive": true} + }, + "policyItems": [ + {"accesses": [], "users": [], "groups": [ "public"]} + ] + }, + { + "id": 2, "name": "allow-read-to-all under /public/", + "resources": { + "path": {"values": [ "/public/*" ], "isRecursive": true} + }, + "policyItems": [ + {"accesses": [{"type": "read", "isAllowed": true},{"type": "execute", "isAllowed": true}], "users": [], "groups": ["public"]} + ] + }, + { + "id": 3, "name": "allow-read-to-finance under /finance/restricted", + "resources": { + "path": {"values": [ "/finance/restricted" ], "isRecursive": true} + }, + "policyItems": [ + {"accesses": [{"type": "read", "isAllowed": true}], "users": [], "groups": ["finance"]} + ] + }, + { + "id": 4, "name": "allow-read-to-finance under /finance/limited", + "resources": { + "path": {"values": [ "/finance/limited"], "isRecursive": true} + }, + "policyItems": [ + {"accesses": [{"type": "read", "isAllowed": true}], "users": [], "groups": ["stewards"]} + ] + } + ] + }, + "tests": [ + { + "name": "test-finance-restricted", + "resource": {"elements":{"path":"/finance/restricted"}}, + "userPermissions": {}, + "groupPermissions": {"finance": {"read": {"result": 1, "isFinal": true}}}, + "rolePermissions": {} + }, + { + "name": "test-finance-limited", + "resource": {"elements":{"path":"/finance/limited"}}, + "userPermissions": {}, + "groupPermissions": {"stewards": {"read": {"result": 1, "isFinal": true}}}, + "rolePermissions": {} + }, + { + "name": "test-anything-under-public", + "resource": {"elements":{"path":"/public/anything"}}, + "userPermissions": {}, + "groupPermissions": {"public": {"read": {"result": 1, "isFinal": true}, "execute": {"result": 1, "isFinal": true}}}, + "rolePermissions": {} + } + ] + } + ] +} diff --git a/hdfs-agent/src/test/resources/aclprovider/test_aclprovider_default.json b/hdfs-agent/src/test/resources/aclprovider/test_aclprovider_default.json new file mode 100644 index 0000000..c345ec6 --- /dev/null +++ b/hdfs-agent/src/test/resources/aclprovider/test_aclprovider_default.json @@ -0,0 +1,142 @@ +{ + "testCases": [ + { + "name": "Test-ACL-Provider", + "roles" : { "serviceName": "hdfsdev", "roleVersion": 1, + "rangerRoles": [ { "name": "admin", "users": [{"name":"admin-1","isAdmin": false}, {"name":"admin-2", "isAdmin": false}], "groups" : [{"name":"admin-group-1", "isAdmin":false}, {"name":"admin-group-2", "isAdmin": false}], "roles": [{"name": "sub-admin-1","isAdmin":false}, {"name":"sub-admin-2", "isAdmin": false}] }, + { "name": "sub-admin-1", "users": [{"name":"sub-admin-user-1", "isAdmin": false}], "groups" : [], "roles": [] }, + { "name": "sub-admin-2", "users": [], "groups" : [{"name":"sub-admin-group-2", "isAdmin":false}], "roles": [] } + ] + }, + "servicePolicies": { + "serviceName": "hdfsdev", + "serviceDef": { + "name": "hdfs", "id": 1, + "resources": [ + {"name": "path", "type": "path", "level": 1, "mandatory": true, "lookupSupported": true, + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher", + "matcherOptions": {"wildCard": true, "ignoreCase": true}, + "label": "Resource Path", "description": "HDFS file or directory path" + } + ], + "accessTypes": [ + {"name": "read", "label": "Read"}, + {"name": "write", "label": "Write"}, + {"name": "execute", "label": "Execute"} + ], + "contextEnrichers": [ + { + "itemId": 1, + "name": "GeolocationEnricher", + "enricher": "org.apache.ranger.plugin.contextenricher.RangerFileBasedGeolocationProvider", + "enricherOptions": {"FilePath": "/etc/ranger/geo/geo.txt", "ForceRead": "false", "IPInDotFormat": "true", "geolocation.meta.prefix": "TEST_"} + } + ], + "policyConditions": [ + { + "itemId": 1, + "name": "ScriptConditionEvaluator", + "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator", + "evaluatorOptions": {"engineName": "JavaScript"}, + "label": "Script", + "description": "Script to execute" + } + ] + }, + "serviceConfig": {"ranger.plugin.hdfs.chained.service" : "mapped_hive", "ranger.plugin.hdfs.chained.service.mapped_hive.impl": "org.apache.ranger.chainedplugin.hdfs.hive.RangerHdfsHiveChainedPlugin"}, + "policies": [ + { + "id": 10, + "name": "allow-read-to-user1,user3 /test/restricted", + "isEnabled": true, "isAuditEnabled": true, "isDenyAllElse": true, + "resources": {"path": {"values": ["/test/restricted"], "isRecursive": true}}, + "policyItems": [ + { "accesses": [{"type": "read", "isAllowed": true}], "users": ["user1", "user2", "user3"], "groups": [], "roles":["sub-admin-1"],"delegateAdmin": false } + ], + "allowExceptions": [ + { "accesses": [{"type": "read", "isAllowed": true}], "users": ["user2"], "groups": [], "delegateAdmin": false } + ] + }, + { + "id": 20, + "name": "allow-read-to-user2 /test/restricted/a", + "isEnabled": true, "isAuditEnabled": true, + "resources": {"path": {"values": ["/test/restricted/a"],"isRecursive": true}}, + "policyItems": [ + { "accesses": [ {"type": "read", "isAllowed": true}, {"type": "write", "isAllowed": true} ], "users": ["user2", "non-user1", "non-user2", "non-user3"], "groups": ["public"], "delegateAdmin": false } + ], + "denyPolicyItems": [ + { "accesses": [ {"type": "read", "isAllowed": true} ], "users": ["non-user4"], "groups": [], "delegateAdmin": false } + ] + }, + { + "id": 30, + "name": "deny-read-to-user3 /test/restricted/b", + "isEnabled": true, "isAuditEnabled": true, + "resources": {"path": {"values": ["/test/restricted/b"], "isRecursive": true} }, + "policyItems": [ + { "accesses": [ {"type": "read", "isAllowed": true} ], "users": ["non-user5", "non-user6", "non-user7", "non-user8"], "groups": ["public"], "delegateAdmin": false, "conditions": [ { "type": "ScriptConditionEvaluator", "values": [ "var country_code = ctx.getRequestContextAttribute('LOCATION_TEST_COUNTRY_CODE'); ctx.result = !!country_code;" ] } ] } + ], + "denyPolicyItems": [ + { "accesses": [ { "type": "read", "isAllowed": true } ], "users": [ "user3", "non-user9" ], "groups": [], "delegateAdmin": false } + ] + }, + { + "id": 1, + "name": "audit-all-access under /finance/restricted", + "isEnabled": true, "isAuditEnabled": true, + "resources": { "path": { "values": [ "/finance/restricted" ], "isRecursive": true } }, + "policyItems": [ + { "accesses": [], "users": [], "groups": [ "public" ], "delegateAdmin": false } + ] + }, + { + "id": 2, + "name": "allow-read-to-all under /public/*", + "isEnabled": true, "isAuditEnabled": false, + "resources": { "path": { "values": [ "/public/*" ], "isRecursive": true } }, + "policyItems": [ + { "accesses": [ { "type": "read", "isAllowed": true }, { "type": "execute", "isAllowed": true } ], "users": [], "groups": [ "public" ], "delegateAdmin": false } + ] + }, + { + "id": 3, + "name": "allow-read-to-finance under /finance/restricted", + "isEnabled": true, "isAuditEnabled": true, + "resources": { "path": { "values": [ "/finance/restricted" ], "isRecursive": true } }, + "policyItems": [ + { "accesses": [ { "type": "read", "isAllowed": true } ], "users": [], "groups": [ "finance" ], "delegateAdmin": false, "conditions": [ { "type": "ScriptConditionEvaluator", "values": [ "var country_code = ctx.getRequestContextAttribute('LOCATION_TEST_COUNTRY_CODE'); ctx.result = !!country_code;" ] } ] } + ] + }, + { + "id": 4, + "name": "No access for /forbidden", + "isEnabled": true, "isAuditEnabled": true, + "isDenyAllElse": true, + "resources": { "path": { "values": [ "/forbidden" ], "isRecursive": true } }, + "policyItems": [ + { "accesses": [ { "type": "read", "isAllowed": true }, { "type": "read", "isAllowed": true }, { "type": "write", "isAllowed": true },{ "type": "execute", "isAllowed": true } ], "users": [], "groups": [ "public" ], "delegateAdmin": false } + ] + } + ] + } + , + "tests": [ + { + "name": "/test/restricted access", + "resource": {"elements":{"path":"/test/restricted" }}, + "userPermissions": {"user1": {"read": {"result":-1, "isFinal" : true}, "write": {"result":-1,"isFinal":true}, "execute":{"result":-1, "isFinal": true}}, "user2": {"read": {"result":-1, "isFinal" : true}, "write": {"result":-1,"isFinal":true}, "execute":{"result":-1, "isFinal": true}},"user3": {"read": {"result":0, "isFinal" : true}, "write": {"result":0,"isFinal":true}, "execute":{"result":0, "isFinal": true}}, "sub-admin-user-1": {"read": {"result":1, "isFinal" : true}, "write [...] + "groupPermissions": {"public": {"read": {"result":2, "isFinal" : true},"write": {"result":-1,"isFinal":true}, "execute":{"result":-1, "isFinal": true}}} + }, + { + "name": "all-deny-test", + "resource": {"elements":{"path":"/forbidden" }}, + "userPermissions": {}, + "groupPermissions": {"public": {"read": {"result":1, "isFinal" : true},"write": {"result":1,"isFinal":true}, "execute":{"result":1, "isFinal": true}}, + "other": {"read": {"result":-1, "isFinal" : true},"write": {"result":-1,"isFinal":true}, "execute":{"result":-1, "isFinal": true}}} + } + ] + } + ] +} +