ranger-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mad...@apache.org
Subject [5/9] incubator-ranger git commit: RANGER-698: updated Ranger policies to support variables like {USER} in resource-names
Date Tue, 03 Jan 2017 08:17:06 GMT
http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
index a4e34da..b5c8fb0 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceTrie.java
@@ -53,13 +53,25 @@ public class RangerResourceTrie<T extends RangerPolicyResourceEvaluator>
{
         }
 
         Map<String, String> matcherOptions = resourceDef.getMatcherOptions();
-        String              strIgnoreCase  = matcherOptions != null ? matcherOptions.get(RangerAbstractResourceMatcher.OPTION_IGNORE_CASE)
: null;
-        String              strWildcard    = matcherOptions != null ? matcherOptions.get(RangerAbstractResourceMatcher.OPTION_WILD_CARD)
: null;
+
+        boolean optReplaceTokens = RangerAbstractResourceMatcher.getOptionReplaceTokens(matcherOptions);
+
+        String tokenReplaceSpecialChars = "";
+
+        if(optReplaceTokens) {
+            char delimiterStart  = RangerAbstractResourceMatcher.getOptionDelimiterStart(matcherOptions);
+            char delimiterEnd    = RangerAbstractResourceMatcher.getOptionDelimiterEnd(matcherOptions);
+            char delimiterEscape = RangerAbstractResourceMatcher.getOptionDelimiterEscape(matcherOptions);
+
+            tokenReplaceSpecialChars += delimiterStart;
+            tokenReplaceSpecialChars += delimiterEnd;
+            tokenReplaceSpecialChars += delimiterEscape;
+        }
 
         this.resourceName  = resourceDef.getName();
