This is an automated email from the ASF dual-hosted git repository. abhay pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push: new 1d2caab RANGER-3147: enhance resource-trie to enable finding evaluators for a given resource and its children - Part 2 1d2caab is described below commit 1d2caab522a62728d1975fcde4b7af0b0afcdb5f Author: Abhay Kulkarni <ab...@apache.org> AuthorDate: Wed Feb 17 10:28:29 2021 -0800 RANGER-3147: enhance resource-trie to enable finding evaluators for a given resource and its children - Part 2 --- .../plugin/policyengine/RangerAccessRequest.java | 2 + .../RangerDefaultPolicyEvaluator.java | 4 +- .../RangerAbstractResourceMatcher.java | 8 +-- .../resourcematcher/RangerPathResourceMatcher.java | 78 ++++++++++++---------- .../RangerPathResourceMatcherTest.java | 51 ++++++++++++++ 5 files changed, 100 insertions(+), 43 deletions(-) diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java index 57804ad..6a38747 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java @@ -25,6 +25,8 @@ import java.util.Map; import java.util.Set; public interface RangerAccessRequest { + String RANGER_ACCESS_REQUEST_SCOPE_STRING = "Scope"; + RangerAccessResource getResource(); String getAccessType(); 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 a8ad632..2edd992 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 @@ -240,10 +240,10 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator } } else { if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) { - request.getContext().put("Scope", "SELF_OR_ONE_LEVEL"); + request.getContext().put(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING, RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD); } matchType = resourceMatcher != null ? resourceMatcher.getMatchType(request.getResource(), request.getContext()) : RangerPolicyResourceMatcher.MatchType.NONE; - request.getContext().remove("Scope"); + request.getContext().remove(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING); } final boolean isMatched; diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java index 4ebffef..4754539 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java @@ -47,7 +47,6 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat public final static String OPTION_TOKEN_DELIMITER_END = "tokenDelimiterEnd"; public final static String OPTION_TOKEN_DELIMITER_ESCAPE = "tokenDelimiterEscape"; public final static String OPTION_TOKEN_DELIMITER_PREFIX = "tokenDelimiterPrefix"; - public final static String OPTION_SIMULATE_HIERARCHY = "simulateHierarchy"; protected RangerResourceDef resourceDef; protected RangerPolicyResource policyResource; @@ -65,7 +64,6 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat protected char endDelimiterChar = '}'; protected char escapeChar = '\\'; protected String tokenPrefix = ""; - protected boolean optSimulateHierarchy; @Override public void setResourceDef(RangerResourceDef resourceDef) { @@ -126,8 +124,6 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat } } - optSimulateHierarchy = getOptionSimulateHierarchy(options); - resourceMatchers = buildResourceMatchers(); isMatchAny = resourceMatchers == null || CollectionUtils.isEmpty(resourceMatchers.getResourceMatchers()); @@ -170,9 +166,7 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat public static String getOptionDelimiterPrefix(Map<String, String> options) { return ServiceDefUtil.getOption(options, OPTION_TOKEN_DELIMITER_PREFIX, ""); } - public static boolean getOptionSimulateHierarchy(Map<String, String> options) { - return ServiceDefUtil.getBooleanOption(options, OPTION_SIMULATE_HIERARCHY, false); - } + protected ResourceMatcherWrapper buildResourceMatchers() { List<ResourceMatcher> resourceMatchers = new ArrayList<>(); boolean needsDynamicEval = false; diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcher.java index 4a158a2..c60e7bc 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcher.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcher.java @@ -27,6 +27,7 @@ import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.util.ServiceDefUtil; import java.util.ArrayList; @@ -129,9 +130,9 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { final ResourceMatcher ret; if (isWildcardPresent) { - ret = new RecursiveWildcardResourceMatcher(policyValue, true, pathSeparatorChar, optIgnoreCase, RangerPathResourceMatcher::isRecursiveWildCardMatch, optIgnoreCase ? 8 : 7); + ret = new RecursiveWildcardResourceMatcher(policyValue, pathSeparatorChar, optIgnoreCase, RangerPathResourceMatcher::isRecursiveWildCardMatch, optIgnoreCase ? 8 : 7); } else { - ret = new RecursivePathResourceMatcher(policyValue, true, pathSeparatorChar, optIgnoreCase ? StringUtils::equalsIgnoreCase : StringUtils::equals, optIgnoreCase ? StringUtils::startsWithIgnoreCase : StringUtils::startsWith, optIgnoreCase ? 8 : 7); + ret = new RecursivePathResourceMatcher(policyValue, pathSeparatorChar, optIgnoreCase ? StringUtils::equalsIgnoreCase : StringUtils::equals, optIgnoreCase ? StringUtils::startsWithIgnoreCase : StringUtils::startsWith, optIgnoreCase ? 8 : 7); } if (optReplaceTokens) { @@ -232,17 +233,17 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { } if (needWildcardMatch) { // test?, test*a*, test*a*b, *test*a - ret = new WildcardResourceMatcher(policyValue, true, pathSeparatorChar, optIgnoreCase, FilenameUtils::wildcardMatch, 6); + ret = new WildcardResourceMatcher(policyValue, pathSeparatorChar, optIgnoreCase, FilenameUtils::wildcardMatch, 6); } else if (wildcardStartIdx == -1) { // test, testa, testab - ret = new StringResourceMatcher(policyValue, true, pathSeparatorChar, optIgnoreCase ? StringUtils::equalsIgnoreCase : StringUtils::equals, optIgnoreCase ? 2 : 1); + ret = new StringResourceMatcher(policyValue, pathSeparatorChar, optIgnoreCase ? StringUtils::equalsIgnoreCase : StringUtils::equals, optIgnoreCase ? 2 : 1); } else if (wildcardStartIdx == 0) { // *test, **test, *testa, *testab String matchStr = policyValue.substring(wildcardEndIdx + 1); - ret = new StringResourceMatcher(matchStr, true, pathSeparatorChar, optIgnoreCase ? StringUtils::endsWithIgnoreCase : StringUtils::endsWith, optIgnoreCase ? 4 : 3); + ret = new StringResourceMatcher(matchStr, pathSeparatorChar, optIgnoreCase ? StringUtils::endsWithIgnoreCase : StringUtils::endsWith, optIgnoreCase ? 4 : 3); } else if (wildcardEndIdx != (len - 1)) { // test*a, test*ab - ret = new WildcardResourceMatcher(policyValue, true, pathSeparatorChar, optIgnoreCase, FilenameUtils::wildcardMatch, 6); + ret = new WildcardResourceMatcher(policyValue, pathSeparatorChar, optIgnoreCase, FilenameUtils::wildcardMatch, 6); } else { // test*, test**, testa*, testab* String matchStr = policyValue.substring(0, wildcardStartIdx); - ret = new StringResourceMatcher(matchStr, true, pathSeparatorChar, optIgnoreCase ? StringUtils::startsWithIgnoreCase : StringUtils::startsWith, optIgnoreCase ? 4 : 3); + ret = new StringResourceMatcher(matchStr, pathSeparatorChar, optIgnoreCase ? StringUtils::startsWithIgnoreCase : StringUtils::startsWith, optIgnoreCase ? 4 : 3); } if (optReplaceTokens) { @@ -261,13 +262,11 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { } static abstract class PathResourceMatcher extends ResourceMatcher { - final boolean optSimulateHierarchy; final char pathSeparatorChar; final int priority; - PathResourceMatcher(String value, boolean optSimulatedHierarchy, char pathSeparatorChar, int priority) { + PathResourceMatcher(String value, char pathSeparatorChar, int priority) { super(value); - this.optSimulateHierarchy = optSimulatedHierarchy; this.pathSeparatorChar = pathSeparatorChar; this.priority = priority; } @@ -278,17 +277,17 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { static class StringResourceMatcher extends PathResourceMatcher { final BiFunction<String, String, Boolean> function; - StringResourceMatcher(String value, boolean optSimulatedHierarchy, char pathSeparatorChar, BiFunction<String, String, Boolean> function, int priority) { - super(value, optSimulatedHierarchy, pathSeparatorChar, priority); + StringResourceMatcher(String value, char pathSeparatorChar, BiFunction<String, String, Boolean> function, int priority) { + super(value, pathSeparatorChar, priority); this.function = function; } @Override boolean isMatch(String resourceValue, Map<String, Object> evalContext) { String expandedValue = getExpandedValue(evalContext); boolean ret = function.apply(resourceValue, expandedValue); - if (!ret && optSimulateHierarchy) { - String scope = MapUtils.isNotEmpty(evalContext) ? (String) evalContext.get("Scope") : null; - if (StringUtils.equals(scope, "SELF_OR_ONE_LEVEL")) { + if (!ret) { + RangerAccessRequest.ResourceMatchingScope scope = MapUtils.isNotEmpty(evalContext) ? (RangerAccessRequest.ResourceMatchingScope) evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null; + if (scope == RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) { int lastLevelSeparatorIndex = expandedValue.lastIndexOf(pathSeparatorChar); if (lastLevelSeparatorIndex != -1) { String shorterExpandedValue = expandedValue.substring(0, lastLevelSeparatorIndex); @@ -308,8 +307,8 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { final TriFunction<String, String, IOCase, Boolean> function; final IOCase ioCase; - WildcardResourceMatcher(String value, boolean optSimulatedHierarchy, char pathSeparatorChar, boolean optIgnoreCase, TriFunction<String, String, IOCase, Boolean> function, int priority) { - super(value, optSimulatedHierarchy, pathSeparatorChar, priority); + WildcardResourceMatcher(String value, char pathSeparatorChar, boolean optIgnoreCase, TriFunction<String, String, IOCase, Boolean> function, int priority) { + super(value, pathSeparatorChar, priority); this.function = function; this.ioCase = optIgnoreCase ? IOCase.INSENSITIVE : IOCase.SENSITIVE; } @@ -317,9 +316,9 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { boolean isMatch(String resourceValue, Map<String, Object> evalContext) { String expandedValue = getExpandedValue(evalContext); boolean ret = function.apply(resourceValue, expandedValue, ioCase); - if (!ret && optSimulateHierarchy) { - String scope = MapUtils.isNotEmpty(evalContext) ? (String) evalContext.get("Scope") : null; - if (StringUtils.equals(scope, "SELF_OR_ONE_LEVEL")) { + if (!ret) { + RangerAccessRequest.ResourceMatchingScope scope = MapUtils.isNotEmpty(evalContext) ? (RangerAccessRequest.ResourceMatchingScope) evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null; + if (scope == RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) { int lastLevelSeparatorIndex = expandedValue.lastIndexOf(pathSeparatorChar); if (lastLevelSeparatorIndex != -1) { String shorterExpandedValue = expandedValue.substring(0, lastLevelSeparatorIndex); @@ -338,8 +337,8 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { final QuadFunction<String, String, Character, IOCase, Boolean> function; final IOCase ioCase; - RecursiveWildcardResourceMatcher(String value, boolean optSimulatedHierarchy, char pathSeparatorChar, boolean optIgnoreCase, QuadFunction<String, String, Character, IOCase, Boolean> function, int priority) { - super(value, optSimulatedHierarchy, pathSeparatorChar, priority); + RecursiveWildcardResourceMatcher(String value, char pathSeparatorChar, boolean optIgnoreCase, QuadFunction<String, String, Character, IOCase, Boolean> function, int priority) { + super(value, pathSeparatorChar, priority); this.function = function; this.ioCase = optIgnoreCase ? IOCase.INSENSITIVE : IOCase.SENSITIVE; } @@ -347,9 +346,9 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { boolean isMatch(String resourceValue, Map<String, Object> evalContext) { String expandedValue = getExpandedValue(evalContext); boolean ret = function.apply(resourceValue, expandedValue, pathSeparatorChar, ioCase); - if (!ret && optSimulateHierarchy) { - String scope = MapUtils.isNotEmpty(evalContext) ? (String) evalContext.get("Scope") : null; - if (StringUtils.equals(scope, "SELF_OR_ONE_LEVEL")) { + if (!ret) { + RangerAccessRequest.ResourceMatchingScope scope = MapUtils.isNotEmpty(evalContext) ? (RangerAccessRequest.ResourceMatchingScope) evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null; + if (scope == RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) { int lastLevelSeparatorIndex = expandedValue.lastIndexOf(pathSeparatorChar); if (lastLevelSeparatorIndex != -1) { String shorterExpandedValue = expandedValue.substring(0, lastLevelSeparatorIndex); @@ -371,8 +370,8 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { final BiFunction<String, String, Boolean> primaryFunction; final BiFunction<String, String, Boolean> fallbackFunction; - RecursivePathResourceMatcher(String value, boolean optSimulateHierarchy, char pathSeparatorChar, BiFunction<String, String, Boolean> primaryFunction, BiFunction<String, String, Boolean> fallbackFunction, int priority) { - super(value, optSimulateHierarchy, pathSeparatorChar, priority); + RecursivePathResourceMatcher(String value, char pathSeparatorChar, BiFunction<String, String, Boolean> primaryFunction, BiFunction<String, String, Boolean> fallbackFunction, int priority) { + super(value, pathSeparatorChar, priority); this.primaryFunction = primaryFunction; this.fallbackFunction = fallbackFunction; } @@ -387,7 +386,6 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { @Override boolean isMatch(String resourceValue, Map<String, Object> evalContext) { - final String noSeparator; if (getNeedsDynamicEval()) { String expandedPolicyValue = getExpandedValue(evalContext); @@ -404,12 +402,24 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { if (!ret && noSeparator != null) { final String withSeparator = getNeedsDynamicEval() ? noSeparator + pathSeparatorChar : valueWithSeparator; - String scope = MapUtils.isNotEmpty(evalContext) ? (String) evalContext.get("Scope") : null; - - if (!optSimulateHierarchy || !StringUtils.equals(scope, "SELF_OR_ONE_LEVEL")) { - ret = fallbackFunction.apply(resourceValue, withSeparator); - } else { - ret = fallbackFunction.apply(withSeparator, resourceValue); + ret = fallbackFunction.apply(resourceValue, withSeparator); + + if (!ret) { + RangerAccessRequest.ResourceMatchingScope scope = MapUtils.isNotEmpty(evalContext) ? (RangerAccessRequest.ResourceMatchingScope) evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null; + if (scope == RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) { + final int lastLevelSeparatorIndex = noSeparator.lastIndexOf(pathSeparatorChar); + if (lastLevelSeparatorIndex != -1) { + final String shorterExpandedValue = noSeparator.substring(0, lastLevelSeparatorIndex); + if (resourceValue.charAt(resourceValue.length() - 1) == pathSeparatorChar) { + resourceValue = resourceValue.substring(0, resourceValue.length() - 1); + } + ret = primaryFunction.apply(resourceValue, shorterExpandedValue); + if (!ret) { + final String shortedExpandedValueWithSeparator = getNeedsDynamicEval() ? shorterExpandedValue + pathSeparatorChar : shorterExpandedValue; + ret = fallbackFunction.apply(resourceValue, shortedExpandedValueWithSeparator); + } + } + } } } diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcherTest.java b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcherTest.java index 5c49777..1425027 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcherTest.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcherTest.java @@ -21,6 +21,7 @@ package org.apache.ranger.plugin.resourcematcher; import com.google.common.collect.Lists; import org.apache.ranger.plugin.model.RangerPolicy; +import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.util.RangerAccessRequestUtil; import org.junit.Test; @@ -50,6 +51,37 @@ public class RangerPathResourceMatcherTest { { "/app/hbase/test.tbl", "/app/hive/test.db", true, false, false, "user" }, }; + Object[][] dataForSelfOrChildScope = { + // { resource, policy, optWildcard, recursive, result + { "/app/hive/test.db", "/", true, false, false, "user" }, + { "/app/hive/test.db", "/", true, true, true, "user" }, + { "/app/hive/test.db", "/*", true, false, true, "user" }, + { "/app/hbase/test.tbl", "/*", true, false, true, "user" }, + { "/app/hive/test.db", "/app", true, false, false, "user" }, + { "/app/hive/test.db", "/app/", true, false, false, "user" }, + { "/app/hive/test.db", "/app/", true, true, true, "user" }, + { "/app/hive/test.db", "/app/*", true, false, true, "user" }, + { "/app/hbase/test.tbl", "/app/*", true, false, true, "user" }, + { "/app/hive/test.db", "/app/hive/*", true, false, true, "user" }, + { "/app/hbase/test.tbl", "/app/hive/*", true, false, false, "user" }, + { "/app/hive/test.db", "/app/hive/test*", true, false, true, "user" }, + { "/app/hbase/test.tbl", "/app/hive/test*", true, false, false, "user" }, + { "/app/hive/test.db", "/app/hive/test.db", true, false, true, "user" }, + { "/app/hbase/test.tbl", "/app/hive/test.db", true, false, false, "user" }, + { "/app/hbase/test.db", "/app/hbase", true, true, true, "user" }, + { "/app/hbase/test.db", "/app/hbase/test.db/test.tbl", true, true, true, "user" }, + { "/app/hbase/test.db/", "/app/hbase/test.db/test.tbl", true, true, true, "user" }, + { "/app/hbase/test.db", "/app/hbase/test.db/test.tbl/test.col", true, true, false, "user" }, + { "/app/hbase/test.db", "/app/h*/test.db/test.tbl", true, true, true, "user" }, + { "/app/hbase/test.db", "/app/hbase/test.db/test.tbl", true, false, true, "user" }, + { "/app/hbase/test.db/", "/app/hbase/test.db/test.tbl", true, false, true, "user" }, + { "/app/hbase/test.db/", "/app/hbase/test.db/test.tbl", true, false, true, "user" }, + { "/app/hbase/test.db", "/app/h*/test.db/test.tbl", true, false, true, "user" }, + { "/app/hbase/test.db", "*/hbase/test.db/test.tbl", true, false, true, "user" }, + { "/app/hbase/test.db", "/app/hbase/test.db/test.t*", true, false, true, "user" }, + { "/app/hbase/test.db", "/app/hbase/test.db/tmp/test.t*", true, false, false, "user" }, + }; + @Test public void testIsMatch() throws Exception { for (Object[] row : data) { @@ -68,6 +100,25 @@ public class RangerPathResourceMatcherTest { } } + @Test + public void testIsMatchForSelfOrChildScope() throws Exception { + for (Object[] row : dataForSelfOrChildScope) { + String resource = (String)row[0]; + String policyValue = (String)row[1]; + boolean optWildcard = (boolean)row[2]; + boolean isRecursive = (boolean)row[3]; + boolean result = (boolean)row[4]; + String user = (String) row[5]; + + Map<String, Object> evalContext = new HashMap<>(); + RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user); + evalContext.put(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING, RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD); + + MatcherWrapper matcher = new MatcherWrapper(policyValue, optWildcard, isRecursive); + assertEquals(getMessage(row), result, matcher.isMatch(resource, evalContext)); + } + } + String getMessage(Object[] row) { return String.format("Resource=%s, Policy=%s, optWildcard=%s, recursive=%s, result=%s", (String)row[0], (String)row[1], (boolean)row[2], (boolean)row[3], (boolean)row[4]);