You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2016/09/02 00:01:26 UTC

[1/2] incubator-ranger git commit: RANGER-698: updated Ranger policies to support variables like {USER} in resource-names

Repository: incubator-ranger
Updated Branches:
  refs/heads/master a39c00f95 -> c659d9aa7


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

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/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/c659d9aa/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 5e8c540..cb50c9f 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
@@ -326,8 +326,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/c659d9aa/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;



[2/2] incubator-ranger git commit: RANGER-698: updated Ranger policies to support variables like {USER} in resource-names

Posted by ma...@apache.org.
RANGER-698: updated Ranger policies to support variables like {USER} in resource-names

Signed-off-by: Madhan Neethiraj <ma...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/c659d9aa
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/c659d9aa
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/c659d9aa

Branch: refs/heads/master
Commit: c659d9aa711595af9e701210484dc72cd8ff8985
Parents: a39c00f
Author: Abhay Kulkarni <ak...@hortonworks.com>
Authored: Thu Sep 1 07:39:58 2016 -0700
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Thu Sep 1 16:25:20 2016 -0700

----------------------------------------------------------------------
 ...rHiveResourcesAccessedTogetherCondition.java |   2 +-
 ...veResourcesNotAccessedTogetherCondition.java |   2 +-
 .../RangerServiceResourceMatcher.java           |   4 +-
 .../contextenricher/RangerTagEnricher.java      |  10 +-
 .../ranger/plugin/model/RangerServiceDef.java   |   2 +-
 .../plugin/policyengine/RangerPolicyEngine.java |   6 +-
 .../policyengine/RangerPolicyEngineImpl.java    |  21 +-
 .../RangerAbstractPolicyItemEvaluator.java      |   3 +-
 .../RangerCachedPolicyEvaluator.java            |  36 +--
 .../RangerDefaultPolicyEvaluator.java           |  82 +++---
 .../RangerDefaultPolicyItemEvaluator.java       |   8 +-
 .../RangerOptimizedPolicyEvaluator.java         |  22 +-
 .../policyevaluator/RangerPolicyEvaluator.java  |   6 +-
 .../RangerPolicyItemEvaluator.java              |   1 -
 .../RangerDefaultPolicyResourceMatcher.java     |  72 +++---
 .../RangerPolicyResourceMatcher.java            |  14 +-
 .../RangerAbstractResourceMatcher.java          | 248 ++++++++++++-------
 .../RangerDefaultResourceMatcher.java           |  20 +-
 .../RangerPathResourceMatcher.java              |  44 ++--
 .../resourcematcher/RangerResourceMatcher.java  |   8 +-
 .../plugin/resourcematcher/ResourceMatcher.java |  47 +++-
 .../plugin/util/RangerAccessRequestUtil.java    |  20 ++
 .../plugin/util/RangerRequestedResources.java   |   5 +-
 .../ranger/plugin/util/RangerResourceTrie.java  |  24 +-
 .../ranger/plugin/util/ServiceDefUtil.java      |  23 ++
 .../ranger/plugin/util/StringTokenReplacer.java | 126 ++++++++++
 .../RangerAbstractResourceMatcherTest.java      |   6 +-
 .../RangerDefaultResourceMatcherTest.java       |  30 ++-
 .../RangerPathResourceMatcherTest.java          |  40 +--
 .../resourcematcher/TestResourceMatcher.java    |  20 +-
 .../test_policyengine_hdfs_resourcespec.json    |  31 ++-
 .../test_resourcematcher_default.json           |  25 +-
 .../test_resourcematcher_dynamic.json           |  33 +++
 .../test_resourcematcher_path.json              |   2 +-
 ...resourcematcher_wildcards_as_delimiters.json |  28 +++
 .../org/apache/ranger/rest/PublicAPIsv2.java    |   4 +-
 .../org/apache/ranger/rest/ServiceREST.java     |  38 +--
 37 files changed, 809 insertions(+), 304 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesAccessedTogetherCondition.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesAccessedTogetherCondition.java b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesAccessedTogetherCondition.java
index fc9842e..b18e7cd 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesAccessedTogetherCondition.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesAccessedTogetherCondition.java
@@ -72,7 +72,7 @@ public class RangerHiveResourcesAccessedTogetherCondition extends RangerAbstract
 		if (isInitialized && CollectionUtils.isNotEmpty(matchers)) {
 			RangerRequestedResources resources = RangerAccessRequestUtil.getRequestedResourcesFromContext(request.getContext());
 
-			ret = resources == null ? false : !resources.isMutuallyExcluded(matchers);
+			ret = resources == null ? false : !resources.isMutuallyExcluded(matchers, request.getContext());
 		} else {
 			LOG.error("RangerHiveResourcesAccessedTogetherCondition.isMatched() - condition is not initialized correctly and will NOT be enforced");
 		}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesNotAccessedTogetherCondition.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesNotAccessedTogetherCondition.java b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesNotAccessedTogetherCondition.java
index 3b8e009..5036a06 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesNotAccessedTogetherCondition.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerHiveResourcesNotAccessedTogetherCondition.java
@@ -72,7 +72,7 @@ public class RangerHiveResourcesNotAccessedTogetherCondition extends RangerAbstr
 		if (isInitialized && CollectionUtils.isNotEmpty(matchers)) {
 			RangerRequestedResources resources = RangerAccessRequestUtil.getRequestedResourcesFromContext(request.getContext());
 
-			ret = resources == null ? true : resources.isMutuallyExcluded(matchers);
+			ret = resources == null ? true : resources.isMutuallyExcluded(matchers, request.getContext());
 		} else {
 			LOG.error("RangerHiveResourcesNotAccessedTogetherCondition.isMatched() - Enforcer is not initialized correctly, Mutual Exclusion will NOT be enforced");
 		}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerServiceResourceMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerServiceResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerServiceResourceMatcher.java
index cf7b8e7..637423e 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerServiceResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerServiceResourceMatcher.java
@@ -71,8 +71,8 @@ public class RangerServiceResourceMatcher implements RangerPolicyResourceEvaluat
 		return Long.compare(getId(), other.getId());
 	}
 
-	public boolean isMatch(RangerAccessResource requestedResource) {
-		return policyResourceMatcher != null ? policyResourceMatcher.isExactHeadMatch(requestedResource) : false;
+	public boolean isMatch(RangerAccessResource requestedResource, Map<String, Object> evalContext) {
+		return policyResourceMatcher != null ? policyResourceMatcher.isExactHeadMatch(requestedResource, evalContext) : false;
 	}
 
 	RangerServiceDef getServiceDef() {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
index 5b60a53..1a6e1b2 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
@@ -132,7 +132,7 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 			LOG.debug("==> RangerTagEnricher.enrich(" + request + ")");
 		}
 
-		List<RangerTag> matchedTags = findMatchingTags(request.getResource());
+		List<RangerTag> matchedTags = findMatchingTags(request.getResource(), request.getContext());
 
 		RangerAccessRequestUtil.setRequestTagsInContext(request.getContext(), matchedTags);
 
@@ -202,9 +202,9 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 		return ret;
 	}
 
