Repository: incubator-ranger Updated Branches: refs/heads/ranger-0.6 76867e570 -> 9dfde6de9
RANGER-1261: fix path matching inconsistencies and wildcard treatment Signed-off-by: Madhan Neethiraj <mad...@apache.org> (cherry picked from commit 22029847559b3881cdc3176b15e545e847ef6d7c) Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/9dfde6de Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/9dfde6de Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/9dfde6de Branch: refs/heads/ranger-0.6 Commit: 9dfde6de92799d7d923cf8eb11bbdc8788d6664c Parents: 76867e5 Author: Abhay Kulkarni <akulka...@hortonworks.com> Authored: Mon Dec 5 20:49:52 2016 -0800 Committer: Madhan Neethiraj <mad...@apache.org> Committed: Fri Jan 6 19:03:43 2017 -0800 ---------------------------------------------------------------------- .../RangerPathResourceMatcher.java | 87 +++++++++++++++++++- .../test_resourcematcher_path.json | 61 ++++++++++++++ .../src/test/resources/hdfs-policies.json | 10 +++ 3 files changed, 155 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/9dfde6de/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcher.java ---------------------------------------------------------------------- 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 a9ac84c..aeb9fb0 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 @@ -130,10 +130,12 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { ret = optIgnoreCase ? new CaseInsensitiveRecursiveWildcardMatcher(policyValue, pathSeparatorChar) : new CaseSensitiveRecursiveWildcardMatcher(policyValue, pathSeparatorChar); } else { - ret = optIgnoreCase ? new CaseInsensitiveStartsWithMatcher(policyValue) : new CaseSensitiveStartsWithMatcher(policyValue); + ret = optIgnoreCase ? new CaseInsensitiveRecursiveMatcher(policyValue, pathSeparatorChar) : new CaseSensitiveRecursiveMatcher(policyValue, pathSeparatorChar); } - ret.setDelimiters(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix); + if (optReplaceTokens) { + ret.setDelimiters(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix); + } return ret; } @@ -172,7 +174,6 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { return ret; } - public StringBuilder toString(StringBuilder sb) { sb.append("RangerPathResourceMatcher={"); @@ -214,3 +215,83 @@ final class CaseInsensitiveRecursiveWildcardMatcher extends ResourceMatcher { int getPriority() { return 8 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);} } + +abstract class RecursiveMatcher extends ResourceMatcher { + final char levelSeparatorChar; + String valueWithoutSeparator = null; + String valueWithSeparator = null; + + RecursiveMatcher(String value, char levelSeparatorChar) { + super(value); + this.levelSeparatorChar = levelSeparatorChar; + } + + String getStringToCompare(String policyValue) { + return (policyValue.lastIndexOf(levelSeparatorChar) == policyValue.length()-1) ? + policyValue.substring(0, policyValue.length()-1) : policyValue; + } +} + +final class CaseSensitiveRecursiveMatcher extends RecursiveMatcher { + CaseSensitiveRecursiveMatcher(String value, char levelSeparatorChar) { + super(value, levelSeparatorChar); + } + + @Override + boolean isMatch(String resourceValue, Map<String, Object> evalContext) { + + final String noSeparator; + if (getNeedsDynamicEval()) { + noSeparator = getStringToCompare(getExpandedValue(evalContext)); + } else { + if (valueWithoutSeparator == null) { + valueWithoutSeparator = getStringToCompare(value); + valueWithSeparator = valueWithoutSeparator + Character.toString(levelSeparatorChar); + } + noSeparator = valueWithoutSeparator; + } + + boolean ret = StringUtils.equals(resourceValue, noSeparator); + + if (!ret) { + final String withSeparator = getNeedsDynamicEval() ? noSeparator + Character.toString(levelSeparatorChar) : valueWithSeparator; + ret = StringUtils.startsWith(resourceValue, withSeparator); + } + + return ret; + } + int getPriority() { return 7 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);} +} + +final class CaseInsensitiveRecursiveMatcher extends RecursiveMatcher { + CaseInsensitiveRecursiveMatcher(String value, char levelSeparatorChar) { + super(value, levelSeparatorChar); + } + + @Override + boolean isMatch(String resourceValue, Map<String, Object> evalContext) { + + final String noSeparator; + if (getNeedsDynamicEval()) { + noSeparator = getStringToCompare(getExpandedValue(evalContext)); + } else { + if (valueWithoutSeparator == null) { + valueWithoutSeparator = getStringToCompare(value); + valueWithSeparator = valueWithoutSeparator + Character.toString(levelSeparatorChar); + } + noSeparator = valueWithoutSeparator; + } + + boolean ret = StringUtils.equalsIgnoreCase(resourceValue, noSeparator); + + if (!ret) { + final String withSeparator = getNeedsDynamicEval() ? noSeparator + Character.toString(levelSeparatorChar) : valueWithSeparator; + ret = StringUtils.startsWithIgnoreCase(resourceValue, withSeparator); + } + + return ret; + } + + int getPriority() { return 8 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);} + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/9dfde6de/agents-common/src/test/resources/resourcematcher/test_resourcematcher_path.json ---------------------------------------------------------------------- diff --git a/agents-common/src/test/resources/resourcematcher/test_resourcematcher_path.json b/agents-common/src/test/resources/resourcematcher/test_resourcematcher_path.json index c67ff45..86da28c 100644 --- a/agents-common/src/test/resources/resourcematcher/test_resourcematcher_path.json +++ b/agents-common/src/test/resources/resourcematcher/test_resourcematcher_path.json @@ -1,6 +1,45 @@ { "testCases":[ { + "name":"value=/a/b*y.txt; isRecursive=true; wildCard=true; ignoreCase=true", + "resourceDef":{ + "matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher", + "matcherOptions":{"wildCard":true, "ignoreCase":true} + }, + "policyResource":{ + "values": ["/a/b*y.txt"], + "isRecursive":true + }, + "tests":[ + { "name":"exact-path","input":"/a/b*y.txt", "result":true}, + { "name":"child-path","input":"/a/b/y.txt", "result":true}, + { "name":"grand-child-path","input":"/a/b1/b2/y.txt", "result":true}, + { "name":"descendant-child-path","input":"/a/b1/c1/d1/any.txt", "result":true}, + { "name":"mismatche-path","input":"/a/any.txt", "result":false}, + + ] + } + , + { + "name":"value=/a/b*y.txt; isRecursive=false; wildCard=true; ignoreCase=true", + "resourceDef":{ + "matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher", + "matcherOptions":{"wildCard":true, "ignoreCase":true} + }, + "policyResource":{ + "values": ["/a/b*y.txt"], + "isRecursive":false + }, + "tests":[ + { "name":"exact-path","input":"/a/b*y.txt", "result":true}, + { "name":"child-path","input":"/a/b/y.txt", "result":true}, + { "name":"grand-child-path","input":"/a/b1/b2/y.txt", "result":true}, + { "name":"descendant-child-path","input":"/a/b1/c1/d1/any.txt", "result":true}, + { "name":"mismatche-path","input":"/a/any.txt", "result":false}, + ] + } + , + { "name":"value=*; isRecursive=false; wildCard=true; ignoreCase=true", "resourceDef":{ "matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher", @@ -131,9 +170,31 @@ { "name":"grand-child-path-camel-case","input":"/Path1/Path2/Path3", "result":true}, { "name":"sibling-path","input":"/path2", "result":false}, { "name":"invalid-path","input":"path1", "result":false}, + { "name":"prefix-path","input":"/path12", "result":false}, + { "name":"no-path","input":"", "result":false} ] } , + { + "name": "value=/path1/path2; isRecursive=true; wildCard=true; ignoreCase=true", + "resourceDef": { + "matcher": "org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher", + "matcherOptions": {"wildCard": true, "ignoreCase": true + } + }, + "policyResource": {"values": ["/path1/path2"], "isRecursive": true}, + "tests": [ + {"name": "exact-path", "input": "/path1/path2", "result": true}, + {"name": "parent-path", "input": "/path1", "result": false}, + {"name": "grand-parent-path", "input": "/", "result": false}, + {"name": "child-path", "input": "/path1/path2/path3", "result": true}, + {"name": "grandchild-path", "input": "/path1/path2/path3/path4", "result": true}, + {"name": "sibling-path", "input": "/path1/path3", "result": false}, + {"name": "prefix-path", "input": "/path1/path21", "result": false}, + {"name": "invalid-path", "input": "path1/path2*", "result": false} + ] + } + , { "name":"value=/path*; isRecursive=true; wildCard=true; ignoreCase=true", "resourceDef":{ http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/9dfde6de/hdfs-agent/src/test/resources/hdfs-policies.json ---------------------------------------------------------------------- diff --git a/hdfs-agent/src/test/resources/hdfs-policies.json b/hdfs-agent/src/test/resources/hdfs-policies.json index c99c811..eb61796 100644 --- a/hdfs-agent/src/test/resources/hdfs-policies.json +++ b/hdfs-agent/src/test/resources/hdfs-policies.json @@ -82,6 +82,11 @@ { "accesses": [ { + "type": "read", + "isAllowed": true + } + , + { "type": "execute", "isAllowed": true } @@ -96,6 +101,11 @@ { "accesses": [ { + "type": "read", + "isAllowed": true + } + , + { "type": "execute", "isAllowed": true }