Repository: incubator-ranger Updated Branches: refs/heads/master 89002025e -> c5f61c898
RANGER-546: fix to custom conditions evaluation Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/c5f61c89 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/c5f61c89 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/c5f61c89 Branch: refs/heads/master Commit: c5f61c898244aa436997990df19778766b0db295 Parents: 8900202 Author: Madhan Neethiraj <[email protected]> Authored: Wed Jun 10 16:00:00 2015 -0700 Committer: Madhan Neethiraj <[email protected]> Committed: Wed Jun 10 21:33:52 2015 -0700 ---------------------------------------------------------------------- .../conditionevaluator/RangerSimpleMatcher.java | 10 +- .../RangerAbstractPolicyEvaluator.java | 15 +- .../RangerAbstractPolicyItemEvaluator.java | 61 +++ .../RangerDefaultPolicyEvaluator.java | 387 +++---------------- .../RangerDefaultPolicyItemEvaluator.java | 273 +++++++++++++ .../RangerOptimizedPolicyEvaluator.java | 4 +- .../policyevaluator/RangerPolicyEvaluator.java | 7 +- .../RangerPolicyItemEvaluator.java | 55 +++ .../plugin/policyengine/TestPolicyEngine.java | 7 + .../RangerDefaultPolicyEvaluatorTest.java | 256 ------------ .../test_policyengine_conditions.json | 230 +++++++++++ .../policyengine/test_policyengine_hbase.json | 2 +- 12 files changed, 707 insertions(+), 600 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcher.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcher.java index 48f806d..d9f6158 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcher.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcher.java @@ -82,15 +82,13 @@ public class RangerSimpleMatcher extends RangerAbstractConditionEvaluator { LOG.debug("==> RangerSimpleMatcher.isMatched(" + request + ")"); } - boolean matched = true; + boolean matched = false; + if (_allowAny) { - LOG.debug("isMatched: allowAny flag is true. Matched!"); + matched = true; } else { String requestValue = extractValue(request, _contextName); - if (requestValue == null) { - LOG.debug("isMatched: couldn't get value from request. Ok. Implicitly matched!"); - } else { - matched = false; + if (StringUtils.isNotBlank(requestValue)) { for (String policyValue : _values) { if (FilenameUtils.wildcardMatch(requestValue, policyValue)) { matched = true; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/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 85e69f1..178b9d8 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 @@ -20,11 +20,9 @@ package org.apache.ranger.plugin.policyevaluator; -import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator; import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; @@ -68,6 +66,11 @@ public abstract class RangerAbstractPolicyEvaluator implements RangerPolicyEvalu } @Override + public boolean isAuditEnabled() { + return policy != null && policy.getIsAuditEnabled(); + } + + @Override public int compareTo(RangerPolicyEvaluator other) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerAbstractPolicyEvaluator.compareTo()"); @@ -76,13 +79,7 @@ public abstract class RangerAbstractPolicyEvaluator implements RangerPolicyEvalu int result = Integer.compare(this.getEvalOrder(), other.getEvalOrder()); if (result == 0) { - Map<String, RangerConditionEvaluator> myConditionEvaluators = this.getConditionEvaluators(); - Map<String, RangerConditionEvaluator> otherConditionEvaluators = other.getConditionEvaluators(); - - int myConditionEvaluatorCount = myConditionEvaluators == null ? 0 : myConditionEvaluators.size(); - int otherConditionEvaluatorCount = otherConditionEvaluators == null ? 0 : otherConditionEvaluators.size(); - - result = Integer.compare(myConditionEvaluatorCount, otherConditionEvaluatorCount); + result = Integer.compare(getCustomConditionsCount(), other.getCustomConditionsCount()); } if(LOG.isDebugEnabled()) { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/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 new file mode 100644 index 0000000..a986ca6 --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.ranger.plugin.policyevaluator; + + +import java.util.Collections; +import java.util.List; + +import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; + + +public abstract class RangerAbstractPolicyItemEvaluator implements RangerPolicyItemEvaluator { + final RangerPolicyEngineOptions options; + final RangerServiceDef serviceDef; + final RangerPolicy policy; + final RangerPolicyItem policyItem; + final long policyId; + + List<RangerConditionEvaluator> conditionEvaluators = Collections.<RangerConditionEvaluator>emptyList(); + + RangerAbstractPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, RangerPolicyEngineOptions options) { + this.serviceDef = serviceDef; + this.policy = policy; + this.policyItem = policyItem; + this.options = options; + this.policyId = policy != null && policy.getId() != null ? policy.getId() : -1; + } + + @Override + public List<RangerConditionEvaluator> getConditionEvaluators() { + return conditionEvaluators; + } + + protected String getServiceType() { + return serviceDef != null ? serviceDef.getName() : null; + } + + protected boolean getConditionsDisabledOption() { + return options != null ? options.disableCustomConditions : false; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/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 9233f8d..030cd87 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 @@ -19,11 +19,12 @@ package org.apache.ranger.plugin.policyevaluator; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; @@ -31,31 +32,31 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator; import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess; -import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef; -import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.policyengine.RangerAccessResource; import org.apache.ranger.plugin.policyengine.RangerAccessResult; -import org.apache.ranger.plugin.policyengine.RangerPolicyEngine; import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; import org.apache.ranger.plugin.policyresourcematcher.RangerDefaultPolicyResourceMatcher; import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher; -import com.google.common.base.Strings; - public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator { private static final Log LOG = LogFactory.getLog(RangerDefaultPolicyEvaluator.class); - private RangerPolicyResourceMatcher resourceMatcher = null; - private Map<String, RangerConditionEvaluator> conditionEvaluators = null; + private RangerPolicyResourceMatcher resourceMatcher = null; + private List<RangerPolicyItemEvaluator> policyItemEvaluators = null; + private int customConditionsCount = 0; + + @Override + public int getCustomConditionsCount() { + return customConditionsCount; + } @Override public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options) { @@ -72,131 +73,28 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator resourceMatcher.setServiceDef(serviceDef); resourceMatcher.setPolicyResources(policy == null ? null : policy.getResources()); resourceMatcher.init(); + + if(policy != null && CollectionUtils.isNotEmpty(policy.getPolicyItems())) { + policyItemEvaluators = new ArrayList<RangerPolicyItemEvaluator>(); - if(options.disableCustomConditions) { - conditionEvaluators = Collections.<String, RangerConditionEvaluator>emptyMap(); - } else { - conditionEvaluators = initializeConditionEvaluators(policy, serviceDef); - } - - if(LOG.isDebugEnabled()) { - LOG.debug("<== RangerDefaultPolicyEvaluator.init()"); - } - } - - @Override - public Map<String, RangerConditionEvaluator> getConditionEvaluators() { - return conditionEvaluators; - } + for(RangerPolicyItem policyItem : policy.getPolicyItems()) { + RangerPolicyItemEvaluator itemEvaluator = new RangerDefaultPolicyItemEvaluator(serviceDef, policy, policyItem, options); - /** - * Non-private only for testability. - * @param policy - * @param serviceDef - * @return a Map of condition name to a new evaluator object of the class configured in service definition for that condition name - */ - Map<String, RangerConditionEvaluator> initializeConditionEvaluators(RangerPolicy policy, RangerServiceDef serviceDef) { - if(LOG.isDebugEnabled()) { - LOG.debug(String.format("==> RangerDefaultPolicyEvaluator.initializeConditionEvaluators(%s, %s)", policy, serviceDef)); - } + itemEvaluator.init(); - Map<String, RangerConditionEvaluator> result = new HashMap<String, RangerConditionEvaluator>(); - if (policy == null) { - LOG.debug("initializeConditionEvaluators: Policy is null!"); - } else if (CollectionUtils.isEmpty(policy.getPolicyItems())) { - LOG.debug("initializeConditionEvaluators: Policyitems collection null or empty!"); - } else { - for (RangerPolicyItem item : policy.getPolicyItems()) { - if (CollectionUtils.isEmpty(item.getConditions())) { - if (LOG.isDebugEnabled()) { - LOG.debug(String.format("initializeConditionEvaluators: null or empty condition collection on policy item[%s]. Ok, skipping", item)); - } - } else { - for (RangerPolicyItemCondition condition : item.getConditions()) { - String conditionName = condition.getType(); - // skip it if we have already processed this condition earlier - if (result.containsKey(conditionName)) { - continue; - } - RangerPolicyConditionDef conditionDef = getConditionDef(serviceDef, conditionName); - if (conditionDef == null) { - LOG.error("initializeConditionEvaluators: Serious Configuration error: Couldn't get condition Definition for condition[" + conditionName + "]! Disabling all checks for this condition."); - } else { - String evaluatorClassName = conditionDef.getEvaluator(); - if (Strings.isNullOrEmpty(evaluatorClassName)) { - LOG.error("initializeConditionEvaluators: Serious Configuration error: Couldn't get condition evaluator class name for condition[" + conditionName + "]! Disabling all checks for this condition."); - } else { - RangerConditionEvaluator anEvaluator = newConditionEvaluator(evaluatorClassName); - if (anEvaluator == null) { - LOG.error("initializeConditionEvaluators: Serious Configuration error: Couldn't instantiate condition evaluator for class[" + evaluatorClassName + "]. All checks for condition[" + conditionName + "] disabled."); - } else { - anEvaluator.setConditionDef(conditionDef); - anEvaluator.setPolicyItemCondition(condition); - anEvaluator.init(); - result.put(conditionName, anEvaluator); - } - } - } - } + policyItemEvaluators.add(itemEvaluator); + + if(CollectionUtils.isNotEmpty(itemEvaluator.getConditionEvaluators())) { + customConditionsCount += itemEvaluator.getConditionEvaluators().size(); } } - } - - if(LOG.isDebugEnabled()) { - LOG.debug(String.format("<== RangerDefaultPolicyEvaluator.initializeConditionEvaluators(%s)", result.toString())); - } - return result; - } - - RangerPolicyConditionDef getConditionDef(RangerServiceDef serviceDef, String conditionName) { - if(LOG.isDebugEnabled()) { - LOG.debug(String.format("==> RangerDefaultPolicyEvaluator.initializeConditionEvaluators(%s, %s)", serviceDef, conditionName)); - } - - RangerPolicyConditionDef result = null; - if (Strings.isNullOrEmpty(conditionName)) { - LOG.debug("initializeConditionEvaluators: Condition name was null or empty!"); - } - else if (serviceDef == null) { - LOG.debug("initializeConditionEvaluators: Servicedef was null!"); - } else if (CollectionUtils.isEmpty(serviceDef.getPolicyConditions())) { - LOG.debug("initializeConditionEvaluators: Policy conditions collection of the service def is empty! Ok, skipping."); } else { - Iterator<RangerPolicyConditionDef> iterator = serviceDef.getPolicyConditions().iterator(); - while (iterator.hasNext() && result == null) { - RangerPolicyConditionDef conditionDef = iterator.next(); - String name = conditionDef.getName(); - if (conditionName.equals(name)) { - result = conditionDef; - } - } - } - - if(LOG.isDebugEnabled()) { - LOG.debug(String.format("<== RangerDefaultPolicyEvaluator.initializeConditionEvaluators(%s -> %s)", conditionName, result)); + policyItemEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList(); } - return result; - } - RangerConditionEvaluator newConditionEvaluator(String className) { if(LOG.isDebugEnabled()) { - LOG.debug(String.format("==> RangerDefaultPolicyEvaluator.newConditionEvaluator(%s)", className)); - } - - RangerConditionEvaluator evaluator = null; - try { - @SuppressWarnings("unchecked") - Class<RangerConditionEvaluator> matcherClass = (Class<RangerConditionEvaluator>)Class.forName(className); - - evaluator = matcherClass.newInstance(); - } catch(Throwable t) { - LOG.error("Caught Throwable: unexpected error instantiating object of class[" + className + "]. Returning null!", t); - } - - if(LOG.isDebugEnabled()) { - LOG.debug(String.format("<== RangerDefaultPolicyEvaluator.newConditionEvaluator(%s)", evaluator == null ? null : evaluator.toString())); + LOG.debug("<== RangerDefaultPolicyEvaluator.init()"); } - return evaluator; } @Override @@ -204,13 +102,12 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator if (LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyEvaluator.evaluate(" + request + ", " + result + ")"); } - RangerPolicy policy = getPolicy(); - if (policy != null && request != null && result != null) { - boolean isMatchAttempted = false; - boolean matchResult = false; + if (request != null && result != null) { + boolean isMatchAttempted = false; + boolean matchResult = false; boolean isHeadMatchAttempted = false; - boolean headMatchResult = false; + boolean headMatchResult = false; if (!result.getIsAuditedDetermined()) { // Need to match request.resource first. If it matches (or head matches), then only more progress can be made @@ -229,7 +126,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator if (matchResult || headMatchResult) { // We are done for determining if audit is needed for this policy - if (policy.getIsAuditEnabled()) { + if (isAuditEnabled()) { result.setIsAudited(true); } } @@ -252,7 +149,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator } // Go further to evaluate access only if match or head match was found at this point if (matchResult || headMatchResult) { - evaluatePolicyItemsForAccess(policy, request, result); + evaluatePolicyItemsForAccess(request, result); } } } @@ -262,63 +159,21 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator } } - protected void evaluatePolicyItemsForAccess(RangerPolicy policy, RangerAccessRequest request, RangerAccessResult result) { + protected void evaluatePolicyItemsForAccess(RangerAccessRequest request, RangerAccessResult result) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyEvaluator.evaluatePolicyItemsForAccess(" + request + ", " + result + ")"); } - for (RangerPolicy.RangerPolicyItem policyItem : policy.getPolicyItems()) { - - boolean isUserGroupMatch = matchUserGroup(policyItem, request.getUser(), request.getUserGroups()); - - if (!isUserGroupMatch) { - continue; - } - // This is only for Grant and Revoke access requests sent by the component. For those cases - // Our plugin will fill in the accessType as ADMIN_ACCESS. - - if (request.isAccessTypeDelegatedAdmin()) { - if (policyItem.getDelegateAdmin()) { - result.setIsAllowed(true); - result.setPolicyId(policy.getId()); - break; - } - continue; - } - - if (CollectionUtils.isEmpty(policyItem.getAccesses())) { - continue; - } - - boolean accessAllowed = false; - if (request.isAccessTypeAny()) { - for (RangerPolicy.RangerPolicyItemAccess access : policyItem.getAccesses()) { - if (access.getIsAllowed()) { - accessAllowed = true; - break; - } - } - } else { - RangerPolicy.RangerPolicyItemAccess access = getAccess(policyItem, request.getAccessType()); - - if (access != null && access.getIsAllowed()) { - accessAllowed = true; - } - } - if (accessAllowed == false) { - continue; - } - - boolean isCustomConditionsMatch = matchCustomConditions(policyItem, request, getConditionEvaluators()); + if(CollectionUtils.isNotEmpty(policyItemEvaluators) && !result.getIsAccessDetermined()) { + for (RangerPolicyItemEvaluator policyItemEvaluator : policyItemEvaluators) { + policyItemEvaluator.evaluate(request, result); - if (!isCustomConditionsMatch) { - continue; - } - - result.setIsAllowed(true); - result.setPolicyId(getPolicy().getId()); - break; + if(result.getIsAccessDetermined()) { + break; + } + } } + if(LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyEvaluator.evaluatePolicyItemsForAccess(" + request + ", " + result + ")"); } @@ -411,102 +266,6 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator return ret; } - protected boolean matchUserGroup(RangerPolicyItem policyItem, String user, Collection<String> groups) { - if(LOG.isDebugEnabled()) { - LOG.debug("==> RangerDefaultPolicyEvaluator.matchUserGroup(" + policyItem + ", " + user + ", " + groups + ")"); - } - - boolean ret = false; - - if(policyItem != null) { - if(!ret && user != null && policyItem.getUsers() != null) { - ret = policyItem.getUsers().contains(user); - } - - if(!ret && groups != null && policyItem.getGroups() != null) { - ret = policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC) || - !Collections.disjoint(policyItem.getGroups(), groups); - } - } - - if(LOG.isDebugEnabled()) { - LOG.debug("<== RangerDefaultPolicyEvaluator.matchUserGroup(" + policyItem + ", " + user + ", " + groups + "): " + ret); - } - - return ret; - } - - // takes map in as argument for testability - protected boolean matchCustomConditions(RangerPolicyItem policyItem, RangerAccessRequest request, Map<String, RangerConditionEvaluator> evaluatorMap) { - if(LOG.isDebugEnabled()) { - LOG.debug("==> RangerDefaultPolicyEvaluator.matchCustomConditions(" + request + ")"); - } - - boolean result = true; - if (policyItem == null) { - LOG.debug("matchCustomConditions: Unexpected: policyItem was null"); - } else if (CollectionUtils.isEmpty(policyItem.getConditions())) { - LOG.debug("matchCustomConditions: policy item does not have any conditions! Ok, implicitly passed."); - } else { - Iterator<RangerPolicyItemCondition> iterator = policyItem.getConditions().iterator(); - /* - * We need to let the request be evaluated by the condition evaluator for each condition on the policy item. - * We bail out as soon as we find a mismatch, i.e. ALL conditions must succeed for condition evaluation to return true. - */ - boolean matched = true; - while (iterator.hasNext() && matched) { - RangerPolicyItemCondition itemCondition = iterator.next(); - if (itemCondition == null) { - LOG.debug("matchCustomConditions: Unexpected: Item condition on policy item was null! Ignoring..."); - } else { - String conditionName = itemCondition.getType(); - if (StringUtils.isBlank(conditionName)) { - LOG.debug("matchCustomConditions: Unexpected: condition name on item conditon [" + conditionName + "] was null/empty/blank! Ignoring..."); - } else if (!evaluatorMap.containsKey(conditionName)) { - LOG.warn("matchCustomConditions: Unexpected: Could not find condition evaluator for condition[" + conditionName + "]! Ignoring..."); - } else { - RangerConditionEvaluator conditionEvaluator = evaluatorMap.get(conditionName); - matched = conditionEvaluator.isMatched(request); - if (LOG.isDebugEnabled()) { - LOG.debug(String.format("matchCustomConditions: evaluator for condition[%s] returned[%s] for request[%s]", conditionName, matched, request)); - } - } - } - } - result = result && matched; - } - - if(LOG.isDebugEnabled()) { - LOG.debug("<== RangerDefaultPolicyEvaluator.matchCustomConditions(" + request + "): " + result); - } - - return result; - } - - protected RangerPolicyItemAccess getAccess(RangerPolicyItem policyItem, String accessType) { - if(LOG.isDebugEnabled()) { - LOG.debug("==> RangerDefaultPolicyEvaluator.getAccess(" + policyItem + ", " + accessType + ")"); - } - - RangerPolicyItemAccess ret = null; - - if(policyItem != null && accessType != null && policyItem.getAccesses() != null) { - for(RangerPolicyItemAccess access : policyItem.getAccesses()) { - if(StringUtils.equalsIgnoreCase(accessType, access.getType())) { - ret = access; - - break; - } - } - } - - if(LOG.isDebugEnabled()) { - LOG.debug("<== RangerDefaultPolicyEvaluator.getAccess(" + policyItem + ", " + accessType + "): " + ret); - } - - return ret; - } - protected boolean isMatch(Map<String, RangerPolicyResource> resources) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resources + ")"); @@ -532,52 +291,15 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator boolean ret = false; - RangerPolicy policy = getPolicy(); - - if(policy != null) { - if (StringUtils.isEmpty(accessType)) { - accessType = RangerPolicyEngine.ANY_ACCESS; - } - - boolean isAnyAccess = StringUtils.equals(accessType, RangerPolicyEngine.ANY_ACCESS); - boolean isAdminAccess = StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS); - - for (RangerPolicy.RangerPolicyItem policyItem : policy.getPolicyItems()) { - if (isAdminAccess) { - if(! policyItem.getDelegateAdmin()) { - continue; - } - } else if (CollectionUtils.isEmpty(policyItem.getAccesses())) { - continue; - } else if (isAnyAccess) { - boolean accessAllowed = false; - - for (RangerPolicy.RangerPolicyItemAccess access : policyItem.getAccesses()) { - if (access.getIsAllowed()) { - accessAllowed = true; - break; - } - } + if(CollectionUtils.isNotEmpty(policyItemEvaluators)) { + for (RangerPolicyItemEvaluator policyItemEvaluator : policyItemEvaluators) { + ret = policyItemEvaluator.matchUserGroup(user, userGroups) && + policyItemEvaluator.matchAccessType(accessType); - if(! accessAllowed) { - continue; - } - } else { - RangerPolicy.RangerPolicyItemAccess access = getAccess(policyItem, accessType); - if (access == null || !access.getIsAllowed()) { - continue; - } - } - - boolean isUserGroupMatch = matchUserGroup(policyItem, user, userGroups); - - if (!isUserGroupMatch) { - continue; - } - - ret = true; - break; - } + if(ret) { + break; + } + } } if(LOG.isDebugEnabled()) { @@ -675,4 +397,23 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator return ret; } + + private RangerPolicyItemAccess getAccess(RangerPolicyItem policyItem, String accessType) { + RangerPolicyItemAccess ret = null; + + if(policyItem != null && CollectionUtils.isNotEmpty(policyItem.getAccesses())) { + for(RangerPolicyItemAccess itemAccess : policyItem.getAccesses()) { + if(StringUtils.equalsIgnoreCase(itemAccess.getType(), accessType)) { + ret = itemAccess; + + break; + } + } + } + + return ret; + } } + + + http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/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 new file mode 100644 index 0000000..bf9b243 --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java @@ -0,0 +1,273 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.ranger.plugin.policyevaluator; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Set; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef; +import org.apache.ranger.plugin.policyengine.RangerAccessRequest; +import org.apache.ranger.plugin.policyengine.RangerAccessResult; +import org.apache.ranger.plugin.policyengine.RangerPolicyEngine; +import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; + + +public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEvaluator { + 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 void init() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator(policyId=" + policyId + ", policyItem=" + policyItem + ", serviceType=" + getServiceType() + ", conditionsDisabled=" + getConditionsDisabledOption() + ")"); + } + + if (!getConditionsDisabledOption() && policyItem != null && CollectionUtils.isNotEmpty(policyItem.getConditions())) { + conditionEvaluators = new ArrayList<RangerConditionEvaluator>(); + + for (RangerPolicyItemCondition condition : policyItem.getConditions()) { + RangerPolicyConditionDef conditionDef = getConditionDef(condition.getType()); + + if (conditionDef == null) { + LOG.error("RangerDefaultPolicyItemEvaluator(policyId=" + policyId + "): conditionDef '" + condition.getType() + "' not found. Ignoring the condition"); + + continue; + } + + RangerConditionEvaluator conditionEvaluator = newConditionEvaluator(conditionDef.getEvaluator()); + + if (conditionEvaluator != null) { + conditionEvaluator.setConditionDef(conditionDef); + conditionEvaluator.setPolicyItemCondition(condition); + conditionEvaluator.init(); + + conditionEvaluators.add(conditionEvaluator); + } else { + LOG.error("RangerDefaultPolicyItemEvaluator(policyId=" + policyId + "): failed to instantiate condition evaluator '" + condition.getType() + "'; evaluatorClassName='" + conditionDef.getEvaluator() + "'"); + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator(policyId=" + policyId + ", conditionsCount=" + getConditionEvaluators().size() + ")"); + } + } + + @Override + public void evaluate(RangerAccessRequest request, RangerAccessResult result) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.evaluate(" + request + ", " + result + ")"); + } + + if(policyItem != null) { + if(matchUserGroup(request.getUser(), request.getUserGroups())) { + if (request.isAccessTypeDelegatedAdmin()) { // used only in grant/revoke scenario + if (policyItem.getDelegateAdmin()) { + result.setIsAllowed(true); + result.setPolicyId(policyId); + } + } else if (CollectionUtils.isNotEmpty(policyItem.getAccesses())) { + boolean accessAllowed = false; + + if (request.isAccessTypeAny()) { + for (RangerPolicy.RangerPolicyItemAccess access : policyItem.getAccesses()) { + if (access.getIsAllowed()) { + accessAllowed = true; + break; + } + } + } else { + for (RangerPolicy.RangerPolicyItemAccess access : policyItem.getAccesses()) { + if (access.getIsAllowed() && StringUtils.equalsIgnoreCase(access.getType(), request.getAccessType())) { + accessAllowed = true; + break; + } + } + } + + if(accessAllowed) { + if(matchCustomConditions(request)) { + result.setIsAllowed(true); + result.setPolicyId(policyId); + } + } + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.evaluate(" + request + ", " + result + ")"); + } + } + + @Override + public boolean matchUserGroup(String user, Set<String> userGroups) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchUserGroup(" + policyItem + ", " + user + ", " + userGroups + ")"); + } + + boolean ret = false; + + if(policyItem != null) { + if(!ret && user != null && policyItem.getUsers() != null) { + ret = policyItem.getUsers().contains(user); + } + + if(!ret && userGroups != null && policyItem.getGroups() != null) { + ret = policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC) || + !Collections.disjoint(policyItem.getGroups(), userGroups); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchUserGroup(" + policyItem + ", " + user + ", " + userGroups + "): " + ret); + } + + return ret; + } + + @Override + public boolean matchAccessType(String accessType) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchAccessType(" + accessType + ")"); + } + + boolean ret = false; + + if(policyItem != null) { + boolean isAdminAccess = StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS); + + if(isAdminAccess) { + ret = policyItem.getDelegateAdmin(); + } else { + if(CollectionUtils.isNotEmpty(policyItem.getAccesses())) { + boolean isAnyAccess = StringUtils.equals(accessType, RangerPolicyEngine.ANY_ACCESS); + + for(RangerPolicyItemAccess itemAccess : policyItem.getAccesses()) { + if(! itemAccess.getIsAllowed()) { + continue; + } + + if(isAnyAccess) { + ret = true; + + break; + } else if(StringUtils.equalsIgnoreCase(itemAccess.getType(), accessType)) { + ret = true; + + break; + } + } + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchAccessType(" + accessType + "): " + ret); + } + + return ret; + } + + @Override + public boolean matchCustomConditions(RangerAccessRequest request) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchCustomConditions(" + request + ")"); + } + + boolean ret = true; + + if (CollectionUtils.isNotEmpty(conditionEvaluators)) { + for(RangerConditionEvaluator conditionEvaluator : conditionEvaluators) { + if(!conditionEvaluator.isMatched(request)) { + ret = false; + + break; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchCustomConditions(" + request + "): " + ret); + } + + return ret; + } + + RangerPolicyConditionDef getConditionDef(String conditionName) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.getConditionDef(" + conditionName + ")"); + } + + RangerPolicyConditionDef ret = null; + + if (serviceDef != null && CollectionUtils.isNotEmpty(serviceDef.getPolicyConditions())) { + for(RangerPolicyConditionDef conditionDef : serviceDef.getPolicyConditions()) { + if(StringUtils.equals(conditionName, conditionDef.getName())) { + ret = conditionDef; + + break; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.getConditionDef(" + conditionName + "): " + ret); + } + + return ret; + } + + RangerConditionEvaluator newConditionEvaluator(String className) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.newConditionEvaluator(" + className + ")"); + } + + RangerConditionEvaluator evaluator = null; + + try { + @SuppressWarnings("unchecked") + Class<RangerConditionEvaluator> matcherClass = (Class<RangerConditionEvaluator>)Class.forName(className); + + evaluator = matcherClass.newInstance(); + } catch(Throwable t) { + LOG.error("RangerDefaultPolicyItemEvaluator.newConditionEvaluator(" + className + "): error instantiating evaluator"); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.newConditionEvaluator(" + className + "): " + evaluator); + } + + return evaluator; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/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 26d5223..4abc1bf 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 @@ -231,7 +231,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator } @Override - protected void evaluatePolicyItemsForAccess(RangerPolicy policy, RangerAccessRequest request, RangerAccessResult result) { + protected void evaluatePolicyItemsForAccess(RangerAccessRequest request, RangerAccessResult result) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerOptimizedPolicyEvaluator.evaluatePolicyItemsForAccess()"); } @@ -241,7 +241,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator if (request.isAccessTypeAny() || (request.isAccessTypeDelegatedAdmin() && delegateAdmin) || hasAllPerms || accessPerms.contains(request.getAccessType())) { // No need to reject based on aggregated access permissions - super.evaluatePolicyItemsForAccess(policy, request, result); + super.evaluatePolicyItemsForAccess(request, result); } } if(LOG.isDebugEnabled()) { http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/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 9fe523a..624ff1c 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 @@ -23,7 +23,6 @@ package org.apache.ranger.plugin.policyevaluator; import java.util.Map; import java.util.Set; -import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator; import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; import org.apache.ranger.plugin.model.RangerServiceDef; @@ -43,10 +42,12 @@ public interface RangerPolicyEvaluator extends Comparable<RangerPolicyEvaluator> RangerServiceDef getServiceDef(); - Map<String, RangerConditionEvaluator> getConditionEvaluators(); - int getEvalOrder(); + int getCustomConditionsCount(); + + boolean isAuditEnabled(); + void evaluate(RangerAccessRequest request, RangerAccessResult result); boolean isMatch(RangerAccessResource resource); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/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 new file mode 100644 index 0000000..9bbe4e3 --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.ranger.plugin.policyevaluator; + +import java.util.List; +import java.util.Set; + +import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator; +import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.ranger.plugin.policyengine.RangerAccessRequest; +import org.apache.ranger.plugin.policyengine.RangerAccessResult; + +public interface RangerPolicyItemEvaluator { + + void init(); + + /* + RangerServiceDef getServiceDef(); + + RangerPolicy getPolicy(); + + RangerPolicyItem getPolicyItem(); + + long getPolicyId(); + */ + + List<RangerConditionEvaluator> getConditionEvaluators(); + + + void evaluate(RangerAccessRequest request, RangerAccessResult result); + + boolean matchUserGroup(String user, Set<String> userGroups); + + boolean matchAccessType(String accessType); + + boolean matchCustomConditions(RangerAccessRequest request); +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java ---------------------------------------------------------------------- diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java index 38b7302..59b7479 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java @@ -81,6 +81,13 @@ public class TestPolicyEngine { runTestsFromResourceFiles(hbaseTestResourceFiles); } + @Test + public void testPolicyEngine_conditions() { + String[] conditionsTestResourceFiles = { "/policyengine/test_policyengine_conditions.json" }; + + runTestsFromResourceFiles(conditionsTestResourceFiles); + } + private void runTestsFromResourceFiles(String[] resourceNames) { for(String resourceName : resourceNames) { InputStream inStream = this.getClass().getResourceAsStream(resourceName); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluatorTest.java ---------------------------------------------------------------------- diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluatorTest.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluatorTest.java index 943b76a..9a3333c 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluatorTest.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluatorTest.java @@ -20,23 +20,14 @@ package org.apache.ranger.plugin.policyevaluator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.ranger.plugin.conditionevaluator.RangerAbstractConditionEvaluator; -import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator; -import org.apache.ranger.plugin.conditionevaluator.RangerIpMatcher; import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition; @@ -45,9 +36,7 @@ import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.junit.After; import org.junit.Before; -import org.junit.Test; -import com.google.common.collect.Lists; public class RangerDefaultPolicyEvaluatorTest { @@ -58,251 +47,6 @@ public class RangerDefaultPolicyEvaluatorTest { @After public void tearDown() throws Exception { } - - @Test - public void test_newConditionEvaulator() { - RangerDefaultPolicyEvaluator evaluator = new RangerDefaultPolicyEvaluator(); - RangerConditionEvaluator ipMatcher = evaluator.newConditionEvaluator("org.apache.ranger.plugin.conditionevaluator.RangerIpMatcher"); - assertTrue(ipMatcher.getClass().equals(RangerIpMatcher.class)); - - // bogus value will lead to null object from coming back - ipMatcher = evaluator.newConditionEvaluator("org.apache.ranger.plugin.conditionevaluator.RangerIpMatcha"); - assertNull(ipMatcher); - ipMatcher = evaluator.newConditionEvaluator("RangerIpMatcher"); - assertNull(ipMatcher); - } - - @Test - public void test_getConditionEvaluator() { - - // null service def and/or policy has reasonable response - RangerDefaultPolicyEvaluator evaluator = new RangerDefaultPolicyEvaluator(); - RangerPolicyConditionDef conditionDef = evaluator.getConditionDef(null, null); - assertNull(conditionDef); - - conditionDef = evaluator.getConditionDef(null, "aCondition"); - assertNull(conditionDef); - - RangerServiceDef serviceDef = mock(RangerServiceDef.class); - conditionDef = evaluator.getConditionDef(null, null); - assertNull(conditionDef); - - // null policy condition def collection should behave sensibly - when(serviceDef.getPolicyConditions()).thenReturn(null); - conditionDef = evaluator.getConditionDef(serviceDef, "aCondition"); - assertNull(conditionDef); - - // so should an service def with empty list of policy conditions. - when(serviceDef.getPolicyConditions()).thenReturn(new ArrayList<RangerServiceDef.RangerPolicyConditionDef>()); - conditionDef = evaluator.getConditionDef(serviceDef, "aCondition"); - assertNull(conditionDef); - - // if service has a condition then sensible answer should come back - RangerPolicyConditionDef aConditionDef = getMockPolicyConditionDef("type1", "com.company.SomeEvaluator", null); - - Map<String, String> evaluatorOptions = new HashMap<String, String>(); - evaluatorOptions.put("key1", "key1"); - - RangerPolicyConditionDef anotherConditionDef = getMockPolicyConditionDef("type2", "com.company.AnotherEvaluator", evaluatorOptions); - List<RangerPolicyConditionDef> conditionDefs = Lists.newArrayList(aConditionDef, anotherConditionDef); - - serviceDef = getMockServiceDef(conditionDefs); - conditionDef = evaluator.getConditionDef(serviceDef, "type1"); - assertEquals(aConditionDef, conditionDef); - conditionDef = evaluator.getConditionDef(serviceDef, "type2"); - assertEquals(anotherConditionDef, conditionDef); - conditionDef = evaluator.getConditionDef(serviceDef, "type3"); - assertNull(conditionDef); - } - - @Test - public void test_initializeConditionEvaluators_firewalling() { - RangerServiceDef serviceDef = null; - RangerPolicy policy = null; - // passing null values should yield sensible response - RangerDefaultPolicyEvaluator policyEvaluator = new RangerDefaultPolicyEvaluator(); - Map<String, RangerConditionEvaluator> result = policyEvaluator.initializeConditionEvaluators(policy, serviceDef); - assertNotNull(result); - assertTrue(result.isEmpty()); - - // or if is the policy item collection in the policy is null - policy = mock(RangerPolicy.class); - when(policy.getPolicyItems()).thenReturn(null); - result = policyEvaluator.initializeConditionEvaluators(policy, serviceDef); - assertNotNull(result); - assertTrue(result.isEmpty()); - - // or if the policy item collection is empty - List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicy.RangerPolicyItem>(); - when(policy.getPolicyItems()).thenReturn(policyItems); - result = policyEvaluator.initializeConditionEvaluators(policy, serviceDef); - assertNotNull(result); - assertTrue(result.isEmpty()); - - // or when the policy conditions collection is null - RangerPolicyItem aPolicyItem = mock(RangerPolicyItem.class); - when(aPolicyItem.getConditions()).thenReturn(null); - policyItems.add(aPolicyItem); - when(policy.getPolicyItems()).thenReturn(policyItems); - result = policyEvaluator.initializeConditionEvaluators(policy, serviceDef); - assertNotNull(result); - assertTrue(result.isEmpty()); - - // or when the policy conditions collection is not null but empty - List<RangerPolicyItemCondition> itemConditions = new ArrayList<RangerPolicy.RangerPolicyItemCondition>(); - when(aPolicyItem.getConditions()).thenReturn(itemConditions); - // remove left over from prior test - policyItems.clear(); policyItems.add(aPolicyItem); - when(policy.getPolicyItems()).thenReturn(policyItems); - result = policyEvaluator.initializeConditionEvaluators(policy, serviceDef); - assertNotNull(result); - assertTrue(result.isEmpty()); - - // or when any combination of fields of item conditions are null - RangerPolicyItemCondition anItemCondition = mock(RangerPolicyItemCondition.class); - when(anItemCondition.getType()).thenReturn(null); - when(anItemCondition.getValues()).thenReturn(null); - itemConditions.add(anItemCondition); - when(aPolicyItem.getConditions()).thenReturn(itemConditions); - policyItems.clear(); policyItems.add(aPolicyItem); - when(policy.getPolicyItems()).thenReturn(policyItems); - result = policyEvaluator.initializeConditionEvaluators(policy, serviceDef); - assertNotNull(result); - assertTrue(result.isEmpty()); - } - - @Test - public void test_initializeConditionEvaluators_happyPath() { - /* - * A policy could contain several policy items and each policy item could contain non-overlapping sets of conditions in them. - * Resulting map should contain a union of conditions in it and each pointing to correct evaluator object. - */ - // first create a service with right condition-name and evaluator names - Map<String, String[]> conditionEvaluatorMap = new HashMap<String, String[]>(); - conditionEvaluatorMap.put("c1", new String[] { "org.apache.ranger.plugin.policyevaluator.RangerDefaultPolicyEvaluatorTest$Evaluator1", null }); - conditionEvaluatorMap.put("c2", new String[] { "org.apache.ranger.plugin.policyevaluator.RangerDefaultPolicyEvaluatorTest$Evaluator2", null }); - conditionEvaluatorMap.put("c3", new String[] { "org.apache.ranger.plugin.policyevaluator.RangerDefaultPolicyEvaluatorTest$Evaluator3", null }); - conditionEvaluatorMap.put("c4", new String[] { "org.apache.ranger.plugin.policyevaluator.RangerDefaultPolicyEvaluatorTest$Evaluator4", null }); - RangerServiceDef serviceDef = getMockServiceDef(conditionEvaluatorMap); - // create policy items each with overlapping but dissimilar sets of conditions in them. - RangerPolicyItem anItem = getMockPolicyItem(new String[] {"c1", "c2"}); - RangerPolicyItem anotherItem = getMockPolicyItem(new String[] {"c2", "c3"}); - RangerPolicy policy = mock(RangerPolicy.class); - when(policy.getPolicyItems()).thenReturn(Arrays.asList(anItem, anotherItem)); - RangerDefaultPolicyEvaluator policyEvaluator = new RangerDefaultPolicyEvaluator(); - Map<String, RangerConditionEvaluator> result = policyEvaluator.initializeConditionEvaluators(policy, serviceDef); - - assertNotNull(result); - assertEquals(3, result.size()); - assertTrue(result.containsKey("c1")); - assertTrue(result.containsKey("c2")); - assertTrue(result.containsKey("c3")); - - RangerConditionEvaluator anEvaluator = result.get("c1"); - assertTrue(anEvaluator.getClass().equals(Evaluator1.class)); - anEvaluator = result.get("c2"); - assertTrue(anEvaluator.getClass().equals(Evaluator2.class)); - anEvaluator = result.get("c3"); - assertTrue(anEvaluator.getClass().equals(Evaluator3.class)); - } - - /** - * Test classs: that exists only for testing purposes - * @author alal - * - */ - static class AlwaysPass extends RangerAbstractConditionEvaluator { - - @Override - public void init() { - super.init(); - } - @Override - public boolean isMatched(RangerAccessRequest request) { - return true; - } - - } - - static class AlwaysFail extends RangerAbstractConditionEvaluator { - - @Override - public void init() { - super.init(); - } - - @Override - public boolean isMatched(RangerAccessRequest request) { - return false; - } - - } - - static class Evaluator1 extends AlwaysPass {} - static class Evaluator2 extends AlwaysPass {} - static class Evaluator3 extends AlwaysFail {} - static class Evaluator4 extends AlwaysFail {} - - /** - * A request may contain a value for several conditions. A policy item could contain evaluators for more/different conditions than that are in the request. - * check should fail if condition evaluator for any policy fails for a conditions contained in the request. If request does not have data for a condition - * then it should succeed. Data in request for condition that are not part of the policy item shouldn't affect the result. - */ - @Test - public void test_matchCustomConditions_happyPath1() { - - // let's create the condition evaluator map for 4 conditions. - Map<String, RangerConditionEvaluator> evaluators = createEvaluatorMap(); - - // let's first create a request with 2 different conditions - RangerAccessRequest request = createAccessRequestWithConditions(new String[] {"c1", "c2"}); - - // Create a policy item -- which also has same exact same number of policy conditions defined on it (2) - RangerPolicyItem policyItem = createPolicyItemForConditions(new String[] {"c1", "c2"} ); - - // check for success - RangerDefaultPolicyEvaluator policyEvaluator = new RangerDefaultPolicyEvaluator(); - boolean result = policyEvaluator.matchCustomConditions(policyItem, request, evaluators); - assertTrue(result); - - // missing conditions on request are ok, too -- they always succeed - // policy item has conditions c1 and c2 where as context will only have c1. - request = createAccessRequestWithConditions(new String[] { "c1" } ); - result = policyEvaluator.matchCustomConditions(policyItem, request, evaluators); - assertTrue(result); - - // Extra conditions on request are ok, too -- they always succeed - // policy item has conditions c1 and c2 where as context has values for conditions c3 and c4 on it and we know their evaluators always fail! - request = createAccessRequestWithConditions(new String[] {"c3", "c4"}); - result = policyEvaluator.matchCustomConditions(policyItem, request, evaluators); - assertTrue(result); - } - - @Test - public void test_matchCustomConditions_happyPath2() { - // let's create the condition evaluator map for 4 conditions and some more. - Map<String, RangerConditionEvaluator> evaluators = createEvaluatorMap(); - - // create policy item with a condition that we know will always fail - RangerPolicyItem policyItem = createPolicyItemForConditions(new String[] { "c1", "c3" } ); - - // let's first create a request with 2 different conditions - RangerAccessRequest request = createAccessRequestWithConditions(new String[]{"c1", "c3"}); - - RangerDefaultPolicyEvaluator policyEvaluator = new RangerDefaultPolicyEvaluator(); - boolean result = policyEvaluator.matchCustomConditions(policyItem, request, evaluators); - assertFalse(result); - } - - Map<String, RangerConditionEvaluator> createEvaluatorMap() { - Map<String, RangerConditionEvaluator> map = new HashMap<String, RangerConditionEvaluator>(); - map.put("c1", new Evaluator1()); - map.put("c2", new Evaluator2()); - map.put("c3", new Evaluator3()); // conditions 3 and 4 would always fail! - map.put("c4", new Evaluator4()); - - return map; - } RangerPolicyItem getMockPolicyItem(String[] strings) { RangerPolicyItem policyItem = mock(RangerPolicyItem.class); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/agents-common/src/test/resources/policyengine/test_policyengine_conditions.json ---------------------------------------------------------------------- diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_conditions.json b/agents-common/src/test/resources/policyengine/test_policyengine_conditions.json new file mode 100644 index 0000000..2ab2bee --- /dev/null +++ b/agents-common/src/test/resources/policyengine/test_policyengine_conditions.json @@ -0,0 +1,230 @@ +{ + "serviceName":"hivedev", + + "serviceDef":{ + "name":"hive", + "id":3, + "resources":[ + {"name":"database","level":1,"mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"Hive Database","description":"Hive Database"}, + {"name":"table","level":2,"parent":"database","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"Hive Table","description":"Hive Table"}, + {"name":"udf","level":2,"parent":"database","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"Hive UDF","description":"Hive UDF"}, + {"name":"column","level":3,"parent":"table","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"Hive Column","description":"Hive Column"} + ], + "accessTypes":[ + {"name":"select","label":"Select"}, + {"name":"update","label":"Update"}, + {"name":"create","label":"Create"}, + {"name":"drop","label":"Drop"}, + {"name":"alter","label":"Alter"}, + {"name":"index","label":"Index"}, + {"name":"lock","label":"Lock"}, + {"name":"all","label":"All"} + ], + "policyConditions":[ + {"name":"country", "evaluator":"org.apache.ranger.plugin.conditionevaluator.RangerSimpleMatcher", "evaluatorOptions":{"CONTEXT_NAME":"country"}} + ] + }, + + "policies":[ + {"id":1,"name":"db=default; allow select from all countries","isEnabled":true,"isAuditEnabled":true, + "resources":{"database":{"values":["default"]},"table":{"values":["*"]},"column":{"values":["*"]}}, + "policyItems":[ + {"accesses":[{"type":"select"}],"users":[],"groups":["public"],"delegateAdmin":false} + ] + } + , + {"id":2,"name":"db=default: allow create only from US","isEnabled":true,"isAuditEnabled":true, + "resources":{"database":{"values":["default"]},"table":{"values":["*"]},"column":{"values":["*"]}}, + "policyItems":[ + {"accesses":[{"type":"create"}],"users":[],"groups":["public"],"delegateAdmin":false, "conditions":[{"type":"country","values":["US"]}]} + ] + } + , + {"id":3,"name":"db=default: allow update from US,CA","isEnabled":true,"isAuditEnabled":true, + "resources":{"database":{"values":["default"]},"table":{"values":["*"]},"column":{"values":["*"]}}, + "policyItems":[ + {"accesses":[{"type":"update"}],"users":[],"groups":["public"],"delegateAdmin":false, "conditions":[{"type":"country","values":["US","CA"]}]} + ] + } + , + {"id":4,"name":"db=default: user1 allowed to drop from US; user1 allowed to index from US,CA; user2 allowed to alter from US","isEnabled":true,"isAuditEnabled":true, + "resources":{"database":{"values":["default"]},"table":{"values":["*"]},"column":{"values":["*"]}}, + "policyItems":[ + {"accesses":[{"type":"drop"}],"users":["user1"],"groups":[],"delegateAdmin":false, "conditions":[{"type":"country","values":["US"]}]}, + {"accesses":[{"type":"index"}],"users":["user1"],"groups":[],"delegateAdmin":false, "conditions":[{"type":"country","values":["US","CA"]}]}, + {"accesses":[{"type":"alter"}],"users":["user2"],"groups":[],"delegateAdmin":false, "conditions":[{"type":"country","values":["US"]}]} + ] + } + ], + + "tests":[ + {"name":"ALLOW 'use default;' no country", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"","user":"user1","userGroups":["users"],"requestData":"use default" + }, + "result":{"isAudited":true,"isAllowed":true,"policyId":1} + } + , + {"name":"DENY 'create default.testTable;' no country", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"create","user":"user1","userGroups":["users"],"requestData":"create default.testTable" + }, + "result":{"isAudited":true,"isAllowed":false,"policyId":-1} + } + , + {"name":"DENY 'update default.testTable;' no country", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"update","user":"user1","userGroups":["users"],"requestData":"update default.testTable" + }, + "result":{"isAudited":true,"isAllowed":false,"policyId":-1} + } + , + {"name":"ALLOW 'create default.testTable;' country=US", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"create","user":"user1","userGroups":["users"],"requestData":"create default.testTable", + "context":{"country":"US"} + }, + "result":{"isAudited":true,"isAllowed":true,"policyId":2} + } + , + {"name":"DENY 'create default.testTable;' country=CA", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"create","user":"user1","userGroups":["users"],"requestData":"create default.testTable", + "context":{"country":"CA"} + }, + "result":{"isAudited":true,"isAllowed":false,"policyId":-1} + } + , + {"name":"ALLOW 'update default.testTable;' country=US", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"update","user":"user1","userGroups":["users"],"requestData":"update default.testTable", + "context":{"country":"US"} + }, + "result":{"isAudited":true,"isAllowed":true,"policyId":3} + } + , + {"name":"ALLOW 'update default.testTable;' country=CA", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"update","user":"user1","userGroups":["users"],"requestData":"update default.testTable", + "context":{"country":"CA"} + }, + "result":{"isAudited":true,"isAllowed":true,"policyId":3} + } + , + {"name":"DENY 'update default.testTable;' country=UK", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"update","user":"user1","userGroups":["users"],"requestData":"update default.testTable", + "context":{"country":"UK"} + }, + "result":{"isAudited":true,"isAllowed":false,"policyId":-1} + } + , + {"name":"ALLOW 'drop default.testTable;' user1, country=US", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"drop","user":"user1","userGroups":["users"],"requestData":"drop default.testTable", + "context":{"country":"US"} + }, + "result":{"isAudited":true,"isAllowed":true,"policyId":4} + } + , + {"name":"DENY 'drop default.testTable;' user1, country=CA", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"drop","user":"user1","userGroups":["users"],"requestData":"drop default.testTable", + "context":{"country":"CA"} + }, + "result":{"isAudited":true,"isAllowed":false,"policyId":-1} + } + , + {"name":"DENY 'drop default.testTable;' user2, country=US", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"drop","user":"user2","userGroups":["users"],"requestData":"drop default.testTable", + "context":{"country":"US"} + }, + "result":{"isAudited":true,"isAllowed":false,"policyId":-1} + } + , + {"name":"ALLOW 'index default.testTable;' user1, country=US", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"index","user":"user1","userGroups":["users"],"requestData":"index default.testTable", + "context":{"country":"US"} + }, + "result":{"isAudited":true,"isAllowed":true,"policyId":4} + } + , + {"name":"ALLOW 'index default.testTable;' user1, country=CA", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"index","user":"user1","userGroups":["users"],"requestData":"index default.testTable", + "context":{"country":"CA"} + }, + "result":{"isAudited":true,"isAllowed":true,"policyId":4} + } + , + {"name":"DENY 'index default.testTable;' user1, country=UK", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"index","user":"user1","userGroups":["users"],"requestData":"index default.testTable", + "context":{"country":"UK"} + }, + "result":{"isAudited":true,"isAllowed":false,"policyId":-1} + } + , + {"name":"DENY 'index default.testTable;' user2, country=US", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"index","user":"user2","userGroups":["users"],"requestData":"index default.testTable", + "context":{"country":"US"} + }, + "result":{"isAudited":true,"isAllowed":false,"policyId":-1} + } + , + {"name":"DENY 'index default.testTable;' user2, country=UK", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"index","user":"user2","userGroups":["users"],"requestData":"index default.testTable", + "context":{"country":"CA"} + }, + "result":{"isAudited":true,"isAllowed":false,"policyId":-1} + } + , + {"name":"ALLOW 'alter default.testTable;' user2, country=US", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"alter","user":"user2","userGroups":["users"],"requestData":"alter default.testTable", + "context":{"country":"US"} + }, + "result":{"isAudited":true,"isAllowed":true,"policyId":4} + } + , + {"name":"DENY 'alter default.testTable;' user2, country=CA", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"alter","user":"user2","userGroups":["users"],"requestData":"alter default.testTable", + "context":{"country":"CA"} + }, + "result":{"isAudited":true,"isAllowed":false,"policyId":-1} + } + , + {"name":"DENY 'alter default.testTable;' user1, country=US", + "request":{ + "resource":{"elements":{"database":"default"}}, + "accessType":"alter","user":"user1","userGroups":["users"],"requestData":"alter default.testTable", + "context":{"country":"US"} + }, + "result":{"isAudited":true,"isAllowed":false,"policyId":-1} + } + ] +} + http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c5f61c89/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 338d4cf..de9c130 100644 --- a/agents-common/src/test/resources/policyengine/test_policyengine_hbase.json +++ b/agents-common/src/test/resources/policyengine/test_policyengine_hbase.json @@ -6,7 +6,7 @@ "id":2, "resources":[ {"name":"table","level":1,"parent":"","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"HBase Table","description":"HBase Table"}, - {"name":"column-family","level":2,"table":"database","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"HBase Column-Family","description":"HBase Column-Family"}, + {"name":"column-family","level":2,"parent":"table","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"HBase Column-Family","description":"HBase Column-Family"}, {"name":"column","level":3,"parent":"column-family","mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"HBase Column","description":"HBase Column"} ], "accessTypes":[