-	private List<RangerTag> findMatchingTags(final RangerAccessResource resource) {
+	private List<RangerTag> findMatchingTags(final RangerAccessResource resource, final Map<String, Object> evalContext) {
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerTagEnricher.findMatchingTags(" + resource + ")");
+			LOG.debug("==> RangerTagEnricher.findMatchingTags(" + resource + ", " + evalContext + ")");
 		}
 
 		List<RangerTag> ret = null;
@@ -216,7 +216,7 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 
 			for (RangerServiceResourceMatcher resourceMatcher : serviceResourceMatchers) {
 
-				boolean matchResult = resourceMatcher.isMatch(resource);
+				boolean matchResult = resourceMatcher.isMatch(resource, evalContext);
 
 				if (matchResult) {
 					if (ret == null) {
@@ -237,7 +237,7 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 		}
 
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerTagEnricher.findMatchingTags(" + resource + ")");
+			LOG.debug("<== RangerTagEnricher.findMatchingTags(" + resource + ", " + evalContext + ")");
 		}
 
 		return ret;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
index f6931b3..2d27961 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
@@ -1260,7 +1260,6 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S
 		private String              rbKeyDescription       = null;
 		private String              rbKeyValidationMessage = null;
 
-
 		public RangerResourceDef() {
 			this(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
 		}
@@ -1931,6 +1930,7 @@ public class RangerServiceDef extends RangerBaseModelObject implements java.io.S
 			result = prime * result + ((name == null) ? 0 : name.hashCode());
 			result = prime * result
 					+ ((rbKeyLabel == null) ? 0 : rbKeyLabel.hashCode());
+
 			return result;
 		}
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java
index a5e92da..698d99a 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngine.java
@@ -37,6 +37,8 @@ public interface RangerPolicyEngine {
 	String AUDIT_NONE = "audit-none";
 	String AUDIT_DEFAULT = "audit-default";
 
+	String USER_CURRENT = "{USER}";
+
 	String getServiceName();
 
 	RangerServiceDef getServiceDef();
@@ -61,9 +63,9 @@ public interface RangerPolicyEngine {
 
 	boolean isAccessAllowed(Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, String accessType);
 
-	List<RangerPolicy> getExactMatchPolicies(RangerAccessResource resource);
+	List<RangerPolicy> getExactMatchPolicies(RangerAccessResource resource, Map<String, Object> evalContext);
 
-	List<RangerPolicy> getExactMatchPolicies(Map<String, RangerPolicyResource> resources);
+	List<RangerPolicy> getExactMatchPolicies(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext);
 
 	List<RangerPolicy> getAllowedPolicies(String user, Set<String> userGroups, String accessType);
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
index 6d3645f..9a63516 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
@@ -198,6 +198,8 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 			((RangerAccessRequestImpl) request).extractAndSetClientIPAddress(useForwardedIPAddress, trustedProxyAddresses);
 		}
 
+		RangerAccessRequestUtil.setCurrentUserInContext(request.getContext(), request.getUser());
+
 		List<RangerContextEnricher> enrichers = allContextEnrichers;
 
 		if(!CollectionUtils.isEmpty(enrichers)) {
@@ -441,15 +443,15 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 	}
 
 	@Override
-	public List<RangerPolicy> getExactMatchPolicies(RangerAccessResource resource) {
+	public List<RangerPolicy> getExactMatchPolicies(RangerAccessResource resource, Map<String, Object> evalContext) {
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerPolicyEngineImpl.getExactMatchPolicies(" + resource + ")");
+			LOG.debug("==> RangerPolicyEngineImpl.getExactMatchPolicies(" + resource + ", " + evalContext + ")");
 		}
 
 		List<RangerPolicy> ret = null;
 
 		for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) {
-			if (evaluator.isCompleteMatch(resource)) {
+			if (evaluator.isCompleteMatch(resource, evalContext)) {
 				if(ret == null) {
 					ret = new ArrayList<RangerPolicy>();
 				}
@@ -459,22 +461,22 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 		}
 
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerPolicyEngineImpl.getExactMatchPolicies(" + resource + "): " + ret);
+			LOG.debug("<== RangerPolicyEngineImpl.getExactMatchPolicies(" + resource + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;
 	}
 
 	@Override
-	public List<RangerPolicy> getExactMatchPolicies(Map<String, RangerPolicyResource> resources) {
+	public List<RangerPolicy> getExactMatchPolicies(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext) {
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerPolicyEngineImpl.getExactMatchPolicies(" + resources + ")");
+			LOG.debug("==> RangerPolicyEngineImpl.getExactMatchPolicies(" + resources + ", " + evalContext + ")");
 		}
 
 		List<RangerPolicy> ret = null;
 
 		for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) {
-			if (evaluator.isCompleteMatch(resources)) {
+			if (evaluator.isCompleteMatch(resources, evalContext)) {
 				if(ret == null) {
 					ret = new ArrayList<RangerPolicy>();
 				}
@@ -484,7 +486,7 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 		}
 
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerPolicyEngineImpl.getExactMatchPolicies(" + resources + "): " + ret);
+			LOG.debug("<== RangerPolicyEngineImpl.getExactMatchPolicies(" + resources + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;
@@ -652,8 +654,6 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 
 					for (RangerPolicyEvaluator evaluator : evaluators) {
 						tagEvalResult.incrementEvaluatedPoliciesCount();
-						if(! evaluator.isMatch(tagEvalRequest.getResource())) 
-							continue;
 
 						evaluator.evaluate(tagEvalRequest, tagEvalResult);
 
@@ -953,6 +953,7 @@ class RangerTagAccessRequest extends RangerAccessRequestImpl {
 
 		RangerAccessRequestUtil.setCurrentTagInContext(request.getContext(), resourceTag);
 		RangerAccessRequestUtil.setCurrentResourceInContext(request.getContext(), request.getResource());
+		RangerAccessRequestUtil.setCurrentUserInContext(request.getContext(), request.getUser());
 
 		super.setContext(requestContext);
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java
index 514884f..b36bc1f 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java
@@ -120,7 +120,8 @@ public abstract class RangerAbstractPolicyItemEvaluator implements RangerPolicyI
 		int evalOrder = RANGER_POLICY_ITEM_EVAL_ORDER_DEFAULT;
 
 		if(policyItem != null) {
-			if(CollectionUtils.isNotEmpty(policyItem.getGroups()) && policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC)) {
+			if((CollectionUtils.isNotEmpty(policyItem.getGroups()) && policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC))
+				|| (CollectionUtils.isNotEmpty(policyItem.getUsers()) && policyItem.getUsers().contains(RangerPolicyEngine.USER_CURRENT))) {
 				evalOrder -= RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_USERSGROUPS;
 			} else {
 				int userGroupCount = 0;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerCachedPolicyEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerCachedPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerCachedPolicyEvaluator.java
index 91a53d8..7711765 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerCachedPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerCachedPolicyEvaluator.java
@@ -26,6 +26,8 @@ import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.policyengine.RangerAccessResource;
 import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
 
+import java.util.Map;
+
 public class RangerCachedPolicyEvaluator extends RangerOptimizedPolicyEvaluator {
     private static final Log LOG = LogFactory.getLog(RangerCachedPolicyEvaluator.class);
 
@@ -47,34 +49,38 @@ public class RangerCachedPolicyEvaluator extends RangerOptimizedPolicyEvaluator
     }
 
     @Override
-    public boolean isMatch(RangerAccessResource resource) {
+    public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
         if (LOG.isDebugEnabled()) {
-            LOG.debug("==> RangerCachedPolicyEvaluator.isMatch(" + resource + ")");
+            LOG.debug("==> RangerCachedPolicyEvaluator.isMatch(" + resource + ", " + evalContext + ")");
         }
 
         boolean result = false;
 
-        // Check in the evaluator-owned cache for the match, if found return. else call super.isMatch(), add result to cache
-        RangerResourceAccessCache.LookupResult lookup = cache.lookup(resource);
+        if (needsDynamicEval()) {
+            result = super.isMatch(resource, evalContext);
+        } else {
+            // Check in the evaluator-owned cache for the match, if found return. else call super.isMatch(), add result to cache
+            RangerResourceAccessCache.LookupResult lookup = cache.lookup(resource);
 
-        if (lookup != RangerResourceAccessCache.LookupResult.IN_NOTMATCHED_CACHE) {
-            // We dont know definitely that this previously not matched
-            if (lookup != RangerResourceAccessCache.LookupResult.IN_MATCHED_CACHE) {
-                result = super.isMatch(resource);
+            if (lookup != RangerResourceAccessCache.LookupResult.IN_NOTMATCHED_CACHE) {
+                // We dont know definitely that this previously not matched
+                if (lookup != RangerResourceAccessCache.LookupResult.IN_MATCHED_CACHE) {
+                    result = super.isMatch(resource, evalContext);
 
-                // update the cache with the result of the match
-                if(result) {
-	                cache.add(resource, RangerResourceAccessCache.CacheType.MATCHED_CACHE);
+                    // update the cache with the result of the match
+                    if (result) {
+                        cache.add(resource, RangerResourceAccessCache.CacheType.MATCHED_CACHE);
+                    } else {
+                        cache.add(resource, RangerResourceAccessCache.CacheType.NOTMATCHED_CACHE);
+                    }
                 } else {
-	                cache.add(resource, RangerResourceAccessCache.CacheType.NOTMATCHED_CACHE);
+                    result = true;
                 }
-            } else {
-                result = true;
             }
         }
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("<== RangerCachedPolicyEvaluator.isMatch(" + resource + "): " + result);
+            LOG.debug("<== RangerCachedPolicyEvaluator.isMatch(" + resource + ", " + evalContext + "): " + result);
         }
 
         return result;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/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 eb46353..867cd20 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
@@ -52,6 +52,7 @@ import org.apache.ranger.plugin.policyengine.RangerRowFilterResult;
 import org.apache.ranger.plugin.policyresourcematcher.RangerDefaultPolicyResourceMatcher;
 import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
 import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
+import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
 import org.apache.ranger.plugin.util.ServiceDefUtil;
 
@@ -70,8 +71,11 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 	private int                             customConditionsCount    = 0;
 	private List<RangerDataMaskPolicyItemEvaluator>  dataMaskEvaluators  = null;
 	private List<RangerRowFilterPolicyItemEvaluator> rowFilterEvaluators = null;
+
 	private String perfTag;
 
+	protected boolean needsDynamicEval() { return resourceMatcher != null ? resourceMatcher.getNeedsDynamicEval() : false; }
+
 	@Override
 	public int getCustomConditionsCount() {
 		return customConditionsCount;
@@ -170,14 +174,14 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
             if (!result.getIsAuditedDetermined()) {
                 // Need to match request.resource first. If it matches (or head matches), then only more progress can be made
                 if (!isResourceMatchAttempted) {
-                    isResourceMatch = isMatch(request.getResource());
+                    isResourceMatch = isMatch(request.getResource(), request.getContext());
                     isResourceMatchAttempted = true;
                 }
 
                 // Try head match only if match was not found and ANY access was requested
                 if (!isResourceMatch) {
                     if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
-                        isResourceHeadMatch = matchResourceHead(request.getResource());
+                        isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
                         isResourceHeadMatchAttempted = true;
                     }
                 }
@@ -196,7 +200,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
                 if (hasMatchablePolicyItem(request)) {
                     // Try Match only if it was not attempted as part of evaluating Audit requirement
                     if (!isResourceMatchAttempted) {
-                        isResourceMatch = isMatch(request.getResource());
+                        isResourceMatch = isMatch(request.getResource(), request.getContext());
                         isResourceMatchAttempted = true;
                     }
 
@@ -204,7 +208,7 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
                     // Audit requirement
                     if (!isResourceMatch) {
                         if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
-                            isResourceHeadMatch = matchResourceHead(request.getResource());
+                            isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
                             isResourceHeadMatchAttempted = true;
                         }
                     }
@@ -245,13 +249,13 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 
 			if (!result.getIsAuditedDetermined()) {
 				if (!isResourceMatchAttempted) {
-					isResourceMatch = isMatch(request.getResource());
+					isResourceMatch = isMatch(request.getResource(), request.getContext());
 					isResourceMatchAttempted = true;
 				}
 
 				if (!isResourceMatch) {
 					if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
-						isResourceHeadMatch = matchResourceHead(request.getResource());
+						isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
 						isResourceHeadMatchAttempted = true;
 					}
 				}
@@ -266,13 +270,13 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 
 			if (!result.getIsAccessDetermined()) {
 				if (!isResourceMatchAttempted) {
-					isResourceMatch = isMatch(request.getResource());
+					isResourceMatch = isMatch(request.getResource(), request.getContext());
 					isResourceMatchAttempted = true;
 				}
 
 				if (!isResourceMatch) {
 					if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
-						isResourceHeadMatch = matchResourceHead(request.getResource());
+						isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
 						isResourceHeadMatchAttempted = true;
 					}
 				}
@@ -312,13 +316,13 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 
 			if (!result.getIsAuditedDetermined()) {
 				if (!isResourceMatchAttempted) {
-					isResourceMatch = isMatch(request.getResource());
+					isResourceMatch = isMatch(request.getResource(), request.getContext());
 					isResourceMatchAttempted = true;
 				}
 
 				if (!isResourceMatch) {
 					if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
-						isResourceHeadMatch = matchResourceHead(request.getResource());
+						isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
 						isResourceHeadMatchAttempted = true;
 					}
 				}
@@ -333,13 +337,13 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 
 			if (!result.getIsAccessDetermined()) {
 				if (!isResourceMatchAttempted) {
-					isResourceMatch = isMatch(request.getResource());
+					isResourceMatch = isMatch(request.getResource(), request.getContext());
 					isResourceMatchAttempted = true;
 				}
 
 				if (!isResourceMatch) {
 					if (attemptResourceHeadMatch && !isResourceHeadMatchAttempted) {
-						isResourceHeadMatch = matchResourceHead(request.getResource());
+						isResourceHeadMatch = matchResourceHead(request.getResource(), request.getContext());
 						isResourceHeadMatchAttempted = true;
 					}
 				}
@@ -358,9 +362,9 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 	}
 
 	@Override
-	public boolean isMatch(RangerAccessResource resource) {
+	public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resource + ")");
+			LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resource + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
@@ -368,32 +372,32 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 		RangerPerfTracer perf = null;
 
 		if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_REQUEST_LOG)) {
-			perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.isMatch(resource=" + resource.getAsString() + "," + perfTag + ")");
+			perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.isMatch(resource=" + resource.getAsString() + "," + evalContext + "," + perfTag + ")");
 		}
 
 		if(resourceMatcher != null) {
-			ret = resourceMatcher.isMatch(resource);
+			ret = resourceMatcher.isMatch(resource, evalContext);
 		}
 
 		RangerPerfTracer.log(perf);
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resource + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resource + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;
 	}
 
 	@Override
-	public boolean isCompleteMatch(RangerAccessResource resource) {
+	public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resource + ")");
+			LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resource + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
 
 		if(resourceMatcher != null) {
-			ret = resourceMatcher.isCompleteMatch(resource);
+			ret = resourceMatcher.isCompleteMatch(resource, evalContext);
 		}
 
 		if(LOG.isDebugEnabled()) {
@@ -404,19 +408,19 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 	}
 
 	@Override
-	public boolean isCompleteMatch(Map<String, RangerPolicyResource> resources) {
+	public boolean isCompleteMatch(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + ")");
+			LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
 
 		if(resourceMatcher != null) {
-			ret = resourceMatcher.isCompleteMatch(resources);
+			ret = resourceMatcher.isCompleteMatch(resources, evalContext);
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;
@@ -428,7 +432,10 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 			LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + resource + ", " + user + ", " + userGroups + ", " + accessType + ")");
 		}
 
-		boolean ret = isAccessAllowed(user, userGroups, accessType) && isMatch(resource);
+		Map<String, Object> evalContext = new HashMap<String, Object>();
+		RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
+
+		boolean ret = isAccessAllowed(user, userGroups, accessType) && isMatch(resource, evalContext);
 		
 		if(LOG.isDebugEnabled()) {
 			LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + resource + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret);
@@ -443,7 +450,10 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 			LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + ")");
 		}
 
-		boolean ret = isAccessAllowed(user, userGroups, accessType) && isMatch(resources);
+		Map<String, Object> evalContext = new HashMap<String, Object>();
+		RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
+
+		boolean ret = isAccessAllowed(user, userGroups, accessType) && isMatch(resources, evalContext);
 		
 		if(LOG.isDebugEnabled()) {
 			LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret);
@@ -458,9 +468,9 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 			LOG.debug("==> RangerDefaultPolicyEvaluator.getResourceAccessInfo(" + request + ", " + result + ")");
 		}
 
-		final boolean isResourceMatch          = isMatch(request.getResource());
+		final boolean isResourceMatch          = isMatch(request.getResource(), request.getContext());
 		final boolean attemptResourceHeadMatch = request.isAccessTypeAny() || request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS;
-		final boolean isResourceHeadMatch      = (!isResourceMatch && attemptResourceHeadMatch) ? matchResourceHead(request.getResource()) : false;
+		final boolean isResourceHeadMatch      = (!isResourceMatch && attemptResourceHeadMatch) ? matchResourceHead(request.getResource(), request.getContext()) : false;
 
 		if(isResourceMatch || isResourceHeadMatch) {
 			if (CollectionUtils.isNotEmpty(allowEvaluators)) {
@@ -643,37 +653,37 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 	}
 
 
-	protected boolean matchResourceHead(RangerAccessResource resource) {
+	protected boolean matchResourceHead(RangerAccessResource resource, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyEvaluator.matchResourceHead(" + resource + ")");
+			LOG.debug("==> RangerDefaultPolicyEvaluator.matchResourceHead(" + resource + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
 
 		if(resourceMatcher != null) {
-			ret = resourceMatcher.isHeadMatch(resource);
+			ret = resourceMatcher.isHeadMatch(resource, evalContext);
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyEvaluator.matchResourceHead(" + resource + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyEvaluator.matchResourceHead(" + resource + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;
 	}
 
-	protected boolean isMatch(Map<String, RangerPolicyResource> resources) {
+	protected boolean isMatch(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resources + ")");
+			LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resources + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
 
 		if(resourceMatcher != null) {
-			ret = resourceMatcher.isMatch(resources);
+			ret = resourceMatcher.isMatch(resources, evalContext);
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resources + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resources + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
index e2c715f..b899dd1 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java
@@ -20,6 +20,7 @@ package org.apache.ranger.plugin.policyevaluator;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 
 import org.apache.commons.collections.CollectionUtils;
@@ -48,6 +49,8 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv
 	private static final Log PERF_POLICYCONDITION_INIT_LOG = RangerPerfTracer.getPerfLogger("policycondition.init");
 	private static final Log PERF_POLICYCONDITION_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policycondition.request");
 
+	private boolean hasCurrentUser = false;
+
 	public RangerDefaultPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, int policyItemType, int policyItemIndex, RangerPolicyEngineOptions options) {
 		super(serviceDef, policy, policyItem, policyItemType, policyItemIndex, options);
 	}
@@ -100,6 +103,9 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv
 			RangerPerfTracer.log(perf);
 		}
 
+		List<String> users = policyItem != null ? policyItem.getUsers() : null;
+		this.hasCurrentUser = CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.USER_CURRENT);
+
 		if(LOG.isDebugEnabled()) {
 			LOG.debug("<== RangerDefaultPolicyItemEvaluator(policyId=" + policyId + ", conditionsCount=" + getConditionEvaluators().size() + ")");
 		}
@@ -172,7 +178,7 @@ public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEv
 
 		if(policyItem != null) {
 			if(!ret && user != null && policyItem.getUsers() != null) {
-				ret = policyItem.getUsers().contains(user);
+				ret = hasCurrentUser || policyItem.getUsers().contains(user);
 			}
 
 			if(!ret && userGroups != null && policyItem.getGroups() != null) {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/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 00b24d1..fb854d0 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
@@ -40,7 +40,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
     private boolean     delegateAdmin  = false;
     private boolean     hasAllPerms    = false;
     private boolean     hasPublicGroup = false;
-
+    private boolean     hasCurrentUser = false;
 
     // For computation of priority
     private static final String RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING   = "*";
@@ -59,7 +59,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
     private static final int RANGER_POLICY_EVAL_SCORE_RESOURCE_DISCOUNT_IS_EXCLUDES                      =  5;
     private static final int RANGER_POLICY_EVAL_SCORE_RESORUCE_DISCOUNT_IS_RECURSIVE                     =  5;
     private static final int RANGER_POLICY_EVAL_SCORE_CUSTOM_CONDITION_PENALTY                           =  5;
-
+    private static final int RANGER_POLICY_EVAL_SCORE_DYNAMIC_RESOURCE_EVAL_PENALTY                      =  20;
 
     @Override
     public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options) {
@@ -77,9 +77,17 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
 
         hasAllPerms = checkIfHasAllPerms();
 
+        for (String user : users) {
+            if (user.equalsIgnoreCase(RangerPolicyEngine.USER_CURRENT)) {
+                hasCurrentUser = true;
+                break;
+            }
+        }
+
         for (String group : groups) {
             if (group.equalsIgnoreCase(RangerPolicyEngine.GROUP_PUBLIC)) {
                 hasPublicGroup = true;
+                break;
             }
         }
 
@@ -185,10 +193,13 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
                 }
             }
         }
+        if (needsDynamicEval()) {
+            evalOrder += RANGER_POLICY_EVAL_SCORE_DYNAMIC_RESOURCE_EVAL_PENALTY;
+        }
 
         evalOrder -= Math.min(RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_RESOURCE, resourceDiscount);
 
-        if (hasPublicGroup) {
+        if (hasPublicGroup || hasCurrentUser) {
             evalOrder -= RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_USERSGROUPS;
         } else {
             evalOrder -= Math.min(groups.size() + users.size(), RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_USERSGROUPS);
@@ -227,7 +238,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
     protected boolean hasMatchablePolicyItem(RangerAccessRequest request) {
         boolean ret = false;
 
-        if (hasPublicGroup || users.contains(request.getUser()) || CollectionUtils.containsAny(groups, request.getUserGroups())) {
+        if (hasPublicGroup || hasCurrentUser || users.contains(request.getUser()) || CollectionUtils.containsAny(groups, request.getUserGroups())) {
             if(request.isAccessTypeDelegatedAdmin()) {
                 ret = delegateAdmin;
             } else if(hasAllPerms) {
@@ -243,7 +254,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
     private boolean hasMatchablePolicyItem(String user, Set<String> userGroups, String accessType) {
         boolean ret = false;
 
-        if (hasPublicGroup || users.contains(user) || CollectionUtils.containsAny(groups, userGroups)) {
+        if (hasPublicGroup || hasCurrentUser || users.contains(user) || CollectionUtils.containsAny(groups, userGroups)) {
             boolean isAdminAccess = StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS);
 
             if(isAdminAccess) {
@@ -276,6 +287,7 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
 
 	            groups.addAll(item.getGroups());
 	            users.addAll(item.getUsers());
+
 	        }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/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 b60e06e..92f1592 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
@@ -71,11 +71,11 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
 
 	void evaluate(RangerAccessRequest request, RangerRowFilterResult result);
 
-	boolean isMatch(RangerAccessResource resource);
+	boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext);
 
-	boolean isCompleteMatch(RangerAccessResource resource);
+	boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext);
 
-	boolean isCompleteMatch(Map<String, RangerPolicyResource> resources);
+	boolean isCompleteMatch(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext);
 
 	boolean isAccessAllowed(RangerAccessResource resource, String user, Set<String> userGroups, String accessType);
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java
index 80e46f5..20b08c8 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyItemEvaluator.java
@@ -47,7 +47,6 @@ public interface RangerPolicyItemEvaluator extends Comparable<RangerPolicyItemEv
 
 	int getEvalOrder();
 
-
 	boolean isMatch(RangerAccessRequest request);
 
 	boolean matchUserGroup(String user, Set<String> userGroups);

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
index 8bde807..5444e2b 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
@@ -48,6 +48,7 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 	protected Map<String, RangerPolicyResource> policyResources = null;
 
 	private Map<String, RangerResourceMatcher> matchers = null;
+	private boolean                            needsDynamicEval = false;
 	private List<RangerResourceDef> firstValidResourceDefHierarchy;
 
 	@Override
@@ -68,6 +69,11 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 	}
 
 	@Override
+	public boolean getNeedsDynamicEval() {
+		return needsDynamicEval;
+	}
+
+	@Override
 	public void init() {
 		if(LOG.isDebugEnabled()) {
 			LOG.debug("==> RangerDefaultPolicyResourceMatcher.init()");
@@ -133,6 +139,9 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 							RangerResourceMatcher matcher = createResourceMatcher(resourceDef, policyResource);
 
 							if (matcher != null) {
+								if (!needsDynamicEval && matcher.getNeedsDynamicEval()) {
+									needsDynamicEval = true;
+								}
 								matchers.put(resourceName, matcher);
 							} else {
 								LOG.error("failed to find matcher for resource " + resourceName);
@@ -189,10 +198,9 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 		return matchers != null ? matchers.get(resourceName) : null;
 	}
 
-	@Override
-	public boolean isMatch(RangerAccessResource resource) {
+	public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isMatch(" + resource + ")");
+			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isMatch(" + resource + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
@@ -211,9 +219,9 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 
 					// when no value exists for a resourceName, consider it a match only if: policy doesn't have a matcher OR matcher allows no-value resource
 					if(StringUtils.isEmpty(resourceValue)) {
-						ret = matcher == null || matcher.isMatch(resourceValue);
+						ret = matcher == null || matcher.isMatch(resourceValue, evalContext);
 					} else {
-						ret = matcher != null && matcher.isMatch(resourceValue);
+						ret = matcher != null && matcher.isMatch(resourceValue, evalContext);
 					}
 
 					if(! ret) {
@@ -228,7 +236,7 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyResourceMatcher.isMatch(" + resource + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyResourceMatcher.isMatch(" + resource  + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;
@@ -236,9 +244,9 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 
 
 	@Override
-	public boolean isMatch(Map<String, RangerPolicyResource> resources) {
+	public boolean isMatch(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isMatch(" + resources + ")");
+			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isMatch(" + resources  + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
@@ -257,10 +265,10 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 
 					// when no value exists for a resourceName, consider it a match only if: policy doesn't have a matcher OR matcher allows no-value resource
 					if(resourceValues == null || CollectionUtils.isEmpty(resourceValues.getValues())) {
-						ret = matcher == null || matcher.isMatch(null);
+						ret = matcher == null || matcher.isMatch(null, null);
 					} else if(matcher != null) {
 						for(String resourceValue : resourceValues.getValues()) {
-							ret = matcher.isMatch(resourceValue);
+							ret = matcher.isMatch(resourceValue, evalContext);
 
 							if(! ret) {
 								break;
@@ -280,16 +288,16 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyResourceMatcher.isMatch(" + resources + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyResourceMatcher.isMatch(" + resources  + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;
 	}
 
 	@Override
-	public boolean isCompleteMatch(RangerAccessResource resource) {
+	public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource + ")");
+			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource  + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
@@ -311,9 +319,9 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 					RangerResourceMatcher matcher       = matchers == null ? null : matchers.get(resourceName);
 
 					if(StringUtils.isEmpty(resourceValue)) {
-						ret = matcher == null || matcher.isCompleteMatch(resourceValue);
+						ret = matcher == null || matcher.isCompleteMatch(resourceValue, evalContext);
 					} else {
-						ret = matcher != null && matcher.isCompleteMatch(resourceValue);
+						ret = matcher != null && matcher.isCompleteMatch(resourceValue, evalContext);
 					}
 
 					if(! ret) {
@@ -328,21 +336,21 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource  + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;
 	}
 
 	@Override
-	public boolean isHeadMatch(RangerAccessResource resource) {
+	public boolean isHeadMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isHeadMatch(" + resource + ")");
+			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isHeadMatch(" + resource + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
-		
+
 		if (matchers == null) {
 
 			LOG.debug("RangerDefaultPolicyResourceMatcher.isHeadMatch(): PolicyResourceMatcher not initialized correctly!!!");
@@ -355,22 +363,22 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 
 		} else {
 
-			ret = newIsHeadMatch(resource);
+			ret = newIsHeadMatch(resource, evalContext);
 
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyResourceMatcher.matchResourceHead(" + resource + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyResourceMatcher.matchResourceHead(" + resource + ", " + evalContext  + "): " + ret);
 		}
 
 		return ret;
 	}
 
 	@Override
-	public boolean isExactHeadMatch(RangerAccessResource resource) {
+	public boolean isExactHeadMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isExactHeadMatch(" + resource + ")");
+			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isExactHeadMatch(" + resource + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
@@ -392,21 +400,21 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 
 		} else {
 
-			ret = newIsHeadMatch(resource);
+			ret = newIsHeadMatch(resource, evalContext);
 
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyResourceMatcher.isExactHeadMatch(" + resource + ")" + ret);
+			LOG.debug("<== RangerDefaultPolicyResourceMatcher.isExactHeadMatch(" + resource + ", " + evalContext + ")" + ret);
 		}
 
 		return ret;
 	}
 
-	private boolean newIsHeadMatch(RangerAccessResource resource) {
+	private boolean newIsHeadMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
 
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyResourceMatcher.newIsHeadMatch(" + resource + ")");
+			LOG.debug("==> RangerDefaultPolicyResourceMatcher.newIsHeadMatch(" + resource + ", " + evalContext + ")");
 		}
 
 		boolean skipped = false;
@@ -424,7 +432,7 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 
 					if (!skipped) {
 
-						matched = matcher.isMatch(resourceValue);
+						matched = matcher.isMatch(resourceValue, evalContext);
 
 					} else {
 
@@ -444,7 +452,7 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 		}
 
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyResourceMatcher.newIsHeadMatch(" + resource + "): " + matched);
+			LOG.debug("<== RangerDefaultPolicyResourceMatcher.newIsHeadMatch(" + resource + ", " + evalContext + "): " + matched);
 		}
 
 		return matched;
@@ -520,9 +528,9 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 	}
 
 	@Override
-	public boolean isCompleteMatch(Map<String, RangerPolicyResource> resources) {
+	public boolean isCompleteMatch(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ")");
+			LOG.debug("==> RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
@@ -561,7 +569,7 @@ public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceM
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
index a8810e5..ea0f36c 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
@@ -40,17 +40,19 @@ public interface RangerPolicyResourceMatcher {
 
 	RangerResourceMatcher getResourceMatcher(String resourceName);
 
-	boolean isMatch(RangerAccessResource resource);
+	boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext);
 
-	boolean isMatch(Map<String, RangerPolicyResource> resources);
+	boolean isMatch(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext);
 
-	boolean isCompleteMatch(RangerAccessResource resource);
+	boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext);
 
-	boolean isHeadMatch(RangerAccessResource resource);
+	boolean isHeadMatch(RangerAccessResource resource, Map<String, Object> evalContext);
 
-	boolean isExactHeadMatch(RangerAccessResource resource);
+	boolean isExactHeadMatch(RangerAccessResource resource, Map<String, Object> evalContext);
 
-	boolean isCompleteMatch(Map<String, RangerPolicyResource> resources);
+	boolean isCompleteMatch(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext);
+
+	boolean getNeedsDynamicEval();
 
 	StringBuilder toString(StringBuilder sb);
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerAbstractResourceMatcher.java
----------------------------------------------------------------------
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 574f2eb..864709c 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
@@ -32,18 +32,21 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
 
 
 public abstract class RangerAbstractResourceMatcher implements RangerResourceMatcher {
 	private static final Log LOG = LogFactory.getLog(RangerAbstractResourceMatcher.class);
 
 	public final static String WILDCARD_ASTERISK = "*";
-	public final static String WILDCARDS = "*?";
 
-	public final static String OPTIONS_SEP        = ";";
-	public final static String OPTION_NV_SEP      = "=";
 	public final static String OPTION_IGNORE_CASE = "ignoreCase";
 	public final static String OPTION_WILD_CARD   = "wildCard";
+	public final static String OPTION_REPLACE_TOKENS         = "replaceTokens";
+	public final static String OPTION_TOKEN_DELIMITER_START  = "tokenDelimiterStart";
+	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";
 
 	protected RangerResourceDef    resourceDef    = null;
 	protected RangerPolicyResource policyResource = null;
@@ -51,10 +54,16 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
 	protected boolean      optIgnoreCase = false;
 	protected boolean      optWildCard   = false;
 
-	protected List<String> policyValues     = null;
-	protected boolean      policyIsExcludes = false;
-	protected boolean      isMatchAny       = false;
-	protected List<ResourceMatcher> resourceMatchers = null;
+	protected List<String> policyValues = null;
+	protected boolean policyIsExcludes = false;
+	protected boolean isMatchAny = false;
+	protected ResourceMatcherWrapper resourceMatchers = null;
+
+	protected boolean optReplaceTokens   = false;
+	protected char    startDelimiterChar = '{';
+	protected char    endDelimiterChar   = '}';
+	protected char    escapeChar         = '\\';
+	protected String  tokenPrefix        = "";
 
 	@Override
 	public void setResourceDef(RangerResourceDef resourceDef) {
@@ -72,13 +81,15 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
 			LOG.debug("==> RangerAbstractResourceMatcher.init()");
 		}
 
-		optIgnoreCase = getBooleanOption(OPTION_IGNORE_CASE, true);
-		optWildCard   = getBooleanOption(OPTION_WILD_CARD, true);
+		Map<String, String> options = resourceDef != null ? resourceDef.getMatcherOptions() : null;
+
+		optIgnoreCase = getOptionIgnoreCase(options);
+		optWildCard   = getOptionWildCard(options);
 
-		policyValues     = new ArrayList<String>();
+		policyValues = new ArrayList<String>();
 		policyIsExcludes = policyResource == null ? false : policyResource.getIsExcludes();
 
-		if(policyResource != null && policyResource.getValues() != null) {
+		if (policyResource != null && policyResource.getValues() != null) {
 			for (String policyValue : policyResource.getValues()) {
 				if (StringUtils.isEmpty(policyValue)) {
 					continue;
@@ -86,8 +97,35 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
 				policyValues.add(policyValue);
 			}
 		}
+
+		optReplaceTokens = getOptionReplaceTokens(options);
+
+		if(optReplaceTokens) {
+			startDelimiterChar = getOptionDelimiterStart(options);
+			endDelimiterChar   = getOptionDelimiterEnd(options);
+			escapeChar         = getOptionDelimiterEscape(options);
+			tokenPrefix        = getOptionDelimiterPrefix(options);
+
+			if(escapeChar == startDelimiterChar || escapeChar == endDelimiterChar ||
+					tokenPrefix.indexOf(escapeChar) != -1 || tokenPrefix.indexOf(startDelimiterChar) != -1 ||
+					tokenPrefix.indexOf(endDelimiterChar) != -1) {
+				String resouceName = resourceDef == null ? "" : resourceDef.getName();
+
+				String msg = "Invalid token-replacement parameters for resource '" + resouceName + "': { ";
+				msg += (OPTION_TOKEN_DELIMITER_START + "='" + startDelimiterChar + "'; ");
+				msg += (OPTION_TOKEN_DELIMITER_END + "='" + endDelimiterChar + "'; ");
+				msg += (OPTION_TOKEN_DELIMITER_ESCAPE + "='" + escapeChar + "'; ");
+				msg += (OPTION_TOKEN_DELIMITER_PREFIX + "='" + tokenPrefix + "' }. ");
+				msg += "Token replacement disabled";
+
+				LOG.error(msg);
+
+				optReplaceTokens = false;
+			}
+		}
+
 		resourceMatchers = buildResourceMatchers();
-		isMatchAny = CollectionUtils.isEmpty(resourceMatchers);
+		isMatchAny = resourceMatchers == null || CollectionUtils.isEmpty(resourceMatchers.getResourceMatchers());
 
 		if(LOG.isDebugEnabled()) {
 			LOG.debug("<== RangerAbstractResourceMatcher.init()");
@@ -97,31 +135,66 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
 	@Override
 	public boolean isMatchAny() { return isMatchAny; }
 
-	protected List<ResourceMatcher> buildResourceMatchers() {
-		List<ResourceMatcher> ret = new ArrayList<ResourceMatcher> ();
+	public boolean getNeedsDynamicEval() {
+		return resourceMatchers != null && resourceMatchers.getNeedsDynamicEval();
+	}
+
+	public static boolean getOptionIgnoreCase(Map<String, String> options) {
+		return ServiceDefUtil.getBooleanOption(options, OPTION_IGNORE_CASE, true);
+	}
+
+	public static boolean getOptionWildCard(Map<String, String> options) {
+		return ServiceDefUtil.getBooleanOption(options, OPTION_WILD_CARD, true);
+	}
+
+	public static boolean getOptionReplaceTokens(Map<String, String> options) {
+		return ServiceDefUtil.getBooleanOption(options, OPTION_REPLACE_TOKENS, true);
+	}
+
+	public static char getOptionDelimiterStart(Map<String, String> options) {
+		return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_START, '{');
+	}
+
+	public static char getOptionDelimiterEnd(Map<String, String> options) {
+		return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_END, '}');
+	}
+
+	public static char getOptionDelimiterEscape(Map<String, String> options) {
+		return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_ESCAPE, '\\');
+	}
+
+	public static String getOptionDelimiterPrefix(Map<String, String> options) {
+		return ServiceDefUtil.getOption(options, OPTION_TOKEN_DELIMITER_PREFIX, "");
+	}
+	protected ResourceMatcherWrapper buildResourceMatchers() {
+		List<ResourceMatcher> resourceMatchers = new ArrayList<ResourceMatcher>();
+		boolean needsDynamicEval = false;
 
 		for (String policyValue : policyValues) {
 			ResourceMatcher matcher = getMatcher(policyValue);
 
 			if (matcher != null) {
 				if (matcher.isMatchAny()) {
-					ret.clear();
+					resourceMatchers.clear();
 					break;
-				} else {
-					ret.add(matcher);
 				}
+				if (!needsDynamicEval && matcher.getNeedsDynamicEval()) {
+					needsDynamicEval = true;
+				}
+				resourceMatchers.add(matcher);
 			}
 		}
 
-		Collections.sort(ret);
+		Collections.sort(resourceMatchers);
 
-		return ret;
+		return CollectionUtils.isNotEmpty(resourceMatchers) ?
+				new ResourceMatcherWrapper(needsDynamicEval, resourceMatchers) : null;
 	}
 
 	@Override
-	public boolean isCompleteMatch(String resource) {
+	public boolean isCompleteMatch(String resource, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerAbstractResourceMatcher.isCompleteMatch(" + resource + ")");
+			LOG.debug("==> RangerAbstractResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
@@ -130,7 +203,7 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
 			ret = StringUtils.isEmpty(resource);
 		} else if(policyValues.size() == 1) {
 			String policyValue = policyValues.get(0);
-			
+
 			if(isMatchAny) {
 				ret = StringUtils.containsOnly(resource, WILDCARD_ASTERISK);
 			} else {
@@ -143,53 +216,7 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerAbstractResourceMatcher.isCompleteMatch(" + resource + "): " + ret);
-		}
-
-		return ret;
-	}
-
-
-	public String getOption(String name) {
-		String ret = null;
-
-		Map<String, String> options = resourceDef != null ? resourceDef.getMatcherOptions() : null;
-
-		if(options != null && name != null) {
-			ret = options.get(name);
-		}
-
-		return ret;
-	}
-
-	public String getOption(String name, String defaultValue) {
-		String ret = defaultValue;
-		String val = getOption(name);
-
-		if(val != null) {
-			ret = val;
-		}
-
-		return ret;
-	}
-
-	public boolean getBooleanOption(String name, boolean defaultValue) {
-		boolean ret = defaultValue;
-		String  val = getOption(name);
-
-		if(val != null) {
-			ret = Boolean.parseBoolean(val);
-		}
-
-		return ret;
-	}
-
-	public char getCharOption(String name, char defaultValue) {
-		char   ret = defaultValue;
-		String val = getOption(name);
-
-		if(! StringUtils.isEmpty(val)) {
-			ret = val.charAt(0);
+			LOG.debug("<== RangerAbstractResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;
@@ -234,7 +261,7 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
 		sb.append("options={");
 		if(resourceDef != null && resourceDef.getMatcherOptions() != null) {
 			for(Map.Entry<String, String> e : resourceDef.getMatcherOptions().entrySet()) {
-				sb.append(e.getKey()).append("=").append(e.getValue()).append(OPTIONS_SEP);
+				sb.append(e.getKey()).append("=").append(e.getValue()).append(';');
 			}
 		}
 		sb.append("} ");
@@ -320,6 +347,10 @@ public abstract class RangerAbstractResourceMatcher implements RangerResourceMat
 			ret = optIgnoreCase ? new CaseInsensitiveStartsWithMatcher(matchStr) : new CaseSensitiveStartsWithMatcher(matchStr);
 		}
 
+		if(optReplaceTokens) {
+			ret.setDelimiters(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix);
+		}
+
 		return ret;
 	}
 }
@@ -329,19 +360,21 @@ final class CaseSensitiveStringMatcher extends ResourceMatcher {
 		super(value);
 	}
 
-	boolean isMatch(String str) {
-		return StringUtils.equals(str, value);
+	@Override
+	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+		return StringUtils.equals(resourceValue, getExpandedValue(evalContext));
 	}
-	int getPriority() { return 1;}
+	int getPriority() { return 1 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
 }
 
 final class CaseInsensitiveStringMatcher extends ResourceMatcher {
 	CaseInsensitiveStringMatcher(String value) { super(value); }
 
-	boolean isMatch(String str) {
-		return StringUtils.equalsIgnoreCase(str, value);
+	@Override
+	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+		return StringUtils.equalsIgnoreCase(resourceValue, getExpandedValue(evalContext));
 	}
-	int getPriority() {return 2; }
+	int getPriority() {return 2 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
 final class CaseSensitiveStartsWithMatcher extends ResourceMatcher {
@@ -349,19 +382,21 @@ final class CaseSensitiveStartsWithMatcher extends ResourceMatcher {
 		super(value);
 	}
 
-	boolean isMatch(String str) {
-		return StringUtils.startsWith(str, value);
+	@Override
+	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+		return StringUtils.startsWith(resourceValue, getExpandedValue(evalContext));
 	}
-	int getPriority() { return 3;}
+	int getPriority() { return 3 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
 }
 
 final class CaseInsensitiveStartsWithMatcher extends ResourceMatcher {
 	CaseInsensitiveStartsWithMatcher(String value) { super(value); }
 
-	boolean isMatch(String str) {
-		return StringUtils.startsWithIgnoreCase(str, value);
+	@Override
+	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+		return StringUtils.startsWithIgnoreCase(resourceValue, getExpandedValue(evalContext));
 	}
-	int getPriority() { return 4; }
+	int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
 final class CaseSensitiveEndsWithMatcher extends ResourceMatcher {
@@ -369,10 +404,11 @@ final class CaseSensitiveEndsWithMatcher extends ResourceMatcher {
 		super(value);
 	}
 
-	boolean isMatch(String str) {
-		return StringUtils.endsWith(str, value);
+	@Override
+	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+		return StringUtils.endsWith(resourceValue, getExpandedValue(evalContext));
 	}
-	int getPriority() { return 3; }
+	int getPriority() { return 3 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
 final class CaseInsensitiveEndsWithMatcher extends ResourceMatcher {
@@ -380,10 +416,11 @@ final class CaseInsensitiveEndsWithMatcher extends ResourceMatcher {
 		super(value);
 	}
 
-	boolean isMatch(String str) {
-		return StringUtils.endsWithIgnoreCase(str, value);
+	@Override
+	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+		return StringUtils.endsWithIgnoreCase(resourceValue, getExpandedValue(evalContext));
 	}
-	int getPriority() { return 4; }
+	int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
 final class CaseSensitiveWildcardMatcher extends ResourceMatcher {
@@ -391,10 +428,11 @@ final class CaseSensitiveWildcardMatcher extends ResourceMatcher {
 		super(value);
 	}
 
-	boolean isMatch(String str) {
-		return FilenameUtils.wildcardMatch(str, value, IOCase.SENSITIVE);
+	@Override
+	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+		return FilenameUtils.wildcardMatch(resourceValue, getExpandedValue(evalContext), IOCase.SENSITIVE);
 	}
-	int getPriority() { return 5; }
+	int getPriority() { return 5 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
 
@@ -403,10 +441,32 @@ final class CaseInsensitiveWildcardMatcher extends ResourceMatcher {
 		super(value);
 	}
 
-	boolean isMatch(String str) {
-		return FilenameUtils.wildcardMatch(str, value, IOCase.INSENSITIVE);
+	@Override
+	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+		return FilenameUtils.wildcardMatch(resourceValue, getExpandedValue(evalContext), IOCase.INSENSITIVE);
 	}
-	int getPriority() {return 6; }
+	int getPriority() {return 6 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
+}
+
+final class ResourceMatcherWrapper {
+	private final boolean needsDynamicEval;
+	private final List<ResourceMatcher> resourceMatchers;
 
+	ResourceMatcherWrapper() {
+		this(false, null);
+	}
+
+	ResourceMatcherWrapper(boolean needsDynamicEval, List<ResourceMatcher> resourceMatchers) {
+		this.needsDynamicEval = needsDynamicEval;
+		this.resourceMatchers = resourceMatchers;
+	}
+
+	boolean getNeedsDynamicEval() {
+		return needsDynamicEval;
+	}
+
+	List<ResourceMatcher> getResourceMatchers() {
+		return resourceMatchers;
+	}
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcher.java
index 0a11be0..c1508bf 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerDefaultResourceMatcher.java
@@ -20,18 +20,19 @@
 package org.apache.ranger.plugin.resourcematcher;
 
 
-import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import java.util.Map;
+
 
 public class RangerDefaultResourceMatcher extends RangerAbstractResourceMatcher {
 	private static final Log LOG = LogFactory.getLog(RangerDefaultResourceMatcher.class);
 
 	@Override
-	public boolean isMatch(String resource) {
+	public boolean isMatch(String resource, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultResourceMatcher.isMatch(" + resource + ")");
+			LOG.debug("==> RangerDefaultResourceMatcher.isMatch(" + resource + ", " + evalContext + ")");
 		}
 
 		boolean ret = false;
@@ -40,14 +41,13 @@ public class RangerDefaultResourceMatcher extends RangerAbstractResourceMatcher
 		if(allValuesRequested || isMatchAny) {
 			ret = isMatchAny;
 		} else {
-			if (CollectionUtils.isNotEmpty(resourceMatchers)) {
-				for (ResourceMatcher resourceMatcher : resourceMatchers) {
-					ret = resourceMatcher.isMatch(resource);
-					if (ret) {
-						break;
-					}
+			for (ResourceMatcher resourceMatcher : resourceMatchers.getResourceMatchers()) {
+				ret = resourceMatcher.isMatch(resource, evalContext);
+				if (ret) {
+					break;
 				}
 			}
+
 		}
 
 		ret = applyExcludes(allValuesRequested, ret);
@@ -67,7 +67,7 @@ public class RangerDefaultResourceMatcher extends RangerAbstractResourceMatcher
 		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultResourceMatcher.isMatch(" + resource + "): " + ret);
+			LOG.debug("<== RangerDefaultResourceMatcher.isMatch(" + resource + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/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 d508f3f..fec527f 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
@@ -19,16 +19,19 @@
 
 package org.apache.ranger.plugin.resourcematcher;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOCase;
 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.util.ServiceDefUtil;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 
 public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher {
@@ -46,8 +49,10 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher {
 			LOG.debug("==> RangerPathResourceMatcher.init()");
 		}
 
+		Map<String, String> options = resourceDef == null ? null : resourceDef.getMatcherOptions();
+
 		policyIsRecursive = policyResource == null ? false : policyResource.getIsRecursive();
-		pathSeparatorChar = getCharOption(OPTION_PATH_SEPARATOR, DEFAULT_PATH_SEPARATOR_CHAR);
+		pathSeparatorChar = ServiceDefUtil.getCharOption(options, OPTION_PATH_SEPARATOR, DEFAULT_PATH_SEPARATOR_CHAR);
 
 		super.init();
 
@@ -57,8 +62,10 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher {
 	}
 
 	@Override
-	protected List<ResourceMatcher> buildResourceMatchers() {
-		List<ResourceMatcher> ret = new ArrayList<ResourceMatcher>();
+
+	protected ResourceMatcherWrapper buildResourceMatchers() {
+		List<ResourceMatcher> resourceMatchers = new ArrayList<ResourceMatcher>();
+		boolean needsDynamicEval = false;
 
 		for (String policyValue : policyValues) {
 			if (optWildCard && policyIsRecursive) {
@@ -71,17 +78,20 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher {
 
 			if (matcher != null) {
 				if (matcher.isMatchAny()) {
-					ret.clear();
+					resourceMatchers.clear();
 					break;
-				} else {
-					ret.add(matcher);
 				}
+				if (!needsDynamicEval && matcher.getNeedsDynamicEval()) {
+					needsDynamicEval = true;
+				}
+				resourceMatchers.add(matcher);
 			}
 		}
 
-		Collections.sort(ret);
+		Collections.sort(resourceMatchers);
 
-		return ret;
+		return CollectionUtils.isNotEmpty(resourceMatchers) ?
+				new ResourceMatcherWrapper(needsDynamicEval, resourceMatchers) : null;
 	}
 
 	@Override
@@ -118,6 +128,8 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher {
 			ret = optIgnoreCase ? new CaseInsensitiveStartsWithMatcher(policyValue) : new CaseSensitiveStartsWithMatcher(policyValue);
 		}
 
+		ret.setDelimiters(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix);
+
 		return ret;
 	}
 
@@ -152,7 +164,6 @@ public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher {
 				ret = FilenameUtils.wildcardMatch(pathToCheck, wildcardPath, caseSensitivity) ;
 			}
 		}
-
 		return ret;
 	}
 
@@ -177,10 +188,11 @@ final class CaseSensitiveRecursiveWildcardMatcher extends ResourceMatcher {
 		this.levelSeparatorChar = levelSeparatorChar;
 	}
 
-	boolean isMatch(String str) {
-		return RangerPathResourceMatcher.isRecursiveWildCardMatch(str, value, levelSeparatorChar, IOCase.SENSITIVE);
+	@Override
+	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+		return RangerPathResourceMatcher.isRecursiveWildCardMatch(resourceValue, getExpandedValue(evalContext), levelSeparatorChar, IOCase.SENSITIVE);
 	}
-	int getPriority() { return 7;}
+	int getPriority() { return 7 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
 }
 
 final class CaseInsensitiveRecursiveWildcardMatcher extends ResourceMatcher {
@@ -190,10 +202,10 @@ final class CaseInsensitiveRecursiveWildcardMatcher extends ResourceMatcher {
 		this.levelSeparatorChar = levelSeparatorChar;
 	}
 
-	boolean isMatch(String str) {
-		return RangerPathResourceMatcher.isRecursiveWildCardMatch(str, value, levelSeparatorChar, IOCase.INSENSITIVE);
+	@Override
+	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
+		return RangerPathResourceMatcher.isRecursiveWildCardMatch(resourceValue, getExpandedValue(evalContext), levelSeparatorChar, IOCase.INSENSITIVE);
 	}
-	int getPriority() { return 8;}
+	int getPriority() { return 8 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
 
 }
-

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerResourceMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerResourceMatcher.java
index 8f1cebe..c1d8366 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerResourceMatcher.java
@@ -22,6 +22,8 @@ package org.apache.ranger.plugin.resourcematcher;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 
+import java.util.Map;
+
 public interface RangerResourceMatcher {
 	void setResourceDef(RangerResourceDef resourceDef);
 
@@ -31,8 +33,10 @@ public interface RangerResourceMatcher {
 
 	boolean isMatchAny();
 
-	boolean isMatch(String resource);
+	boolean isMatch(String resource, Map<String, Object> evalContext);
+
+	boolean isCompleteMatch(String resource, Map<String, Object> evalContext);
 
-	boolean isCompleteMatch(String resource);
+	boolean getNeedsDynamicEval();
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
index 39eb339..853c525 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
@@ -19,16 +19,31 @@
 
 package org.apache.ranger.plugin.resourcematcher;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.util.StringTokenReplacer;
+
+import java.util.Map;
+
 abstract class ResourceMatcher implements Comparable<ResourceMatcher> {
+    private static final Log LOG = LogFactory.getLog(ResourceMatcher.class);
+
     protected final String value;
+    protected StringTokenReplacer tokenReplacer;
+
+    static final int DYNAMIC_EVALUATION_PENALTY = 8;
 
     ResourceMatcher(String value) { this.value = value; }
 
-    abstract boolean isMatch(String str);
+    abstract boolean isMatch(String resourceValue, Map<String, Object> evalContext);
     abstract int getPriority();
 
     boolean isMatchAny() { return value != null && value.length() == 0; }
 
+    boolean getNeedsDynamicEval() {
+        return tokenReplacer != null;
+    }
+
     @Override
     public int compareTo(ResourceMatcher other) { return Integer.compare(getPriority(), other.getPriority()); }
 
@@ -36,4 +51,32 @@ abstract class ResourceMatcher implements Comparable<ResourceMatcher> {
     public String toString() {
         return this.getClass().getName() + "(" + this.value + ")";
     }
-}
\ No newline at end of file
+
+    void setDelimiters(char startDelimiterChar, char endDelimiterChar, char escapeChar, String tokenPrefix) {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("==> setDelimiters(value= " + value + ", startDelimiter=" + startDelimiterChar +
+                    ", endDelimiter=" + endDelimiterChar + ", escapeChar=" + escapeChar + ", prefix=" + tokenPrefix);
+        }
+
+        if(value != null && (value.indexOf(escapeChar) != -1 || (value.indexOf(startDelimiterChar) != -1 && value.indexOf(endDelimiterChar) != -1))) {
+            tokenReplacer = new StringTokenReplacer(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix);
+        }
+
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("<== setDelimiters(value= " + value + ", startDelimiter=" + startDelimiterChar +
+                    ", endDelimiter=" + endDelimiterChar + ", escapeChar=" + escapeChar + ", prefix=" + tokenPrefix);
+        }
+    }
+
+    String getExpandedValue(Map<String, Object> evalContext) {
+        final String ret;
+
+        if(tokenReplacer != null) {
+            ret = tokenReplacer.replaceTokens(value, evalContext);
+        } else {
+            ret = value;
+        }
+
+        return ret;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
index 0ce3721..2f3a39e 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
@@ -37,6 +37,8 @@ public class RangerAccessRequestUtil {
 	public static final String KEY_CONTEXT_TAG_OBJECT          = "TAG_OBJECT";
 	public static final String KEY_CONTEXT_RESOURCE            = "RESOURCE";
 	public static final String KEY_CONTEXT_REQUESTED_RESOURCES = "REQUESTED_RESOURCES";
+	public static final String KEY_TOKEN_NAMESPACE = "token:";
+	public static final String KEY_USER = "USER";
 
 	public static void setRequestTagsInContext(Map<String, Object> context, List<RangerTag> tags) {
 		if(CollectionUtils.isEmpty(tags)) {
@@ -125,4 +127,22 @@ public class RangerAccessRequestUtil {
 
 		return ret;
 	}
+
+	public static void setCurrentUserInContext(Map<String, Object> context, String user) {
+		setTokenInContext(context, KEY_USER, user);
+	}
+
+	public static String getCurrentUserFromContext(Map<String, Object> context) {
+		Object ret = getTokenFromContext(context, KEY_USER);
+		return ret != null ? ret.toString() : "";
+	}
+
+	public static void setTokenInContext(Map<String, Object> context, String tokenName, Object tokenValue) {
+		String tokenNameWithNamespace = KEY_TOKEN_NAMESPACE + tokenName;
+		context.put(tokenNameWithNamespace, tokenValue);
+	}
+	public static Object getTokenFromContext(Map<String, Object> context, String tokenName) {
+		String tokenNameWithNamespace = KEY_TOKEN_NAMESPACE + tokenName;
+		return MapUtils.isNotEmpty(context) ? context.get(tokenNameWithNamespace) : null;
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/c659d9aa/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRequestedResources.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRequestedResources.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRequestedResources.java
index 0f10deb..cb3b84a 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRequestedResources.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerRequestedResources.java
@@ -31,6 +31,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlRootElement;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 @JsonAutoDetect(getterVisibility= JsonAutoDetect.Visibility.NONE, setterVisibility= JsonAutoDetect.Visibility.NONE, fieldVisibility= JsonAutoDetect.Visibility.ANY)
 @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL )
@@ -67,7 +68,7 @@ public class RangerRequestedResources {
 		}
 	}
 
-	public boolean isMutuallyExcluded(final List<RangerPolicyResourceMatcher> matchers) {
+	public boolean isMutuallyExcluded(final List<RangerPolicyResourceMatcher> matchers, final Map<String, Object> evalContext) {
 		boolean ret = true;
 
 		int matchedCount = 0;
@@ -78,7 +79,7 @@ public class RangerRequestedResources {
 
 				for (RangerPolicyResourceMatcher matcher : matchers) {
 
-					if (matcher.isMatch(resource) && matchedCount++ > 0) {
+					if (matcher.isMatch(resource, evalContext) && matchedCount++ > 0) {
 						ret = false;
 						break;
 					}