-        this.optIgnoreCase = strIgnoreCase != null ? Boolean.parseBoolean(strIgnoreCase)
: false;
-        this.optWildcard   = strWildcard != null ? Boolean.parseBoolean(strWildcard) : false;;
-        this.wildcardChars = optWildcard ? DEFAULT_WILDCARD_CHARS : "";
+        this.optIgnoreCase = RangerAbstractResourceMatcher.getOptionIgnoreCase(matcherOptions);
+        this.optWildcard   = RangerAbstractResourceMatcher.getOptionWildCard(matcherOptions);
+        this.wildcardChars = optWildcard ? DEFAULT_WILDCARD_CHARS + tokenReplaceSpecialChars
: "" + tokenReplaceSpecialChars;
         this.root          = new TrieNode(Character.valueOf((char)0));
 
         for(T evaluator : evaluators) {
@@ -79,7 +91,7 @@ public class RangerResourceTrie<T extends RangerPolicyResourceEvaluator>
{
             } else {
                 RangerResourceMatcher resourceMatcher = evaluator.getResourceMatcher(resourceName);
 
-                if(resourceMatcher != null && resourceMatcher.isMatchAny()) {
+                if(resourceMatcher != null && (resourceMatcher.isMatchAny())) {
                     root.addWildcardEvaluator(evaluator);
                 } else {
                     if(CollectionUtils.isNotEmpty(policyResource.getValues())) {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
index 0a2b451..dbdc935 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
@@ -110,6 +110,28 @@ public class ServiceDefUtil {
         return ret;
     }
 
+    public static String getOption(Map<String, String> options, String name, String
defaultValue) {
+        String ret = options != null && name != null ? options.get(name) : null;
+
+        if(ret == null) {
+            ret = defaultValue;
+        }
+
+        return ret;
+    }
+
+    public static boolean getBooleanOption(Map<String, String> options, String name,
boolean defaultValue) {
+        String val = getOption(options, name, null);
+
+        return val == null ? defaultValue : Boolean.parseBoolean(val);
+    }
+
+    public static char getCharOption(Map<String, String> options, String name, char
defaultValue) {
+        String val = getOption(options, name, null);
+
+        return StringUtils.isEmpty(val) ? defaultValue : val.charAt(0);
+    }
+
     private static void normalizeDataMaskDef(RangerServiceDef serviceDef) {
         if(serviceDef != null && serviceDef.getDataMaskDef() != null) {
             List<RangerResourceDef>   dataMaskResources   = serviceDef.getDataMaskDef().getResources();
@@ -282,4 +304,5 @@ public class ServiceDefUtil {
 
         return ret;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/agents-common/src/main/java/org/apache/ranger/plugin/util/StringTokenReplacer.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/StringTokenReplacer.java
b/agents-common/src/main/java/org/apache/ranger/plugin/util/StringTokenReplacer.java
new file mode 100644
index 0000000..f7047f3
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/StringTokenReplacer.java
@@ -0,0 +1,126 @@
+/*
+ * 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.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class StringTokenReplacer {
+    private final char startChar;
+    private final char endChar;
+    private final char escapeChar;
+    private final String tokenPrefix;
+
+    public StringTokenReplacer(char startChar, char endChar, char escapeChar, String tokenPrefix)
{
+        this.startChar  = startChar;
+        this.endChar    = endChar;
+        this.escapeChar = escapeChar;
+        this.tokenPrefix = tokenPrefix;
+    }
+
+    public String replaceTokens(String value, Map<String, Object> tokens) {
+        if(tokens == null || tokens.size() < 1 || value == null || value.length() <
1 ||
+                (value.indexOf(startChar) == -1 && value.indexOf(endChar) == -1 &&
value.indexOf(escapeChar) == -1)) {
+            return value;
+        }
+
+        StringBuilder ret   = new StringBuilder();
+        StringBuilder token = null;
+
+        for(int i = 0; i < value.length(); i++) {
+            char c = value.charAt(i);
+
+            if(c == escapeChar) {
+                i++;
+                if(i < value.length()) {
+                    c = value.charAt(i);
+                    if(token != null) {
+                        token.append(c);
+                    } else {
+                        ret.append(c);
+                    }
+                }
+                continue;
+            }
+
+            if(token == null) { // not in token
+                if(c == startChar) {
+                    token = new StringBuilder();
+                } else {
+                    ret.append(c);
+                }
+            } else { // in token
+                if(c == endChar) {
+                    String rawToken = token.toString();
+                    if (tokenPrefix.length() == 0 || rawToken.startsWith(tokenPrefix)) {
+                        Object replaced = RangerAccessRequestUtil.getTokenFromContext(tokens,
rawToken.substring(tokenPrefix.length()));
+                        if (replaced != null) {
+                            ret.append(replaced.toString());
+                        }
+                    } else {
+                        ret.append(startChar).append(token).append(endChar);
+                    }
+                    token = null;
+                } else {
+                    token.append(c);
+                }
+            }
+        }
+
+        if(token != null) { // if no endChar is found
+            ret.append(startChar).append(token);
+        }
+
+        return ret.toString();
+    }
+
+    public static void main(String[] args) {
+        char                startChar  = '%';
+        char                endChar    = '%';
+        char                escapeChar = '\\';
+        String              tokenPrefix = "ranger:";
+        Map<String, Object> tokens     = new HashMap<String, Object>();
+
+        tokens.put("USER", "testUser");
+        tokens.put("COUNTRY", "USA");
+        tokens.put("STATE", "CA");
+        tokens.put("CITY", "Santa Clara");
+
+        StringTokenReplacer tokenReplacer = new StringTokenReplacer(startChar, endChar, escapeChar,
tokenPrefix);
+
+        if(args.length == 0) {
+            args = new String[] {
+                    "/home/%USER%/*",
+                    "/home/%ranger:USER%/*",
+                    "tmp_%USER%",
+                    "tmp_%ranger:USER%",
+                    "%USER%_db",
+                    "%ranger:USER%_db",
+                    "\\%USER_db",
+                    "\\%ranger:USER_db",
+                    "\\%USER%_db",
+                    "\\%ranger:USER%_db",
+            };
+        }
+
+        for(String str : args) {
+            System.out.println(str + " ==> " + tokenReplacer.replaceTokens(str, tokens));
+        }
+    }}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcherTest.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcherTest.java
b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcherTest.java
index 48bc6ee..e2c7c27 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcherTest.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcherTest.java
@@ -21,6 +21,8 @@ package org.apache.ranger.plugin.resourcematcher;
 
 import org.junit.Test;
 
+import java.util.Map;
+
 import static org.junit.Assert.*;
 
 public class RangerAbstractResourceMatcherTest {
@@ -40,9 +42,9 @@ public class RangerAbstractResourceMatcherTest {
     static class AbstractMatcherWrapper extends RangerAbstractResourceMatcher {
 
         @Override
-        public boolean isMatch(String resource) {
+        public boolean isMatch(String resource, Map<String, Object> evalContext) {
             fail("This method is not expected to be used by test!");
             return false;
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcherTest.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcherTest.java
b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcherTest.java
index d2fb62c..7532061 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcherTest.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcherTest.java
@@ -21,24 +21,28 @@ package org.apache.ranger.plugin.resourcematcher;
 
 import com.google.common.collect.Lists;
 import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.junit.Test;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import static org.junit.Assert.*;
 
 public class RangerDefaultResourceMatcherTest {
 
     Object[][] data = {
             // { resource, policy, excludes, result
-            { "*",  "*",  false, true },  // resource is all values
-            { "*",  "*",  true,  false },
-            { "*",  "a*", false, false }, // but, policy is not match any
-            { "*",  "a*", true,  false }, // ==> compare with above: exclude flag has
no effect here
-            { "a*", "a",  false, false }, // resource has regex marker!
-            { "a*", "a",  true,  true },
-            { "a",  "a",  false, true },  // exact match
-            { "a",  "a",  true,  false },
-            { "a1", "a*", false, true },  // trivial regex match
-            { "a1", "a*", true,  false },
+            { "*",  "*",  false, true, "user" },  // resource is all values
+            { "*",  "*",  true,  false, "user" },
+            { "*",  "a*", false, false, "user" }, // but, policy is not match any
+            { "*",  "a*", true,  false, "user" }, // ==> compare with above: exclude flag
has no effect here
+            { "a*", "a",  false, false, "user" }, // resource has regex marker!
+            { "a*", "a",  true,  true, "user" },
+            { "a",  "a",  false, true, "user" },  // exact match
+            { "a",  "a",  true,  false, "user" },
+            { "a1", "a*", false, true, "user" },  // trivial regex match
+            { "a1", "a*", true,  false, "user" },
     };
 
     @Test
@@ -48,9 +52,13 @@ public class RangerDefaultResourceMatcherTest {
             String policyValue = (String)row[1];
             boolean excludes = (boolean)row[2];
             boolean result = (boolean)row[3];
+            String user = (String) row[4];
+
+            Map<String, Object> evalContext = new HashMap<String, Object>();
+            RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
 
             MatcherWrapper matcher = new MatcherWrapper(policyValue, excludes);
-            assertEquals(getMessage(row), result, matcher.isMatch(resource));
+            assertEquals(getMessage(row), result, matcher.isMatch(resource, evalContext));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerPathResourceMatcherTest.java
----------------------------------------------------------------------
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 c9d207f..da81d81 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,29 +21,33 @@ package org.apache.ranger.plugin.resourcematcher;
 
 import com.google.common.collect.Lists;
 import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.junit.Test;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import static org.junit.Assert.assertEquals;
 
 public class RangerPathResourceMatcherTest {
 
     Object[][] data = {
             // { resource, policy, optWildcard, recursive, result
-            { "/app/hive/test.db",    "/",                 true, false, false },
-            { "/app/hive/test.db",    "/",                 true, true,  true },
-            { "/app/hive/test.db",    "/*",                true, false, true },
-            { "/app/hbase/test.tbl",  "/*",                true, false, true },
-            { "/app/hive/test.db",    "/app",              true, false, false },
-            { "/app/hive/test.db",    "/app/",             true, false, false },
-            { "/app/hive/test.db",    "/app/",             true, true,  true },
-            { "/app/hive/test.db",    "/app/*",            true, false, true },
-            { "/app/hbase/test.tbl",  "/app/*",            true, false, true },
-            { "/app/hive/test.db",    "/app/hive/*",       true, false, true },
-            { "/app/hbase/test.tbl",  "/app/hive/*",       true, false, false },
-            { "/app/hive/test.db",    "/app/hive/test*",   true, false, true },
-            { "/app/hbase/test.tbl",  "/app/hive/test*",   true, false, false },
-            { "/app/hive/test.db",    "/app/hive/test.db", true, false, true },
-            { "/app/hbase/test.tbl",  "/app/hive/test.db", true, false, false },
+            { "/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" },
     };
 
     @Test
@@ -54,9 +58,13 @@ public class RangerPathResourceMatcherTest {
             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<String, Object>();
+            RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
 
             MatcherWrapper matcher = new MatcherWrapper(policyValue, optWildcard, isRecursive);
-            assertEquals(getMessage(row), result, matcher.isMatch(resource));
+            assertEquals(getMessage(row), result, matcher.isMatch(resource, evalContext));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/TestResourceMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/TestResourceMatcher.java
b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/TestResourceMatcher.java
index 9b870d4..2cb8fde 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/TestResourceMatcher.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/TestResourceMatcher.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.*;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
@@ -39,7 +40,7 @@ import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 
 public class TestResourceMatcher {
-	static Gson               gsonBuilder  = null;
+	static Gson gsonBuilder = null;
 
 	@BeforeClass
 	public static void setUpBeforeClass() throws Exception {
@@ -74,6 +75,20 @@ public class TestResourceMatcher {
 		runTestsFromResourceFiles(tests);
 	}
 
+	@Test
+    public void testResourceMatcher_dynamic() throws Exception {
+        String[] tests = { "/resourcematcher/test_resourcematcher_dynamic.json"};
+
+        runTestsFromResourceFiles(tests);
+    }
+
+	@Test
+	public void testResourceMatcher_wildcards_as_delimiters() throws Exception {
+		String[] tests = { "/resourcematcher/test_resourcematcher_wildcards_as_delimiters.json"};
+
+		runTestsFromResourceFiles(tests);
+	}
+
 	private void runTestsFromResourceFiles(String[] resourceNames) throws Exception {
 		for(String resourceName : resourceNames) {
 			InputStream       inStream = this.getClass().getResourceAsStream(resourceName);
@@ -97,7 +112,7 @@ public class TestResourceMatcher {
 				}
 
 				boolean expected = oneTest.result;
-				boolean result   = matcher.isMatch(oneTest.input);
+				boolean result   = matcher.isMatch(oneTest.input, oneTest.evalContext);
 
 				assertEquals("isMatch() failed! " + testCase.name + ":" + oneTest.name + ": input=" +
oneTest.input, expected, result);
 			}
@@ -130,6 +145,7 @@ public class TestResourceMatcher {
 			class OneTest {
 				String  name;
 				String  input;
+				Map<String, Object> evalContext;
 				boolean result;
 			}
 		}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/agents-common/src/test/resources/policyengine/test_policyengine_hdfs_resourcespec.json
----------------------------------------------------------------------
diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_hdfs_resourcespec.json
b/agents-common/src/test/resources/policyengine/test_policyengine_hdfs_resourcespec.json
index da0a629..384beb8 100644
--- a/agents-common/src/test/resources/policyengine/test_policyengine_hdfs_resourcespec.json
+++ b/agents-common/src/test/resources/policyengine/test_policyengine_hdfs_resourcespec.json
@@ -5,7 +5,11 @@
     "name":"hdfs",
     "id":1,
     "resources":[
-    {"name":"path","type":"path","level":1,"mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher","matcherOptions":{"wildCard":true,
"ignoreCase":true},"label":"Resource Path","description":"HDFS file or directory path"}
+    {"name":"path","type":"path","level":1,"mandatory":true,"lookupSupported":true,
+      "matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher",
+      "matcherOptions":{"wildCard":true, "ignoreCase":true},
+      "startDelimiterChar": "{", "endDelimiterChar": "}", "escapeChar":"%",
+      "label":"Resource Path","description":"HDFS file or directory path"}
     ],
     "accessTypes":[
       {"name":"read","label":"Read"},
@@ -23,9 +27,33 @@
        {"accesses":[{"type":"read","isAllowed":true}],"users":[],"groups":["finance"],"delegateAdmin":false,
"conditions":[ ] }
      ]
     }
+    ,
+    {"id":2,"name":"allow-read-to-{USER} under /home/{USER}/","isEnabled":true,"isAuditEnabled":false,
+      "resources":{"path":{"values":["/home/{USER}/"],"isRecursive":true}},
+      "policyItems":[
+        {"accesses":[{"type":"read","isAllowed":true}],"users":["{USER}"],"groups":[],"delegateAdmin":false,
"conditions":[ ] }
+      ]
+    }
   ],
 
   "tests":[
+    {"name":"DENY 'read /home/user1/tmp/sales.db' for user=user2",
+      "request":{
+        "resource":{"elements":{"path":"/home/user1/tmp/sales.db"}},
+        "accessType":"read","user":"user2","userGroups":[],"requestData":"DENY read /home/user1/tmp/sales.db
to user2"
+      },
+      "result":{"isAudited":false,"isAllowed":false,"policyId":-1}
+    }
+    ,
+    {"name":"ALLOW 'read /home/user1/tmp/sales.db' for user=user1",
+      "request":{
+        "resource":{"elements":{"path":"/home/user1/tmp/sales.db"}},
+        "accessType":"read","user":"user1","userGroups":[],"requestData":"ALLOW read /home/user1/tmp/sales.db
to user1"
+      },
+      "result":{"isAudited":false,"isAllowed":true,"policyId":2}
+    }
+  ,
+
     {"name":"ALLOW 'read /finance/restricted/tmp/sales.db' for g=finance",
      "request":{
       "resource":{"elements":{"path":"/finance/restricted/tmp/sales.db"}},
@@ -33,6 +61,7 @@
      },
      "result":{"isAudited":true,"isAllowed":true,"policyId":1}
     }
+
   ]
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/agents-common/src/test/resources/resourcematcher/test_resourcematcher_default.json
----------------------------------------------------------------------
diff --git a/agents-common/src/test/resources/resourcematcher/test_resourcematcher_default.json
b/agents-common/src/test/resources/resourcematcher/test_resourcematcher_default.json
index 918c30f..50b4cc3 100644
--- a/agents-common/src/test/resources/resourcematcher/test_resourcematcher_default.json
+++ b/agents-common/src/test/resources/resourcematcher/test_resourcematcher_default.json
@@ -1,5 +1,28 @@
 {
   "testCases":[
+        {
+            "name":"values={USER}_simple, %{USER}_simple; wildCard=true; ignoreCase=true;
startDelimiter={, endDelimiter=}, escapeChar=%",
+            "resourceDef":{
+                "matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
+                "matcherOptions":{"wildCard":true, "ignoreCase":true, "replaceTokens":true,
"tokenDelimiterEscape":"%", "tokenDelimiterPrefix":"rangerToken:" }
+            },
+            "policyResource":{
+                "values": ["{rangerToken:USER}_simple", "simple_{USER}", "{USER}_simple"]
+            },
+            "tests":[
+                { "name":"all-lower","input":"admin_simple", "evalContext": { "token:USER":
"admin"}, "result":true},
+                { "name":"all-upper","input":"{USER}_SIMPLE", "result":true},
+                { "name":"mixed-case","input":"_SiMpLe", "evalContext": { "token:USER": ""},
"result":true},
+                { "name":"invalid-all-lower-wild","input":"other-simple", "result":false},
+                { "name":"invalid-all-upper-wild","input":"OTHER-SIMPLE", "result":false},
+                { "name":"invalid-mixed-case-wild","input":"OtHeR-SiMpLe", "result":false},
+                { "name":"escaped-delimiter","input":"%{USER}_SiMpLe", "evalContext": { "token:USER":
""}, "result":false},
+                { "name":"not-escaped-delimiter-with-evalContext","input":"{USER}_SiMpLe",
"evalContext": { "token:USER": ""}, "result":true},
+                { "name":"not-escaped-delimiter-no-evalContext","input":"{USER}_SiMpLe",
"result":true},
+                { "name":"with-no-prefix","input":"simple_admin", "evalContext": { "token:USER":
"admin"}, "result":false},
+                { "name":"with-no-prefix-straight-match","input":"simple_{USER}", "evalContext":
{ "token:USER": "admin"}, "result":true}
+            ]
+        },
   	{
       "name":"value=simple; wildCard=true; ignoreCase=true",
       "resourceDef":{
@@ -350,4 +373,4 @@
       ]
   	}
   ]
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/agents-common/src/test/resources/resourcematcher/test_resourcematcher_dynamic.json
----------------------------------------------------------------------
diff --git a/agents-common/src/test/resources/resourcematcher/test_resourcematcher_dynamic.json
b/agents-common/src/test/resources/resourcematcher/test_resourcematcher_dynamic.json
new file mode 100644
index 0000000..168a50f
--- /dev/null
+++ b/agents-common/src/test/resources/resourcematcher/test_resourcematcher_dynamic.json
@@ -0,0 +1,33 @@
+{
+  "testCases":[
+	  {
+		  "name":"value=/; isRecursive=false; wildCard=true; ignoreCase=true",
+		  "resourceDef":{
+			  "matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher",
+			  "matcherOptions":{"wildCard":true, "ignoreCase":true, "replaceTokens":true, "tokenDelimiterStart":"%",
"tokenDelimiterEnd":"%", "tokenDelimiterEscape":"@" }
+		  },
+		  "policyResource":{
+			  "values": ["/abc%xyz%w", "/xyz%somestuff%z", "/abc@%xyz@w", "/mad@@%xyy%"],
+			  "isRecursive":false
+		  },
+		  "tests":[
+			  { "name":"exact-path","input":"/mad@new", "evalContext": {"token:xyy": "new"}, "result":true}
+			  ,
+			  { "name":"exact-path","input":"/abcw", "evalContext": {"token:somestuff": "somethingelse"},
"result":true}
+			  ,
+			  { "name":"exact-path","input":"/abc%xyz%w", "evalContext": {"token:somestuff": "somethingelse",
"token:xyz":"abcd"}, "result":false}
+			  ,
+			  { "name":"exact-path","input":"/abcabcdw", "evalContext": {"token:somestuff": "somethingelse",
"token:xyz":"abcd"}, "result":true}
+			  ,
+			  { "name":"exact-path","input":"/xyzsomethingelsez", "evalContext": {"token:somestuff":
"somethingelse"}, "result":true}
+			  ,
+			  { "name":"exact-path","input":"/abc@%xyz@w", "evalContext": {"token:somestuff": "somethingelse"},
"result":false}
+			  ,
+			  { "name":"exact-path","input":"/abc%xyzw", "evalContext": {"token:somestuff": "somethingelse"},
"result":true}
+			  ,
+			  { "name":"exact-path","input":"/abcabcdw", "evalContext": {"token:somestuff": "somethingelse",
"xyz":"abcd"}, "result":false}
+
+		  ]
+	  }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/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 e55ddc1..c67ff45 100644
--- a/agents-common/src/test/resources/resourcematcher/test_resourcematcher_path.json
+++ b/agents-common/src/test/resources/resourcematcher/test_resourcematcher_path.json
@@ -351,4 +351,4 @@
       ]
   	}
   ]
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/agents-common/src/test/resources/resourcematcher/test_resourcematcher_wildcards_as_delimiters.json
----------------------------------------------------------------------
diff --git a/agents-common/src/test/resources/resourcematcher/test_resourcematcher_wildcards_as_delimiters.json
b/agents-common/src/test/resources/resourcematcher/test_resourcematcher_wildcards_as_delimiters.json
new file mode 100644
index 0000000..f896745
--- /dev/null
+++ b/agents-common/src/test/resources/resourcematcher/test_resourcematcher_wildcards_as_delimiters.json
@@ -0,0 +1,28 @@
+{
+  "testCases":[
+	  {
+		  "name":"value=/; isRecursive=false; wildCard=false; ignoreCase=true",
+		  "resourceDef":{
+			  "matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher",
+			  "matcherOptions":{"wildCard":false, "ignoreCase":true, "replaceTokens":true, "tokenDelimiterStart":"*",
"tokenDelimiterEnd":"?", "tokenDelimiterEscape":"@" }
+		  },
+		  "policyResource":{
+			  "values": ["/abc*xyz?w", "/xyz*somestuff?z", "/abc@*xyz@w", "/mad@@*xyy?"],
+			  "isRecursive":false
+		  },
+		  "tests":[
+			  { "name":"exact-path","input":"/abc@*xyz@w", "evalContext": {"token:somestuff": "somethingelse"},
"result":false}
+			  ,
+			  { "name":"exact-path","input":"/mad@new", "evalContext": {"token:xyy": "new"}, "result":true}
+			  ,
+			  { "name":"exact-path","input":"/abcw", "evalContext": {"token:somestuff": "somethingelse"},
"result":true}
+			  ,
+			  { "name":"exact-path","input":"/abc*xyz?w", "evalContext": {"token:somestuff": "somethingelse",
"token:xyz":"abcd"}, "result":false}
+			  ,
+			  { "name":"exact-path","input":"/xyzsomethingelsez", "evalContext": {"token:somestuff":
"somethingelse"}, "result":true}
+			  ,
+			  { "name":"exact-path","input":"/abc*xyzw", "evalContext": {"token:somestuff": "somethingelse"},
"result":true}
+		  ]
+	  }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java b/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java
index 19ddc87..13c2fcf 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java
@@ -347,8 +347,8 @@ public class PublicAPIsv2 {
 	@POST
 	@Path("/api/policy/apply/")
 	@Produces({ "application/json", "application/xml" })
-	public RangerPolicy applyPolicy(RangerPolicy policy) { // new API
-		return serviceREST.applyPolicy(policy);
+	public RangerPolicy applyPolicy(RangerPolicy policy, @Context HttpServletRequest request)
{ // new API
+		return serviceREST.applyPolicy(policy, request);
 	}
 
 	@PUT

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/dc873cb2/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
index 90b146b..26e2906 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
@@ -83,6 +83,7 @@ import org.apache.ranger.plugin.service.ResourceLookupContext;
 import org.apache.ranger.plugin.store.PList;
 import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 import org.apache.ranger.plugin.util.GrantRevokeRequest;
+import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
 import org.apache.ranger.plugin.util.SearchFilter;
 import org.apache.ranger.plugin.util.ServicePolicies;
@@ -889,7 +890,7 @@ public class ServiceREST {
 						throw restErrorUtil.createGrantRevokeRESTException( "User doesn't have necessary permission
to grant access");
 					}
 
-					RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource);
+					RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource, userName);
 	
 					if(policy != null) {
 						boolean policyUpdated = false;
@@ -1001,7 +1002,7 @@ public class ServiceREST {
 					}
 
 					if (isAllowed) {
-						RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource);
+						RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource, userName);
 
 						if(policy != null) {
 							boolean policyUpdated = false;
@@ -1101,7 +1102,7 @@ public class ServiceREST {
 						throw restErrorUtil.createGrantRevokeRESTException("User doesn't have necessary permission
to revoke access");
 					}
 
-					RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource);
+					RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource, userName);
 
 					if(policy != null) {
 						boolean policyUpdated = false;
@@ -1179,7 +1180,7 @@ public class ServiceREST {
 					}
 
 					if (isAllowed) {
-						RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource);
+						RangerPolicy policy = getExactMatchPolicyForResource(serviceName, resource, userName);
 
 						if(policy != null) {
 							boolean policyUpdated = false;
@@ -1313,7 +1314,7 @@ public class ServiceREST {
 	@POST
 	@Path("/policies/apply")
 	@Produces({ "application/json", "application/xml" })
-	public RangerPolicy applyPolicy(RangerPolicy policy) {
+	public RangerPolicy applyPolicy(RangerPolicy policy, @Context HttpServletRequest request)
{
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("==> ServiceREST.applyPolicy(" + policy + ")");
 		}
@@ -1328,7 +1329,8 @@ public class ServiceREST {
 					throw new Exception("Applied policy contains condition(s); not supported:" + policy);
 				}
 
-				RangerPolicy existingPolicy = getExactMatchPolicyForResource(policy.getService(), policy.getResources());
+				String user = request.getRemoteUser();
+				RangerPolicy existingPolicy = getExactMatchPolicyForResource(policy.getService(), policy.getResources(),
StringUtils.isNotBlank(user) ? user :"admin");
 
 				if (existingPolicy == null) {
 					ret = createPolicy(policy, null);
@@ -1959,14 +1961,18 @@ public class ServiceREST {
 		}
 	}
 
-	private RangerPolicy getExactMatchPolicyForResource(String serviceName, RangerAccessResource
resource) throws Exception {
+	private RangerPolicy getExactMatchPolicyForResource(String serviceName, RangerAccessResource
resource, String user) throws Exception {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> ServiceREST.getExactMatchPolicyForResource(" + resource + ")");
+			LOG.debug("==> ServiceREST.getExactMatchPolicyForResource(" + resource + ", " + user
+ ")");
 		}
 
 		RangerPolicy       ret          = null;
 		RangerPolicyEngine policyEngine = getPolicyEngine(serviceName);
-		List<RangerPolicy> policies     = policyEngine != null ? policyEngine.getExactMatchPolicies(resource)
: null;
+
+		Map<String, Object> evalContext = new HashMap<String, Object>();
+		RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
+
+		List<RangerPolicy> policies     = policyEngine != null ? policyEngine.getExactMatchPolicies(resource,
evalContext) : null;
 
 		if(CollectionUtils.isNotEmpty(policies)) {
 			// at this point, ret is a policy in policy-engine; the caller might update the policy
(for grant/revoke); so get a copy from the store
@@ -1974,20 +1980,24 @@ public class ServiceREST {
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== ServiceREST.getExactMatchPolicyForResource(" + resource + "): " + ret);
+			LOG.debug("<== ServiceREST.getExactMatchPolicyForResource(" + resource + ", " + user
+ "): " + ret);
 		}
 
 		return ret;
 	}
 
-	private RangerPolicy getExactMatchPolicyForResource(String serviceName, Map<String, RangerPolicyResource>
resources) throws Exception {
+	private RangerPolicy getExactMatchPolicyForResource(String serviceName, Map<String, RangerPolicyResource>
resources, String user) throws Exception {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> ServiceREST.getExactMatchPolicyForResource(" + resources + ")");
+			LOG.debug("==> ServiceREST.getExactMatchPolicyForResource(" + resources + ", " + user
+ ")");
 		}
 
 		RangerPolicy       ret          = null;
 		RangerPolicyEngine policyEngine = getPolicyEngine(serviceName);
-		List<RangerPolicy> policies     = policyEngine != null ? policyEngine.getExactMatchPolicies(resources)
: null;
+
+		Map<String, Object> evalContext = new HashMap<String, Object>();
+		RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
+
+		List<RangerPolicy> policies     = policyEngine != null ? policyEngine.getExactMatchPolicies(resources,
evalContext) : null;
 
 		if(CollectionUtils.isNotEmpty(policies)) {
 			// at this point, ret is a policy in policy-engine; the caller might update the policy
(for grant/revoke); so get a copy from the store
@@ -1995,7 +2005,7 @@ public class ServiceREST {
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== ServiceREST.getExactMatchPolicyForResource(" + resources + "): " + ret);
+			LOG.debug("<== ServiceREST.getExactMatchPolicyForResource(" + resources + ", " + user
+ "): " + ret);
 		}
 
 		return ret;



Mime
View raw message