RANGER-606: policy updated to support for policyItems for deny/allowExceptions/denyExceptions (in addition to existing allow)
Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/c18f8bf7 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/c18f8bf7 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/c18f8bf7 Branch: refs/heads/master Commit: c18f8bf7407809e2917abd7f00406043281a7e27 Parents: e8ceab4 Author: Madhan Neethiraj <[email protected]> Authored: Sun Sep 6 02:00:40 2015 -0700 Committer: Madhan Neethiraj <[email protected]> Committed: Tue Sep 8 15:47:33 2015 -0700 ---------------------------------------------------------------------- .../ranger/plugin/model/RangerPolicy.java | 158 +++++++++---- .../model/validation/RangerPolicyValidator.java | 28 ++- .../plugin/policyengine/RangerAccessResult.java | 7 +- .../policyengine/RangerPolicyEngineImpl.java | 70 ++++-- .../policyengine/RangerPolicyRepository.java | 106 +++++---- .../RangerAbstractPolicyEvaluator.java | 9 + .../RangerAbstractPolicyItemEvaluator.java | 26 ++- .../RangerDefaultPolicyEvaluator.java | 225 ++++++++++++++----- .../RangerDefaultPolicyItemEvaluator.java | 4 +- .../RangerOptimizedPolicyEvaluator.java | 63 +++--- .../policyevaluator/RangerPolicyEvaluator.java | 4 + .../RangerPolicyItemEvaluator.java | 6 + .../plugin/store/AbstractPredicateUtil.java | 38 +++- .../policyengine/test_policyengine_hbase.json | 8 + ...test_policyengine_hive_mutex_conditions.json | 73 +++--- .../test_policyengine_tag_hdfs.json | 72 +++--- .../test_policyengine_tag_hive.json | 35 +-- .../org/apache/ranger/biz/ServiceDBStore.java | 28 ++- .../org/apache/ranger/rest/ServiceREST.java | 31 ++- .../ranger/service/RangerPolicyService.java | 3 +- .../ranger/service/RangerPolicyServiceBase.java | 26 ++- .../RangerPolicyWithAssignedIdService.java | 3 +- .../main/webapp/scripts/models/RangerPolicy.js | 7 - .../scripts/modules/globalize/message/en.js | 1 - .../src/main/webapp/scripts/utils/XAUtils.js | 13 +- .../scripts/views/policies/PermissionList.js | 28 +-- .../scripts/views/policies/RangerPolicyForm.js | 84 +++++-- .../scripts/views/policies/RangerPolicyRO.js | 1 - .../views/policies/RangerPolicyTableLayout.js | 11 - .../views/reports/PlugableServiceDiffDetail.js | 16 -- .../scripts/views/reports/UserAccessLayout.js | 11 - .../templates/policies/PermissionItem.html | 3 - .../templates/policies/PermissionList.html | 15 +- .../policies/RangerPolicyForm_tmpl.html | 54 ++++- .../templates/policies/RangerPolicyRO_tmpl.html | 3 - .../PlugableServicePolicyDeleteDiff_tmpl.html | 1 - .../reports/PlugableServicePolicyDiff_tmpl.html | 1 - .../PlugableServicePolicyUpdateDiff_tmpl.html | 2 - .../ranger/service/TestRangerPolicyService.java | 6 +- 39 files changed, 864 insertions(+), 416 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicy.java ---------------------------------------------------------------------- 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 19c2b50..6486429 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 @@ -28,7 +28,6 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; -import org.apache.commons.collections.CollectionUtils; import org.codehaus.jackson.annotate.JsonAutoDetect; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; @@ -45,26 +44,24 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria // For future use private static final long serialVersionUID = 1L; - public static final int POLICY_TYPE_ALLOW = 0; - public static final int POLICY_TYPE_DENY = 1; - public static final int POLICY_ITEM_TYPE_DEFAULT = 0; - public static final int POLICY_ITEM_TYPE_ABSTAIN = 1; - private String service = null; private String name = null; - private Integer policyType = POLICY_TYPE_ALLOW; + private Integer policyType = null; private String description = null; private String resourceSignature = null; private Boolean isAuditEnabled = null; private Map<String, RangerPolicyResource> resources = null; private List<RangerPolicyItem> policyItems = null; + private List<RangerPolicyItem> denyPolicyItems = null; + private List<RangerPolicyItem> allowExceptions = null; + private List<RangerPolicyItem> denyExceptions = null; /** * @param */ public RangerPolicy() { - this(null, null, POLICY_TYPE_ALLOW, null, null, null, null); + this(null, null, null, null, null, null, null); } /** @@ -87,6 +84,9 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria setIsAuditEnabled(null); setResources(resources); setPolicyItems(policyItems); + setDenyPolicyItems(null); + setAllowExceptions(null); + setDenyExceptions(null); } /** @@ -103,6 +103,9 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria setIsAuditEnabled(other.getIsAuditEnabled()); setResources(other.getResources()); setPolicyItems(other.getPolicyItems()); + setDenyPolicyItems(other.getDenyPolicyItems()); + setAllowExceptions(other.getAllowExceptions()); + setDenyExceptions(other.getDenyExceptions()); } /** @@ -245,16 +248,88 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria } } - final public boolean isPolicyTypeAllow() { - boolean ret = this.policyType == null || this.policyType == POLICY_TYPE_ALLOW; + /** + * @return the denyPolicyItems + */ + public List<RangerPolicyItem> getDenyPolicyItems() { + return denyPolicyItems; + } + + /** + * @param denyPolicyItems the denyPolicyItems to set + */ + public void setDenyPolicyItems(List<RangerPolicyItem> denyPolicyItems) { + if(this.denyPolicyItems == null) { + this.denyPolicyItems = new ArrayList<RangerPolicyItem>(); + } - return ret; + if(this.denyPolicyItems == denyPolicyItems) { + return; + } + + this.denyPolicyItems.clear(); + + if(denyPolicyItems != null) { + for(RangerPolicyItem policyItem : denyPolicyItems) { + this.denyPolicyItems.add(policyItem); + } + } } - final public boolean isPolicyTypeDeny() { - boolean ret = this.policyType != null && this.policyType == POLICY_TYPE_DENY; + /** + * @return the allowExceptions + */ + public List<RangerPolicyItem> getAllowExceptions() { + return allowExceptions; + } + + /** + * @param allowExceptions the allowExceptions to set + */ + public void setAllowExceptions(List<RangerPolicyItem> allowExceptions) { + if(this.allowExceptions == null) { + this.allowExceptions = new ArrayList<RangerPolicyItem>(); + } + + if(this.allowExceptions == allowExceptions) { + return; + } + + this.allowExceptions.clear(); - return ret; + if(allowExceptions != null) { + for(RangerPolicyItem policyItem : allowExceptions) { + this.allowExceptions.add(policyItem); + } + } + } + + /** + * @return the denyExceptions + */ + public List<RangerPolicyItem> getDenyExceptions() { + return denyExceptions; + } + + /** + * @param denyExceptions the denyExceptions to set + */ + public void setDenyExceptions(List<RangerPolicyItem> denyExceptions) { + if(this.denyExceptions == null) { + this.denyExceptions = new ArrayList<RangerPolicyItem>(); + } + + if(this.denyExceptions == denyExceptions) { + return; + } + + this.denyExceptions.clear(); + + if(denyExceptions != null) { + for(RangerPolicyItem policyItem : denyExceptions) { + this.denyExceptions.add(policyItem); + } + } } @Override @@ -298,6 +373,36 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria } sb.append("} "); + sb.append("denyPolicyItems={"); + if(denyPolicyItems != null) { + for(RangerPolicyItem policyItem : denyPolicyItems) { + if(policyItem != null) { + policyItem.toString(sb); + } + } + } + sb.append("} "); + + sb.append("allowExceptions={"); + if(denyExceptions != null) { + for(RangerPolicyItem policyItem : allowExceptions) { + if(policyItem != null) { + policyItem.toString(sb); + } + } + } + sb.append("} "); + + sb.append("denyExceptions={"); + if(denyExceptions != null) { + for(RangerPolicyItem policyItem : denyExceptions) { + if(policyItem != null) { + policyItem.toString(sb); + } + } + } + sb.append("} "); + sb.append("}"); return sb; @@ -478,7 +583,6 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria private List<String> groups = null; private List<RangerPolicyItemCondition> conditions = null; private Boolean delegateAdmin = null; - private Integer itemType = POLICY_ITEM_TYPE_DEFAULT; public RangerPolicyItem() { this(null, null, null, null, null); @@ -490,7 +594,6 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria setGroups(groups); setConditions(conditions); setDelegateAdmin(delegateAdmin); - setItemType(null); } /** @@ -604,20 +707,6 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria this.delegateAdmin = delegateAdmin == null ? Boolean.FALSE : delegateAdmin; } - /** - * @return the itemType - */ - public Integer getItemType() { - return itemType; - } - - /** - * @param itemType the itemType to set - */ - public void setItemType(Integer itemType) { - this.itemType = itemType == null ? POLICY_ITEM_TYPE_DEFAULT : itemType; - } - @Override public String toString( ) { StringBuilder sb = new StringBuilder(); @@ -671,7 +760,6 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria sb.append("} "); sb.append("delegateAdmin={").append(delegateAdmin).append("} "); - sb.append("itemType={").append(itemType).append("} "); sb.append("}"); return sb; @@ -690,7 +778,6 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria result = prime * result + ((groups == null) ? 0 : groups.hashCode()); result = prime * result + ((users == null) ? 0 : users.hashCode()); - result = prime * result + ((itemType == null) ? 0 : itemType.hashCode()); return result; } @@ -718,11 +805,6 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria return false; } else if (!delegateAdmin.equals(other.delegateAdmin)) return false; - if (itemType == null) { - if (other.itemType != null) - return false; - } else if (!itemType.equals(other.itemType)) - return false; if (groups == null) { if (other.groups != null) return false; @@ -877,7 +959,7 @@ public class RangerPolicy extends RangerBaseModelObject implements java.io.Seria * @param values the value to set */ public void setValues(List<String> values) { - if (CollectionUtils.isEmpty(values)) { + if (values == null) { this.values = new ArrayList<String>(); } else { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java index da817c6..a5837ce 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java @@ -212,11 +212,21 @@ public class RangerPolicyValidator extends RangerValidator { serviceNameValid = true; } } - List<RangerPolicyItem> policyItems = policy.getPolicyItems(); - boolean isAuditEnabled = getIsAuditEnabled(policy); - RangerServiceDef serviceDef = null; - String serviceDefName = null; - if (CollectionUtils.isEmpty(policyItems) && !isAuditEnabled) { + + boolean isAuditEnabled = getIsAuditEnabled(policy); + String serviceDefName = null; + RangerServiceDef serviceDef = null; + int policyItemsCount = 0; + + if(CollectionUtils.isNotEmpty(policy.getPolicyItems())) { + policyItemsCount += policy.getPolicyItems().size(); + } + + if(CollectionUtils.isNotEmpty(policy.getDenyPolicyItems())) { + policyItemsCount += policy.getDenyPolicyItems().size(); + } + + if (policyItemsCount == 0 && !isAuditEnabled) { ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_MISSING_POLICY_ITEMS; failures.add(new ValidationFailureDetailsBuilder() .field("policy items") @@ -227,7 +237,7 @@ public class RangerPolicyValidator extends RangerValidator { valid = false; } else if (service != null) { serviceDefName = service.getType(); - serviceDef = getServiceDef(serviceDefName); + serviceDef = getServiceDef(serviceDefName); if (serviceDef == null) { ValidationErrorCode error = ValidationErrorCode.POLICY_VALIDATION_ERR_MISSING_SERVICE_DEF; failures.add(new ValidationFailureDetailsBuilder() @@ -238,9 +248,13 @@ public class RangerPolicyValidator extends RangerValidator { .build()); valid = false; } else { - valid = isValidPolicyItems(policyItems, failures, serviceDef) && valid; + valid = isValidPolicyItems(policy.getPolicyItems(), failures, serviceDef) && valid; + valid = isValidPolicyItems(policy.getDenyPolicyItems(), failures, serviceDef) && valid; + valid = isValidPolicyItems(policy.getAllowExceptions(), failures, serviceDef) && valid; + valid = isValidPolicyItems(policy.getDenyExceptions(), failures, serviceDef) && valid; } } + if (serviceNameValid) { // resource checks can't be done meaningfully otherwise valid = isValidResources(policy, failures, action, isAdmin, serviceDef) && valid; } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java index 9bc43c7..49d32b2 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessResult.java @@ -81,7 +81,7 @@ public class RangerAccessResult { public boolean getIsAccessDetermined() { return isAccessDetermined; } - private void setIsAccessDetermined(boolean value) { isAccessDetermined = value; } + public void setIsAccessDetermined(boolean value) { isAccessDetermined = value; } /** * @return the isAllowed @@ -94,7 +94,10 @@ public class RangerAccessResult { * @param isAllowed the isAllowed to set */ public void setIsAllowed(boolean isAllowed) { - setIsAccessDetermined(true); + if(! isAllowed) { + setIsAccessDetermined(true); + } + this.isAllowed = isAllowed; } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java ---------------------------------------------------------------------- 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 c7d2a28..3cccde0 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 @@ -288,6 +288,7 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { List<RangerPolicy> ret = new ArrayList<RangerPolicy>(); + // TODO: run through evaluator in tagPolicyRepository as well for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) { RangerPolicy policy = evaluator.getPolicy(); @@ -313,34 +314,43 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { RangerAccessResult ret = createAccessResult(request); if (ret != null && request != null) { - if (tagPolicyRepository != null && CollectionUtils.isNotEmpty(tagPolicyRepository.getPolicies())) { - RangerAccessResult tagAccessResult = isAccessAllowedForTagPolicies(request); + if (hasTagPolicies()) { + isAccessAllowedForTagPolicies(request, ret); if (LOG.isDebugEnabled()) { - if (tagAccessResult.getIsAccessDetermined() && tagAccessResult.getIsAuditedDetermined()) { - LOG.debug("RangerPolicyEngineImpl.isAccessAllowedNoAudit() - access and audit determined by tag policy. No resource policies will be evaluated, request=" + request + ", result=" + tagAccessResult); + if (ret.getIsAccessDetermined() && ret.getIsAuditedDetermined()) { + LOG.debug("RangerPolicyEngineImpl.isAccessAllowedNoAudit() - access and audit determined by tag policy. No resource policies will be evaluated, request=" + request + ", result=" + ret); } } - - ret.setAccessResultFrom(tagAccessResult); - ret.setAuditResultFrom(tagAccessResult); } if (!ret.getIsAccessDetermined() || !ret.getIsAuditedDetermined()) { - List<RangerPolicyEvaluator> evaluators = policyRepository.getPolicyEvaluators(); - - if (CollectionUtils.isNotEmpty(evaluators)) { + if (hasResourcePolicies()) { boolean foundInCache = policyRepository.setAuditEnabledFromCache(request, ret); + RangerPolicyEvaluator allowedEvaluator = null; + List<RangerPolicyEvaluator> evaluators = policyRepository.getPolicyEvaluators(); for (RangerPolicyEvaluator evaluator : evaluators) { evaluator.evaluate(request, ret); + if(allowedEvaluator == null && ret.getIsAllowed()) { + allowedEvaluator = evaluator; + } + // stop once isAccessDetermined==true && isAuditedDetermined==true - if (ret.getIsAccessDetermined() && ret.getIsAuditedDetermined()) { - break; + if(ret.getIsAuditedDetermined()) { + if(ret.getIsAccessDetermined() || (allowedEvaluator != null && !evaluator.hasDeny())) { + break; // Break out of policy-evaluation loop for this tag + } } } + if(!ret.getIsAccessDetermined() && allowedEvaluator != null) { + ret.setIsAllowed(true); + ret.setPolicyId(allowedEvaluator.getPolicy().getId()); + ret.setIsAccessDetermined(true); + } + if (!foundInCache) { policyRepository.storeAuditEnabledInCache(request, ret); } @@ -355,12 +365,11 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { return ret; } - protected RangerAccessResult isAccessAllowedForTagPolicies(final RangerAccessRequest request) { + protected RangerAccessResult isAccessAllowedForTagPolicies(final RangerAccessRequest request, RangerAccessResult result) { if (LOG.isDebugEnabled()) { LOG.debug("==> RangerPolicyEngineImpl.isAccessAllowedForTagPolicies(" + request + ")"); } - RangerAccessResult result = createAccessResult(request); List<RangerPolicyEvaluator> evaluators = tagPolicyRepository.getPolicyEvaluators(); if (CollectionUtils.isNotEmpty(evaluators)) { @@ -376,20 +385,33 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { LOG.debug("RangerPolicyEngineImpl.isAccessAllowedForTagPolicies: Evaluating policies for tag (" + tag.getType() + ")"); } - RangerAccessRequest tagEvalRequest = new RangerTagAccessRequest(tag, tagPolicyRepository.getServiceDef(), request); - RangerAccessResult tagEvalResult = createAccessResult(tagEvalRequest); + RangerAccessRequest tagEvalRequest = new RangerTagAccessRequest(tag, tagPolicyRepository.getServiceDef(), request); + RangerAccessResult tagEvalResult = createAccessResult(tagEvalRequest); + RangerPolicyEvaluator allowedEvaluator = null; for (RangerPolicyEvaluator evaluator : evaluators) { evaluator.evaluate(tagEvalRequest, tagEvalResult); - if (tagEvalResult.getIsAccessDetermined() && tagEvalResult.getIsAuditedDetermined()) { - if (LOG.isDebugEnabled()) { - LOG.debug("RangerPolicyEngineImpl.isAccessAllowedForTagPolicies: concluding eval of tag (" + tag.getType() + ") with authorization=" + tagEvalResult.getIsAllowed()); + if(allowedEvaluator == null && tagEvalResult.getIsAllowed()) { + allowedEvaluator = evaluator; + } + + if(tagEvalResult.getIsAuditedDetermined()) { + if(tagEvalResult.getIsAccessDetermined() || (allowedEvaluator != null && !evaluator.hasDeny())) { + if (LOG.isDebugEnabled()) { + LOG.debug("RangerPolicyEngineImpl.isAccessAllowedForTagPolicies: concluding eval of tag (" + tag.getType() + ") with authorization=" + tagEvalResult.getIsAllowed()); + } + break; // Break out of policy-evaluation loop for this tag } - break; // Break out of policy-evaluation loop for this tag } } + if(!tagEvalResult.getIsAccessDetermined() && allowedEvaluator != null) { + tagEvalResult.setIsAllowed(true); + tagEvalResult.setPolicyId(allowedEvaluator.getPolicy().getId()); + tagEvalResult.setIsAccessDetermined(true); + } + if (tagEvalResult.getIsAuditedDetermined()) { someTagAllowedAudit = true; // And generate an audit event @@ -453,6 +475,14 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine { } } + private boolean hasTagPolicies() { + return tagPolicyRepository != null && CollectionUtils.isNotEmpty(tagPolicyRepository.getPolicies()); + } + + private boolean hasResourcePolicies() { + return policyRepository != null && CollectionUtils.isNotEmpty(policyRepository.getPolicies()); + } + @Override public String toString( ) { StringBuilder sb = new StringBuilder(); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java index 96fddde..8519860 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java @@ -92,7 +92,7 @@ public class RangerPolicyRepository { this.appId = appId; - this.policies = Collections.unmodifiableList(normalizePolicyItemAccesses(tagPolicies.getPolicies(), componentServiceDef.getName())); + this.policies = Collections.unmodifiableList(normalizeAndPrunePolicies(tagPolicies.getPolicies(), componentServiceDef.getName())); this.policyVersion = tagPolicies.getPolicyVersion() != null ? tagPolicies.getPolicyVersion() : -1; this.accessAuditCache = null; @@ -134,7 +134,7 @@ public class RangerPolicyRepository { String prefix = componentType + AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR; - List<RangerServiceDef.RangerAccessTypeDef> unneededAccessTypeDefs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>(); + List<RangerServiceDef.RangerAccessTypeDef> unneededAccessTypeDefs = null; for (RangerServiceDef.RangerAccessTypeDef accessTypeDef : accessTypeDefs) { @@ -169,72 +169,102 @@ public class RangerPolicyRepository { } } else if (StringUtils.contains(accessType, AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR)) { + if(unneededAccessTypeDefs == null) { + unneededAccessTypeDefs = new ArrayList<RangerServiceDef.RangerAccessTypeDef>(); + } + unneededAccessTypeDefs.add(accessTypeDef); } } - accessTypeDefs.removeAll(unneededAccessTypeDefs); + + if(unneededAccessTypeDefs != null) { + accessTypeDefs.removeAll(unneededAccessTypeDefs); + } } } return serviceDef; } - private List<RangerPolicy> normalizePolicyItemAccesses(List<RangerPolicy> rangerPolicies, final String componentType) { - + private List<RangerPolicy> normalizeAndPrunePolicies(List<RangerPolicy> rangerPolicies, final String componentType) { if (CollectionUtils.isNotEmpty(rangerPolicies) && StringUtils.isNotBlank(componentType)) { - - String prefix = componentType + AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR; - - List<RangerPolicy> unneededPolicies = new ArrayList<>(); + List<RangerPolicy> policiesToPrune = null; for (RangerPolicy policy : rangerPolicies) { + normalizeAndPrunePolicyItems(policy.getPolicyItems(), componentType); + normalizeAndPrunePolicyItems(policy.getDenyPolicyItems(), componentType); + normalizeAndPrunePolicyItems(policy.getAllowExceptions(), componentType); + normalizeAndPrunePolicyItems(policy.getDenyExceptions(), componentType); + + if (!policy.getIsAuditEnabled() && + CollectionUtils.isEmpty(policy.getPolicyItems()) && + CollectionUtils.isEmpty(policy.getDenyPolicyItems()) && + CollectionUtils.isEmpty(policy.getAllowExceptions()) && + CollectionUtils.isEmpty(policy.getDenyExceptions())) { + + if(policiesToPrune == null) { + policiesToPrune = new ArrayList<RangerPolicy>(); + } - List<RangerPolicy.RangerPolicyItem> policyItems = policy.getPolicyItems(); - - if (CollectionUtils.isNotEmpty(policyItems)) { - - List<RangerPolicy.RangerPolicyItem> unneededPolicyItems = new ArrayList< RangerPolicy.RangerPolicyItem>(); - - for (RangerPolicy.RangerPolicyItem policyItem : policyItems) { - - List<RangerPolicy.RangerPolicyItemAccess> policyItemAccesses = policyItem.getAccesses(); + policiesToPrune.add(policy); + } + } - if (CollectionUtils.isNotEmpty(policyItemAccesses)) { + if(policiesToPrune != null) { + rangerPolicies.removeAll(policiesToPrune); + } + } - List<RangerPolicy.RangerPolicyItemAccess> unneededItemAccesses = new ArrayList<RangerPolicy.RangerPolicyItemAccess>(); + return rangerPolicies; + } - for (RangerPolicy.RangerPolicyItemAccess access : policyItemAccesses) { + private List<RangerPolicy.RangerPolicyItem> normalizeAndPrunePolicyItems(List<RangerPolicy.RangerPolicyItem> policyItems, final String componentType) { + if(CollectionUtils.isNotEmpty(policyItems)) { + final String prefix = componentType + AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR; + List<RangerPolicy.RangerPolicyItem> itemsToPrune = null; - String accessType = access.getType(); + for (RangerPolicy.RangerPolicyItem policyItem : policyItems) { + List<RangerPolicy.RangerPolicyItemAccess> policyItemAccesses = policyItem.getAccesses(); - if (StringUtils.startsWith(accessType, prefix)) { + if (CollectionUtils.isNotEmpty(policyItemAccesses)) { + List<RangerPolicy.RangerPolicyItemAccess> accessesToPrune = null; - String newAccessType = StringUtils.removeStart(accessType, prefix); + for (RangerPolicy.RangerPolicyItemAccess access : policyItemAccesses) { + String accessType = access.getType(); - access.setType(newAccessType); + if (StringUtils.startsWith(accessType, prefix)) { + String newAccessType = StringUtils.removeStart(accessType, prefix); - } else if (accessType.contains(AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR)) { - unneededItemAccesses.add(access); - } + access.setType(newAccessType); + } else if (accessType.contains(AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR)) { + if(accessesToPrune == null) { + accessesToPrune = new ArrayList<RangerPolicy.RangerPolicyItemAccess>(); } - policyItemAccesses.removeAll(unneededItemAccesses); - if (policyItemAccesses.isEmpty() && !policyItem.getDelegateAdmin()) { - unneededPolicyItems.add(policyItem); - } + accessesToPrune.add(access); } } - policyItems.removeAll(unneededPolicyItems); - } - if (CollectionUtils.isEmpty(policyItems) && !policy.getIsAuditEnabled()) { - unneededPolicies.add(policy); + if(accessesToPrune != null) { + policyItemAccesses.removeAll(accessesToPrune); + } + + if (policyItemAccesses.isEmpty() && !policyItem.getDelegateAdmin()) { + if(itemsToPrune != null) { + itemsToPrune = new ArrayList< RangerPolicy.RangerPolicyItem>(); + } + + itemsToPrune.add(policyItem); + } } } - rangerPolicies.removeAll(unneededPolicies); + + if(itemsToPrune != null) { + policyItems.removeAll(itemsToPrune); + } } - return rangerPolicies; + return policyItems; } private void init(RangerPolicyEngineOptions options) { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java index 1308e63..fa35f1c 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java @@ -21,6 +21,7 @@ package org.apache.ranger.plugin.policyevaluator; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ranger.plugin.model.RangerPolicy; @@ -60,6 +61,14 @@ public abstract class RangerAbstractPolicyEvaluator implements RangerPolicyEvalu return serviceDef; } + public boolean hasAllow() { + return policy != null && CollectionUtils.isNotEmpty(policy.getPolicyItems()); + } + + public boolean hasDeny() { + return policy != null && CollectionUtils.isNotEmpty(policy.getDenyPolicyItems()); + } + @Override public int getEvalOrder() { return evalOrder; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java ---------------------------------------------------------------------- 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 45fce94..450f766 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 @@ -36,8 +36,7 @@ import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; public abstract class RangerAbstractPolicyItemEvaluator implements RangerPolicyItemEvaluator { private static final Log LOG = LogFactory.getLog(RangerAbstractPolicyItemEvaluator.class); - private static final int RANGER_POLICY_ITEM_EVAL_ORDER_DEFAULT = 1000; - private static final int RANGER_POLICY_ITEM_EVAL_ORDER_DISCOUNT_ABSTAIN = 500; + private static final int RANGER_POLICY_ITEM_EVAL_ORDER_DEFAULT = 1000; private static final int RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_USERSGROUPS = 25; private static final int RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_ACCESS_TYPES = 25; @@ -47,17 +46,19 @@ public abstract class RangerAbstractPolicyItemEvaluator implements RangerPolicyI final RangerPolicyEngineOptions options; final RangerServiceDef serviceDef; final RangerPolicyItem policyItem; + final int policyItemType; final long policyId; final int evalOrder; List<RangerConditionEvaluator> conditionEvaluators = Collections.<RangerConditionEvaluator>emptyList(); - RangerAbstractPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, RangerPolicyEngineOptions options) { - this.serviceDef = serviceDef; - this.policyItem = policyItem; - this.options = options; - this.policyId = policy != null && policy.getId() != null ? policy.getId() : -1; - this.evalOrder = computeEvalOrder(); + RangerAbstractPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, int policyItemType, RangerPolicyEngineOptions options) { + this.serviceDef = serviceDef; + this.policyItem = policyItem; + this.policyItemType = policyItemType; + this.options = options; + this.policyId = policy != null && policy.getId() != null ? policy.getId() : -1; + this.evalOrder = computeEvalOrder(); } @Override @@ -76,6 +77,11 @@ public abstract class RangerAbstractPolicyItemEvaluator implements RangerPolicyI } @Override + public int getPolicyItemType() { + return policyItemType; + } + + @Override public int compareTo(RangerPolicyItemEvaluator other) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerAbstractPolicyItemEvaluator.compareTo()"); @@ -102,10 +108,6 @@ public abstract class RangerAbstractPolicyItemEvaluator implements RangerPolicyI int evalOrder = RANGER_POLICY_ITEM_EVAL_ORDER_DEFAULT; if(policyItem != null) { - if(policyItem.getItemType() == RangerPolicy.POLICY_ITEM_TYPE_ABSTAIN) { - evalOrder -= RANGER_POLICY_ITEM_EVAL_ORDER_DISCOUNT_ABSTAIN; - } - if(CollectionUtils.isNotEmpty(policyItem.getGroups()) && policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC)) { evalOrder -= RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_USERSGROUPS; } else { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java ---------------------------------------------------------------------- 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 9c63089..a6285d9 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 @@ -49,9 +49,12 @@ import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatche public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator { private static final Log LOG = LogFactory.getLog(RangerDefaultPolicyEvaluator.class); - private RangerPolicyResourceMatcher resourceMatcher = null; - private List<RangerPolicyItemEvaluator> policyItemEvaluators = null; - private int customConditionsCount = 0; + private RangerPolicyResourceMatcher resourceMatcher = null; + private List<RangerPolicyItemEvaluator> allowEvaluators = null; + private List<RangerPolicyItemEvaluator> denyEvaluators = null; + private List<RangerPolicyItemEvaluator> allowExceptionEvaluators = null; + private List<RangerPolicyItemEvaluator> denyExceptionEvaluators = null; + private int customConditionsCount = 0; @Override public int getCustomConditionsCount() { @@ -64,35 +67,32 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator LOG.debug("==> RangerDefaultPolicyEvaluator.init()"); } - preprocessPolicy(policy, serviceDef); - super.init(policy, serviceDef, options); + preprocessPolicy(policy, serviceDef); + resourceMatcher = new RangerDefaultPolicyResourceMatcher(); resourceMatcher.setServiceDef(serviceDef); resourceMatcher.setPolicyResources(policy == null ? null : policy.getResources()); resourceMatcher.init(); - - if(policy != null && CollectionUtils.isNotEmpty(policy.getPolicyItems())) { - policyItemEvaluators = new ArrayList<RangerPolicyItemEvaluator>(); - - for(RangerPolicyItem policyItem : policy.getPolicyItems()) { - RangerPolicyItemEvaluator itemEvaluator = new RangerDefaultPolicyItemEvaluator(serviceDef, policy, policyItem, options); - itemEvaluator.init(); - - policyItemEvaluators.add(itemEvaluator); - - if(CollectionUtils.isNotEmpty(itemEvaluator.getConditionEvaluators())) { - customConditionsCount += itemEvaluator.getConditionEvaluators().size(); - } - } + if(policy != null) { + allowEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, policy.getPolicyItems(), RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW); + denyEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, policy.getDenyPolicyItems(), RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY); + allowExceptionEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, policy.getAllowExceptions(), RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS); + denyExceptionEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, policy.getDenyExceptions(), RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS); } else { - policyItemEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); + allowEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); + denyEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); + allowExceptionEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); + denyExceptionEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); } - Collections.sort(policyItemEvaluators); + Collections.sort(allowEvaluators); + Collections.sort(denyEvaluators); + Collections.sort(allowExceptionEvaluators); + Collections.sort(denyExceptionEvaluators); if(LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyEvaluator.init()"); @@ -152,15 +152,15 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator } // Go further to evaluate access only if match or head match was found at this point if (isResourceMatch || isResourceHeadMatch) { - boolean isPolicyItemsMatch = isPolicyItemsMatch(request); + RangerPolicyItemEvaluator matchedPolicyItem = getDeterminingPolicyItem(request); - RangerPolicy policy = getPolicy(); + if(matchedPolicyItem != null) { + RangerPolicy policy = getPolicy(); - if(isPolicyItemsMatch) { - if(policy.isPolicyTypeDeny()) { + if(matchedPolicyItem.getPolicyItemType() == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY) { if(isResourceMatch) { - result.setIsAllowed(false); - result.setPolicyId(policy.getId()); + result.setIsAllowed(false); + result.setPolicyId(policy.getId()); } } else { result.setIsAllowed(true); @@ -176,28 +176,49 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator } } - protected boolean isPolicyItemsMatch(RangerAccessRequest request) { + protected RangerPolicyItemEvaluator getDeterminingPolicyItem(RangerAccessRequest request) { if(LOG.isDebugEnabled()) { - LOG.debug("==> RangerDefaultPolicyEvaluator.isPolicyItemsMatch(" + request + ")"); + LOG.debug("==> RangerDefaultPolicyEvaluator.getDeterminingPolicyItem(" + request + ")"); } - boolean ret = false; + RangerPolicyItemEvaluator ret = null; - if(CollectionUtils.isNotEmpty(policyItemEvaluators)) { - for (RangerPolicyItemEvaluator policyItemEvaluator : policyItemEvaluators) { - ret = policyItemEvaluator.isMatch(request); + /* + * 1. if a deny matches without hitting any deny-exception, return that + * 2. if an allow matches without hitting any allow-exception, return that + */ + ret = getMatchingPolicyItem(request, denyEvaluators, denyExceptionEvaluators); - if(ret) { - if(policyItemEvaluator.getPolicyItem().getItemType() == RangerPolicy.POLICY_ITEM_TYPE_ABSTAIN) { - ret = false; - } - break; - } - } + if(ret == null) { + ret = getMatchingPolicyItem(request, allowEvaluators, allowExceptionEvaluators); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.getDeterminingPolicyItem(" + request + "): " + ret); + } + + return ret; + } + + protected RangerPolicyItemEvaluator getDeterminingPolicyItem(String user, Set<String> userGroups, String accessType) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.getDeterminingPolicyItem(" + user + ", " + userGroups + ", " + accessType + ")"); + } + + RangerPolicyItemEvaluator ret = null; + + /* + * 1. if a deny matches without hitting any deny-exception, return that + * 2. if an allow matches without hitting any allow-exception, return that + */ + ret = getMatchingPolicyItem(user, userGroups, accessType, denyEvaluators, denyExceptionEvaluators); + + if(ret == null) { + ret = getMatchingPolicyItem(user, userGroups, accessType, allowEvaluators, allowExceptionEvaluators); } if(LOG.isDebugEnabled()) { - LOG.debug("<== RangerDefaultPolicyEvaluator.isPolicyItemsMatch(" + request + "): " + ret); + LOG.debug("<== RangerDefaultPolicyEvaluator.getDeterminingPolicyItem(" + user + ", " + userGroups + ", " + accessType + "): " + ret); } return ret; @@ -315,15 +336,10 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator boolean ret = false; - if(CollectionUtils.isNotEmpty(policyItemEvaluators)) { - for (RangerPolicyItemEvaluator policyItemEvaluator : policyItemEvaluators) { - ret = policyItemEvaluator.matchUserGroup(user, userGroups) && - policyItemEvaluator.matchAccessType(accessType); + RangerPolicyItemEvaluator item = this.getDeterminingPolicyItem(user, userGroups, accessType); - if(ret) { - break; - } - } + if(item != null && item.getPolicyItemType() == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW) { + ret = true; } if(LOG.isDebugEnabled()) { @@ -350,7 +366,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator } private void preprocessPolicy(RangerPolicy policy, RangerServiceDef serviceDef) { - if(policy == null || CollectionUtils.isEmpty(policy.getPolicyItems()) || serviceDef == null) { + if(policy == null || (!hasAllow() && !hasDeny()) || serviceDef == null) { return; } @@ -360,7 +376,14 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator return; } - for(RangerPolicyItem policyItem : policy.getPolicyItems()) { + preprocessPolicyItems(policy.getPolicyItems(), impliedAccessGrants); + preprocessPolicyItems(policy.getDenyPolicyItems(), impliedAccessGrants); + preprocessPolicyItems(policy.getAllowExceptions(), impliedAccessGrants); + preprocessPolicyItems(policy.getDenyExceptions(), impliedAccessGrants); + } + + private void preprocessPolicyItems(List<RangerPolicyItem> policyItems, Map<String, Collection<String>> impliedAccessGrants) { + for(RangerPolicyItem policyItem : policyItems) { if(CollectionUtils.isEmpty(policyItem.getAccesses())) { continue; } @@ -437,4 +460,104 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator return ret; } + + private List<RangerPolicyItemEvaluator> createPolicyItemEvaluators(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options, List<RangerPolicyItem> policyItems, int policyItemType) { + List<RangerPolicyItemEvaluator> ret = null; + + if(CollectionUtils.isNotEmpty(policyItems)) { + ret = new ArrayList<RangerPolicyItemEvaluator>(); + + for(RangerPolicyItem policyItem : policyItems) { + RangerPolicyItemEvaluator itemEvaluator = new RangerDefaultPolicyItemEvaluator(serviceDef, policy, policyItem, policyItemType, options); + + itemEvaluator.init(); + + ret.add(itemEvaluator); + + if(CollectionUtils.isNotEmpty(itemEvaluator.getConditionEvaluators())) { + customConditionsCount += itemEvaluator.getConditionEvaluators().size(); + } + } + } else { + ret = Collections.<RangerPolicyItemEvaluator>emptyList(); + } + + return ret; + } + + private RangerPolicyItemEvaluator getMatchingPolicyItem(RangerAccessRequest request, List<RangerPolicyItemEvaluator> evaluators, List<RangerPolicyItemEvaluator> exceptionEvaluators) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + request + ")"); + } + + RangerPolicyItemEvaluator ret = null; + + if(CollectionUtils.isNotEmpty(evaluators)) { + for (RangerPolicyItemEvaluator evaluator : evaluators) { + if(evaluator.isMatch(request)) { + ret = evaluator; + + break; + } + } + } + + if(ret != null && CollectionUtils.isNotEmpty(exceptionEvaluators)) { + for (RangerPolicyItemEvaluator exceptionEvaluator : exceptionEvaluators) { + if(exceptionEvaluator.isMatch(request)) { + if(LOG.isDebugEnabled()) { + LOG.debug("RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + request + "): found exception policyItem(" + exceptionEvaluator.getPolicyItem() + "); ignoring the matchedPolicyItem(" + ret.getPolicyItem() + ")"); + } + + ret = null; + + break; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + request + "): " + ret); + } + + return ret; + } + + private RangerPolicyItemEvaluator getMatchingPolicyItem(String user, Set<String> userGroups, String accessType, List<RangerPolicyItemEvaluator> evaluators, List<RangerPolicyItemEvaluator> exceptionEvaluators) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + user + ", " + userGroups + ", " + accessType + ")"); + } + + RangerPolicyItemEvaluator ret = null; + + if(CollectionUtils.isNotEmpty(evaluators)) { + for (RangerPolicyItemEvaluator evaluator : evaluators) { + if(evaluator.matchUserGroup(user, userGroups) && evaluator.matchAccessType(accessType)) { + ret = evaluator; + + break; + } + } + } + + if(ret != null && CollectionUtils.isNotEmpty(exceptionEvaluators)) { + for (RangerPolicyItemEvaluator exceptionEvaluator : exceptionEvaluators) { + if(exceptionEvaluator.matchUserGroup(user, userGroups) && exceptionEvaluator.matchAccessType(accessType)) { + if(LOG.isDebugEnabled()) { + LOG.debug("RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + user + ", " + userGroups + ", " + accessType + "): found exception policyItem(" + exceptionEvaluator.getPolicyItem() + "); ignoring the matchedPolicyItem(" + ret.getPolicyItem() + ")"); + } + + ret = null; + + break; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + user + ", " + userGroups + ", " + accessType + "): " + ret); + } + + return ret; + } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java ---------------------------------------------------------------------- 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 6f8faff..39a0a5e 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 @@ -42,8 +42,8 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv private static final Log LOG = LogFactory.getLog(RangerDefaultPolicyItemEvaluator.class); - public RangerDefaultPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, RangerPolicyEngineOptions options) { - super(serviceDef, policy, policyItem, options); + public RangerDefaultPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, int policyItemType, RangerPolicyEngineOptions options) { + super(serviceDef, policy, policyItem, policyItemType, options); } public void init() { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java ---------------------------------------------------------------------- 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 9fa20cd..a118466 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 @@ -35,9 +35,9 @@ import java.lang.Math; public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator { private static final Log LOG = LogFactory.getLog(RangerOptimizedPolicyEvaluator.class); - private Set<String> groups = null; - private Set<String> users = null; - private Set<String> accessPerms = null; + private Set<String> groups = new HashSet<String>(); + private Set<String> users = new HashSet<String>(); + private Set<String> accessPerms = new HashSet<String>(); private boolean delegateAdmin = false; private boolean hasAllPerms = false; private boolean hasPublicGroup = false; @@ -48,7 +48,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator private static final String RANGER_POLICY_EVAL_MATCH_ONE_CHARACTER_STRING = "?"; private static final int RANGER_POLICY_EVAL_SCORE_DEFAULT = 10000; - private static final int RANGER_POLICY_EVAL_SCORE_DISCOUNT_DENY_POLICY = 4000; + private static final int RANGER_POLICY_EVAL_SCORE_DISCOUNT_POLICY_HAS_DENY = 4000; private static final int RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_RESOURCE = 100; private static final int RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_USERSGROUPS = 25; @@ -71,25 +71,10 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator super.init(policy, serviceDef, options); - accessPerms = new HashSet<String>(); - groups = new HashSet<String>(); - users = new HashSet<String>(); - - for (RangerPolicy.RangerPolicyItem item : policy.getPolicyItems()) { - delegateAdmin = delegateAdmin || item.getDelegateAdmin(); - - List<RangerPolicy.RangerPolicyItemAccess> policyItemAccesses = item.getAccesses(); - for(RangerPolicy.RangerPolicyItemAccess policyItemAccess : policyItemAccesses) { - - if (policyItemAccess.getIsAllowed()) { - String accessType = policyItemAccess.getType(); - accessPerms.add(accessType); - } - } - - groups.addAll(item.getGroups()); - users.addAll(item.getUsers()); - } + preprocessPolicyItems(policy.getPolicyItems()); + preprocessPolicyItems(policy.getDenyPolicyItems()); + preprocessPolicyItems(policy.getAllowExceptions()); + preprocessPolicyItems(policy.getDenyExceptions()); hasAllPerms = checkIfHasAllPerms(); @@ -203,8 +188,8 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator evalOrder -= customConditionsDiscount; } - if (policy.isPolicyTypeDeny()) { - evalOrder -= RANGER_POLICY_EVAL_SCORE_DISCOUNT_DENY_POLICY; + if (hasDeny()) { + evalOrder -= RANGER_POLICY_EVAL_SCORE_DISCOUNT_POLICY_HAS_DENY; } if(LOG.isDebugEnabled()) { @@ -243,19 +228,19 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator } @Override - protected boolean isPolicyItemsMatch(RangerAccessRequest request) { + protected RangerPolicyItemEvaluator getDeterminingPolicyItem(RangerAccessRequest request) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerOptimizedPolicyEvaluator.isPolicyItemsMatch()"); } - boolean ret = false; + RangerPolicyItemEvaluator ret = null; if (hasPublicGroup || users.contains(request.getUser()) || CollectionUtils.containsAny(groups, request.getUserGroups())) { // No need to reject based on users and groups if (request.isAccessTypeAny() || (request.isAccessTypeDelegatedAdmin() && delegateAdmin) || hasAllPerms || accessPerms.contains(request.getAccessType())) { // No need to reject based on aggregated access permissions - ret = super.isPolicyItemsMatch(request); + ret = super.getDeterminingPolicyItem(request); } } @@ -266,6 +251,26 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator return ret; } + private void preprocessPolicyItems(List<RangerPolicy.RangerPolicyItem> policyItems) { + if(CollectionUtils.isNotEmpty(policyItems)) { + for (RangerPolicy.RangerPolicyItem item : policyItems) { + delegateAdmin = delegateAdmin || item.getDelegateAdmin(); + + List<RangerPolicy.RangerPolicyItemAccess> policyItemAccesses = item.getAccesses(); + for(RangerPolicy.RangerPolicyItemAccess policyItemAccess : policyItemAccesses) { + + if (policyItemAccess.getIsAllowed()) { + String accessType = policyItemAccess.getType(); + accessPerms.add(accessType); + } + } + + groups.addAll(item.getGroups()); + users.addAll(item.getUsers()); + } + } + } + private boolean checkIfHasAllPerms() { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerOptimizedPolicyEvaluator.checkIfHasAllPerms()"); @@ -275,7 +280,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator List<RangerServiceDef.RangerAccessTypeDef> serviceAccessTypes = getServiceDef().getAccessTypes(); for (RangerServiceDef.RangerAccessTypeDef serviceAccessType : serviceAccessTypes) { if(! accessPerms.contains(serviceAccessType.getName())) { - result = false; + result = false; break; } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java ---------------------------------------------------------------------- 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 624ff1c..e5f34a2 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 @@ -42,6 +42,10 @@ public interface RangerPolicyEvaluator extends Comparable<RangerPolicyEvaluator> RangerServiceDef getServiceDef(); + boolean hasAllow(); + + boolean hasDeny(); + int getEvalOrder(); int getCustomConditionsCount(); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java ---------------------------------------------------------------------- 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 e91d5d1..6360dc9 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 @@ -26,11 +26,17 @@ import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; public interface RangerPolicyItemEvaluator extends Comparable<RangerPolicyItemEvaluator> { + public static final int POLICY_ITEM_TYPE_ALLOW = 0; + public static final int POLICY_ITEM_TYPE_DENY = 1; + public static final int POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS = 2; + public static final int POLICY_ITEM_TYPE_DENY_EXCEPTIONS = 3; void init(); RangerPolicyItem getPolicyItem(); + int getPolicyItemType(); + List<RangerConditionEvaluator> getConditionEvaluators(); int getEvalOrder(); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractPredicateUtil.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractPredicateUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractPredicateUtil.java index 772c2d7..abfb350 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractPredicateUtil.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractPredicateUtil.java @@ -374,11 +374,22 @@ public class AbstractPredicateUtil { if(object instanceof RangerPolicy) { RangerPolicy policy = (RangerPolicy)object; - for(RangerPolicyItem policyItem : policy.getPolicyItems()) { - if(policyItem.getUsers().contains(userName)) { - ret = true; + List<?>[] policyItemsList = new List<?>[] { policy.getPolicyItems(), + policy.getDenyPolicyItems(), + policy.getAllowExceptions(), + policy.getDenyExceptions() + }; - break; + for(List<?> policyItemsObj : policyItemsList) { + @SuppressWarnings("unchecked") + List<RangerPolicyItem> policyItems = (List<RangerPolicyItem>)policyItemsObj; + + for(RangerPolicyItem policyItem : policyItems) { + if(policyItem.getUsers().contains(userName)) { + ret = true; + + break; + } } } } else { @@ -413,11 +424,22 @@ public class AbstractPredicateUtil { if(object instanceof RangerPolicy) { RangerPolicy policy = (RangerPolicy)object; - for(RangerPolicyItem policyItem : policy.getPolicyItems()) { - if(policyItem.getGroups().contains(groupName)) { - ret = true; + List<?>[] policyItemsList = new List<?>[] { policy.getPolicyItems(), + policy.getDenyPolicyItems(), + policy.getAllowExceptions(), + policy.getDenyExceptions() + }; - break; + for(List<?> policyItemsObj : policyItemsList) { + @SuppressWarnings("unchecked") + List<RangerPolicyItem> policyItems = (List<RangerPolicyItem>)policyItemsObj; + + for(RangerPolicyItem policyItem : policyItems) { + if(policyItem.getGroups().contains(groupName)) { + ret = true; + + break; + } } } } else { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/test/resources/policyengine/test_policyengine_hbase.json ---------------------------------------------------------------------- diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_hbase.json b/agents-common/src/test/resources/policyengine/test_policyengine_hbase.json index de9c130..b267be0 100644 --- a/agents-common/src/test/resources/policyengine/test_policyengine_hbase.json +++ b/agents-common/src/test/resources/policyengine/test_policyengine_hbase.json @@ -43,6 +43,14 @@ ], "tests":[ + {"name":"TEST!!! ALLOW 'scan finance restricted-cf;' for finance-admin", + "request":{ + "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}}, + "accessType":"read","user":"user1","userGroups":["users","finance-admin"],"requestData":"scan finance restricted-cf" + }, + "result":{"isAudited":true,"isAllowed":true,"policyId":2} + } + , {"name":"ALLOW 'scan finance restricted-cf;' for finance", "request":{ "resource":{"elements":{"table":"finance","column-family":"restricted-cf"}}, http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/test/resources/policyengine/test_policyengine_hive_mutex_conditions.json ---------------------------------------------------------------------- diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_hive_mutex_conditions.json b/agents-common/src/test/resources/policyengine/test_policyengine_hive_mutex_conditions.json index 9c29cfd..4de74ad 100644 --- a/agents-common/src/test/resources/policyengine/test_policyengine_hive_mutex_conditions.json +++ b/agents-common/src/test/resources/policyengine/test_policyengine_hive_mutex_conditions.json @@ -33,24 +33,34 @@ }, "policies":[ - {"id":1,"name":"db=default; deny select with mutual exclusion of col* for everyone except user2, admin","isEnabled":true,"isAuditEnabled":true,"policyType":1, + {"id":1,"name":"db=default; allow select with mutual exclusion of col* only for user2, admin; deny for everyone else","isEnabled":true,"isAuditEnabled":true, "resources":{"database":{"values":["default"]},"table":{"values":["testTable"]},"column":{"values":["col*"]}}, "policyItems":[ - {"accesses":[{"type":"select"}],"users":[],"groups":["public"],"delegateAdmin":false,"conditions":[{"type":"accessed-together","values":["default.testTable.col*"]}]}, - {"accesses":[{"type":"select"}],"users":["user2","admin"],"groups":["admin"],"delegateAdmin":false,"itemType":1} + {"accesses":[{"type":"select"}],"users":["user2", "admin"],"groups":[],"delegateAdmin":false} + ], + "denyPolicyItems":[ + {"accesses":[{"type":"select"}],"users":[],"groups":["public"],"delegateAdmin":false,"conditions":[{"type":"accessed-together","values":["default.testTable.col*"]}]} + ], + "denyExceptions":[ + {"accesses":[{"type":"select"}],"users":["user2","admin"],"groups":["admin"],"delegateAdmin":false} ] }, - {"id":2,"name":"db=default; deny select with mutual exclusion of col1, name for everone except admin","isEnabled":true,"isAuditEnabled":true,"policyType":1, + {"id":2,"name":"db=default; deny select with mutual exclusion of col1, name for everone except admin","isEnabled":true,"isAuditEnabled":true, "resources":{"database":{"values":["default"]},"table":{"values":["testTable"]},"column":{"values":["col1"]}}, "policyItems":[ - {"accesses":[{"type":"select"}],"users":[],"groups":["public"],"delegateAdmin":false,"conditions":[{"type":"accessed-together","values":["default.testTable.col1", "default.testTable.name"]}]}, - {"accesses":[{"type":"select"}],"users":["admin"],"groups":["admin"],"delegateAdmin":false,"itemType":1} + {"accesses":[{"type":"select"}],"users":["admin"],"groups":[],"delegateAdmin":false} + ], + "denyPolicyItems":[ + {"accesses":[{"type":"select"}],"users":[],"groups":["public"],"delegateAdmin":false,"conditions":[{"type":"accessed-together","values":["default.testTable.col1", "default.testTable.name"]}]} + ], + "denyExceptions":[ + {"accesses":[{"type":"select"}],"users":["admin"],"groups":[],"delegateAdmin":false} ] }, - {"id":3,"name":"db=default; allow default.testTable.* for user1, user2, admin","isEnabled":true,"isAuditEnabled":true,"policyType":0, + {"id":3,"name":"db=default; table=testTable; column=*; allow access to everyone","isEnabled":true,"isAuditEnabled":true, "resources":{"database":{"values":["default"]},"table":{"values":["testTable"]},"column":{"values":["*"]}}, "policyItems":[ - {"accesses":[{"type":"select"}],"users":["user1", "user2", "admin"],"groups":[],"delegateAdmin":false} + {"accesses":[{"type":"select"}],"users":[""],"groups":["public"],"delegateAdmin":false} ] } ], @@ -82,8 +92,9 @@ "policyId": 1 } } - , { - "name": "DENY 'select col1, name from default.testtable;' to user2", + , + { + "name": "ALLOW 'select col1, col2 from default.testtable;' to admin", "request": { "resource": { "elements": { @@ -93,23 +104,23 @@ } }, "accessType": "select", - "user": "user2", + "user": "admin", "userGroups": [ ], - "requestData": "select col1,name from default.testtable", + "requestData": "select col1,col2 from default.testtable", "context": { - "REQUESTED_RESOURCES": "{\"requestedResources\":[ {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"col1\"} }, {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"name\"} } ]}" + "REQUESTED_RESOURCES": "{\"requestedResources\":[ {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"col1\"} }, {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"col2\"} } ]}" } }, "result": { "isAudited": true, - "isAllowed": false, - "policyId": 2 + "isAllowed": true, + "policyId": 1 } } , - { - "name": "ALLOW 'select col1, col2 from default.testtable;' to admin", + { + "name": "DENY 'select col1, name from default.testtable;' to user2", "request": { "resource": { "elements": { @@ -119,22 +130,23 @@ } }, "accessType": "select", - "user": "admin", + "user": "user2", "userGroups": [ ], - "requestData": "select col1,col2 from default.testtable", + "requestData": "select col1,name from default.testtable", "context": { - "REQUESTED_RESOURCES": "{\"requestedResources\":[ {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"col1\"} }, {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"col2\"} } ]}" + "REQUESTED_RESOURCES": "{\"requestedResources\":[ {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"col1\"} }, {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"name\"} } ]}" } }, "result": { "isAudited": true, - "isAllowed": true, - "policyId": 3 + "isAllowed": false, + "policyId": 2 } } - ,{ - "name": "ALLOW 'select col2, name from default.testtable;' to user1", + , + { + "name": "ALLOW 'select col2 from default.testtable;' to user1", "request": { "resource": { "elements": { @@ -148,9 +160,9 @@ "userGroups": [ "public" ], - "requestData": "select col2,name from default.testtable", + "requestData": "select col2 from default.testtable", "context": { - "REQUESTED_RESOURCES": "{\"requestedResources\":[ {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"col2\"} }, {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"name\"} } ]}" + "REQUESTED_RESOURCES": "{\"requestedResources\":[ {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"col2\"} } ]}" } }, "result": { @@ -159,8 +171,9 @@ "policyId": 3 } } - ,{ - "name": "ALLOW 'select col2, col2 from default.testtable;' to user1", + , + { + "name": "ALLOW 'select col2, name from default.testtable;' to user1", "request": { "resource": { "elements": { @@ -174,9 +187,9 @@ "userGroups": [ "public" ], - "requestData": "select col2 from default.testtable", + "requestData": "select col2,name from default.testtable", "context": { - "REQUESTED_RESOURCES": "{\"requestedResources\":[ {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"col2\"} } ]}" + "REQUESTED_RESOURCES": "{\"requestedResources\":[ {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"col2\"} }, {\"elements\":{\"database\":\"default\",\"table\":\"testTable\",\"column\":\"name\"} } ]}" } }, "result": { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/test/resources/policyengine/test_policyengine_tag_hdfs.json ---------------------------------------------------------------------- diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_tag_hdfs.json b/agents-common/src/test/resources/policyengine/test_policyengine_tag_hdfs.json index 454cf51..ed42d5c 100644 --- a/agents-common/src/test/resources/policyengine/test_policyengine_tag_hdfs.json +++ b/agents-common/src/test/resources/policyengine/test_policyengine_tag_hdfs.json @@ -15,26 +15,6 @@ }, "policies":[ - {"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} - ] - } ], "tagPolicyInfo": { @@ -120,7 +100,7 @@ ] }, "tagPolicies":[ - {"id":101,"name":"test_policy","isEnabled":true,"isAuditEnabled":true,"policyType":1, + {"id":101,"name":"PII with expiry","isEnabled":true,"isAuditEnabled":true, "resources":{"tag":{"values":["PII"],"isRecursive":false}}, "policyItems":[ { @@ -128,29 +108,43 @@ {"type":"hdfs:read", "isAllowed":true}, {"type":"hive:grant", "isAllowed":true}, {"type":"delete", "isAllowed":true}, - {"type":":write", "isAllowed":true} + {"type":"hdfs:write", "isAllowed":true} + ], + "users":["user1"], + "groups":["finance"], + "delegateAdmin":false, + "conditions" : [] + } + ], + "denyPolicyItems":[ + { + "accesses":[ + {"type":"hdfs:read", "isAllowed":true}, + {"type":"hive:grant", "isAllowed":true}, + {"type":"delete", "isAllowed":true}, + {"type":"hdfs:write", "isAllowed":true} ], "users":[""], "groups":["public"], "delegateAdmin":false, - "itemType":0, "conditions" : [ {"type":"ScriptConditionEvaluator", "values": [ - "ctx.result = true; importPackage(java.util); var accessDate = ctx.getAsDate(ctx.accessTime); var expiryDate =ctx.getTagAttributeAsDate('pii','expiry'); expiryDate.getTime() < accessDate.getTime();" + "ctx.result = true; importPackage(java.util); var accessDate = ctx.accessTime; var expiryDate = ctx.getTagAttributeAsDate('PII','expiry_date'); expiryDate.getTime() < accessDate.getTime();" ]} ] - }, + } + ], + "denyExceptions":[ { "accesses":[ {"type":"hdfs:read", "isAllowed":true}, {"type":"hive:grant", "isAllowed":true}, {"type":"delete", "isAllowed":true}, - {"type":":write", "isAllowed":true} + {"type":"hdfs:write", "isAllowed":true} ], "users":["user1"], "groups":["finance"], "delegateAdmin":false, - "itemType":1, "conditions" : [] } ] @@ -161,10 +155,28 @@ {"name":"ALLOW 'read /finance/restricted/sales.db' for g=finance", "request":{ "resource":{"elements":{"path":"/finance/restricted/sales.db"}}, - "accessType":"read","user":"user1","userGroups":["finance"],"requestData":"read /finance/restricted/sales.db", - "context": {"TAGS":"[{\"type\":\"PII\"}]"} + "accessType":"read","user":"userx","userGroups":["finance"],"requestData":"read /finance/restricted/sales.db", + "context": {"TAGS":"[{\"type\":\"PII\",\"attributes\":{\"expiry_date\":\"2015/09/01\"}}]"} + }, + "result":{"isAudited":true,"isAllowed":true,"policyId":101} + } + , + {"name":"ALLOW 'read /finance/restricted/sales.db' for u=user1", + "request":{ + "resource":{"elements":{"path":"/finance/restricted/sales.db"}}, + "accessType":"read","user":"user1","userGroups":["employee"],"requestData":"read /finance/restricted/sales.db", + "context": {"TAGS":"[{\"type\":\"PII\",\"attributes\":{\"expiry_date\":\"2015/09/01\"}}]"} + }, + "result":{"isAudited":true,"isAllowed":true,"policyId":101} + } + , + {"name":"DENY 'read /finance/restricted/sales.db' for u=user2", + "request":{ + "resource":{"elements":{"path":"/finance/restricted/sales.db"}}, + "accessType":"read","user":"user2","userGroups":["employee"],"requestData":"read /finance/restricted/sales.db", + "context": {"TAGS":"[{\"type\":\"PII\",\"attributes\":{\"expiry_date\":\"2015/09/01\"}}]"} }, - "result":{"isAudited":true,"isAllowed":true,"policyId":3} + "result":{"isAudited":true,"isAllowed":false,"policyId":101} } ] } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive.json ---------------------------------------------------------------------- diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive.json b/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive.json index f071cdc..cb07b17 100644 --- a/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive.json +++ b/agents-common/src/test/resources/policyengine/test_policyengine_tag_hive.json @@ -153,7 +153,7 @@ ] }, "tagPolicies":[ - {"id":1,"name":"RESTRICTED_TAG_POLICY","isEnabled":true,"isAuditEnabled":true,"policyType":0, + {"id":1,"name":"RESTRICTED_TAG_POLICY","isEnabled":true,"isAuditEnabled":true, "resources":{"tag":{"values":["RESTRICTED"],"isRecursive":false}}, "policyItems":[ { @@ -165,24 +165,30 @@ } ] }, - {"id":2,"name":"PII_TAG_POLICY","isEnabled":true,"isAuditEnabled":true,"policyType":0, + {"id":2,"name":"PII_TAG_POLICY","isEnabled":true,"isAuditEnabled":true, "resources":{"tag":{"values":["PII"],"isRecursive":false}}, "policyItems":[ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["hive"],"groups":[],"delegateAdmin":false} ] }, - {"id":3,"name":"PII_TAG_POLICY-FINAL","isEnabled":true,"isAuditEnabled":true,"policyType":1, + {"id":3,"name":"PII_TAG_POLICY-FINAL","isEnabled":true,"isAuditEnabled":true, "resources":{"tag":{"values":["PII-FINAL"],"isRecursive":false}}, - "policyItems":[ - {"accesses":[{"type":"hive:select","isAllowed":true}],"users":[""],"groups":["public"],"delegateAdmin":false}, - {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["hive"],"groups":[],"delegateAdmin":false,"itemType":1} + "denyPolicyItems":[ + {"accesses":[{"type":"hive:select","isAllowed":true}],"users":[""],"groups":["public"],"delegateAdmin":false} + ] + , + "denyExceptions":[ + {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["hive"],"groups":[],"delegateAdmin":false} ] }, {"id":4,"name":"RESTRICTED_TAG_POLICY_FINAL","isEnabled":true,"isAuditEnabled":true,"policyType":1, "resources":{"tag":{"values":["RESTRICTED-FINAL"],"isRecursive":false}}, - "policyItems":[ - {"accesses":[{"type":"hive:select","isAllowed":true}],"users":[],"groups":["public"],"delegateAdmin":false}, - {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["hive", "user1"],"groups":[],"delegateAdmin":false,"itemType":1, + "denyPolicyItems":[ + {"accesses":[{"type":"hive:select","isAllowed":true}],"users":[],"groups":["public"],"delegateAdmin":false} + ] + , + "denyExceptions":[ + {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["hive", "user1"],"groups":[],"delegateAdmin":false, "conditions":[{ "type":"ScriptConditionEvaluator", "values":["if ( ctx.isAccessedBefore('expiry') ) ctx.result = true;"] @@ -190,13 +196,16 @@ } ] }, - {"id":5,"name":"EXPIRES_ON","isEnabled":true,"isAuditEnabled":true,"policyType":1, + {"id":5,"name":"EXPIRES_ON","isEnabled":true,"isAuditEnabled":true, "resources":{"tag":{"values":["EXPIRES_ON"],"isRecursive":false}}, - "policyItems":[ + "denyPolicyItems":[ {"accesses":[{"type":"hive:select","isAllowed":true}],"users":[],"groups":["public"],"delegateAdmin":false, "conditions":[{"type":"enforce-expiry","values":["yes"]}] - }, - {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["dataloader"],"groups":[],"delegateAdmin":false,"itemType":1} + } + ] + , + "denyExceptions":[ + {"accesses":[{"type":"hive:select","isAllowed":true}],"users":["dataloader"],"groups":[],"delegateAdmin":false} ] } ] http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c18f8bf7/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java index cccea3e..73a9109 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java @@ -103,6 +103,7 @@ import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef; import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper; +import org.apache.ranger.plugin.policyevaluator.RangerPolicyItemEvaluator; import org.apache.ranger.plugin.store.*; import org.apache.ranger.plugin.util.SearchFilter; import org.apache.ranger.plugin.util.ServicePolicies; @@ -1417,7 +1418,10 @@ public class ServiceDBStore extends AbstractServiceStore { } Map<String, RangerPolicyResource> resources = policy.getResources(); - List<RangerPolicyItem> policyItems = policy.getPolicyItems(); + List<RangerPolicyItem> policyItems = policy.getPolicyItems(); + List<RangerPolicyItem> denyPolicyItems = policy.getDenyPolicyItems(); + List<RangerPolicyItem> allowExceptions = policy.getAllowExceptions(); + List<RangerPolicyItem> denyExceptions = policy.getDenyExceptions(); policy.setVersion(new Long(1)); updatePolicySignature(policy); @@ -1438,7 +1442,10 @@ public class ServiceDBStore extends AbstractServiceStore { XXPolicy xCreatedPolicy = daoMgr.getXXPolicy().getById(policy.getId()); createNewResourcesForPolicy(policy, xCreatedPolicy, resources); - createNewPolicyItemsForPolicy(policy, xCreatedPolicy, policyItems, xServiceDef); + createNewPolicyItemsForPolicy(policy, xCreatedPolicy, policyItems, xServiceDef, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW); + createNewPolicyItemsForPolicy(policy, xCreatedPolicy, denyPolicyItems, xServiceDef, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY); + createNewPolicyItemsForPolicy(policy, xCreatedPolicy, allowExceptions, xServiceDef, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS); + createNewPolicyItemsForPolicy(policy, xCreatedPolicy, denyExceptions, xServiceDef, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS); handlePolicyUpdate(service); RangerPolicy createdPolicy = policyService.getPopulatedViewObject(xCreatedPolicy); dataHistService.createObjectDataHistory(createdPolicy, RangerDataHistService.ACTION_CREATE); @@ -1487,7 +1494,10 @@ public class ServiceDBStore extends AbstractServiceStore { } } Map<String, RangerPolicyResource> newResources = policy.getResources(); - List<RangerPolicyItem> newPolicyItems = policy.getPolicyItems(); + List<RangerPolicyItem> policyItems = policy.getPolicyItems(); + List<RangerPolicyItem> denyPolicyItems = policy.getDenyPolicyItems(); + List<RangerPolicyItem> allowExceptions = policy.getAllowExceptions(); + List<RangerPolicyItem> denyExceptions = policy.getDenyExceptions(); List<XXTrxLog> trxLogList = policyService.getTransactionLog(policy, xxExisting, RangerPolicyService.OPERATION_UPDATE_CONTEXT); @@ -1509,7 +1519,10 @@ public class ServiceDBStore extends AbstractServiceStore { deleteExistingPolicyItems(policy); createNewResourcesForPolicy(policy, newUpdPolicy, newResources); - createNewPolicyItemsForPolicy(policy, newUpdPolicy, newPolicyItems, xServiceDef); + createNewPolicyItemsForPolicy(policy, newUpdPolicy, policyItems, xServiceDef, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW); + createNewPolicyItemsForPolicy(policy, newUpdPolicy, denyPolicyItems, xServiceDef, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY); + createNewPolicyItemsForPolicy(policy, newUpdPolicy, allowExceptions, xServiceDef, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS); + createNewPolicyItemsForPolicy(policy, newUpdPolicy, denyExceptions, xServiceDef, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS); handlePolicyUpdate(service); RangerPolicy updPolicy = policyService.getPopulatedViewObject(newUpdPolicy); @@ -1831,7 +1844,6 @@ public class ServiceDBStore extends AbstractServiceStore { policy.setService(createdService.getName()); policy.setDescription(tagType + " Policy for TAG Service: " + createdService.getName()); policy.setIsAuditEnabled(true); - policy.setPolicyType(RangerPolicy.POLICY_TYPE_DENY); Map<String, RangerPolicyResource> resourceMap = new HashMap<String, RangerPolicyResource>(); @@ -1872,7 +1884,7 @@ public class ServiceDBStore extends AbstractServiceStore { policyItems.add(policyItem); - policy.setPolicyItems(policyItems); + policy.setDenyPolicyItems(policyItems); policy = createPolicy(policy); } else { @@ -2026,7 +2038,7 @@ public class ServiceDBStore extends AbstractServiceStore { } } - private void createNewPolicyItemsForPolicy(RangerPolicy policy, XXPolicy xPolicy, List<RangerPolicyItem> policyItems, XXServiceDef xServiceDef) throws Exception { + private void createNewPolicyItemsForPolicy(RangerPolicy policy, XXPolicy xPolicy, List<RangerPolicyItem> policyItems, XXServiceDef xServiceDef, int policyItemType) throws Exception { for (int itemOrder = 0; itemOrder < policyItems.size(); itemOrder++) { RangerPolicyItem policyItem = policyItems.get(itemOrder); @@ -2034,7 +2046,7 @@ public class ServiceDBStore extends AbstractServiceStore { xPolicyItem = (XXPolicyItem) rangerAuditFields.populateAuditFields( xPolicyItem, xPolicy); xPolicyItem.setDelegateAdmin(policyItem.getDelegateAdmin()); - xPolicyItem.setItemType(policyItem.getItemType()); + xPolicyItem.setItemType(policyItemType); xPolicyItem.setPolicyId(policy.getId()); xPolicyItem.setOrder(itemOrder); xPolicyItem = daoMgr.getXXPolicyItem().create(xPolicyItem);
