This is an automated email from the ASF dual-hosted git repository.

madhan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new f33a88a90 RANGER-4165: support SELF_OR_PREFIX resource matching scope
f33a88a90 is described below

commit f33a88a90318ecd06fbdfeea10f65d709c3b9100
Author: Madhan Neethiraj <[email protected]>
AuthorDate: Sun May 14 15:51:06 2023 -0700

    RANGER-4165: support SELF_OR_PREFIX resource matching scope
---
 .../RangerServiceResourceMatcher.java              |   5 +-
 .../plugin/contextenricher/RangerTagEnricher.java  |   7 +-
 .../plugin/policyengine/RangerAccessRequest.java   |  13 +-
 .../policyengine/RangerAccessRequestImpl.java      |  11 ++
 .../policyengine/RangerAccessRequestReadOnly.java  |   3 +
 .../policyengine/RangerAccessRequestWrapper.java   |   3 +
 .../policyengine/RangerPolicyEngineImpl.java       |   4 +-
 .../policyengine/RangerPolicyRepository.java       |   2 +-
 .../plugin/policyengine/RangerResourceTrie.java    |  88 +++++++--
 .../RangerAuditPolicyEvaluator.java                |   2 +-
 .../RangerDefaultPolicyEvaluator.java              |   8 +-
 .../RangerDefaultPolicyResourceMatcher.java        |  39 +++-
 .../RangerPolicyResourceMatcher.java               |  11 ++
 .../RangerAbstractResourceMatcher.java             |  69 ++++---
 .../RangerDefaultResourceMatcher.java              |  20 +-
 .../resourcematcher/RangerPathResourceMatcher.java | 215 +++++++++++++--------
 .../resourcematcher/RangerResourceMatcher.java     |   3 +-
 .../resourcematcher/RangerURLResourceMatcher.java  |  20 +-
 .../plugin/resourcematcher/ResourceMatcher.java    |  53 +++--
 .../util/RangerResourceEvaluatorsRetriever.java    |  12 +-
 .../plugin/policyengine/TestPathResourceTrie.java  |  22 ++-
 .../plugin/policyengine/TestPolicyEngine.java      |  14 ++
 .../RangerAbstractResourceMatcherTest.java         |   3 +-
 .../RangerDefaultResourceMatcherTest.java          |   3 +-
 .../RangerPathResourceMatcherTest.java             |   7 +-
 .../RangerURLResourceMatcherTest.java              |   3 +-
 .../resourcematcher/TestResourceMatcher.java       |   3 +-
 .../test/resources/policyengine/aws_s3_tags.json   |  33 ++++
 .../policyengine/test_policyengine_aws.json        |  24 +--
 .../policyengine/test_policyengine_aws_s3.json     | 211 ++++++++++++++++++++
 .../policyengine/test_policyengine_kafka.json      | 157 +++++++++++++++
 31 files changed, 873 insertions(+), 195 deletions(-)

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 465d7d375..e696db518 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
@@ -22,6 +22,7 @@ package org.apache.ranger.plugin.contextenricher;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceResource;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.apache.ranger.plugin.policyengine.RangerAccessResource;
 import 
org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
 import org.apache.ranger.plugin.policyresourcematcher.RangerResourceEvaluator;
@@ -70,8 +71,8 @@ public class RangerServiceResourceMatcher implements 
RangerResourceEvaluator {
                return 
ServiceDefUtil.isAncestorOf(policyResourceMatcher.getServiceDef(), 
leafResourceDef, resourceDef);
        }
 
-       public RangerPolicyResourceMatcher.MatchType 
getMatchType(RangerAccessResource requestedResource, Map<String, Object> 
evalContext) {
-               return policyResourceMatcher != null ?  
policyResourceMatcher.getMatchType(requestedResource, evalContext) : 
RangerPolicyResourceMatcher.MatchType.NONE;
+       public RangerPolicyResourceMatcher.MatchType 
getMatchType(RangerAccessResource requestedResource, Map<String, 
ResourceElementMatchingScope> scopes, Map<String, Object> evalContext) {
+               return policyResourceMatcher != null ? 
policyResourceMatcher.getMatchType(requestedResource, scopes, evalContext) : 
RangerPolicyResourceMatcher.MatchType.NONE;
        }
 
        static class IdComparator implements 
Comparator<RangerServiceResourceMatcher>, Serializable {
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 e0a86c398..b5428cfdf 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
@@ -564,7 +564,7 @@ public class RangerTagEnricher extends 
RangerAbstractContextEnricher {
                                List<RangerServiceResourceMatcher> notMatched = 
new ArrayList<>();
 
                                for (RangerServiceResourceMatcher 
resourceMatcher : oldMatchers) {
-                                       final 
RangerPolicyResourceMatcher.MatchType matchType = 
resourceMatcher.getMatchType(accessResource, request.getContext());
+                                       final 
RangerPolicyResourceMatcher.MatchType matchType = 
resourceMatcher.getMatchType(accessResource, 
request.getResourceElementMatchingScopes(), request.getContext());
 
                                        if (LOG.isDebugEnabled()) {
                                                LOG.debug("resource:[" + 
accessResource + ", MatchType:[" + matchType + "]");
@@ -703,10 +703,9 @@ public class RangerTagEnricher extends 
RangerAbstractContextEnricher {
                        final Collection<RangerServiceResourceMatcher> 
serviceResourceMatchers = getEvaluators(request, enrichedServiceTags);
 
                        if 
(CollectionUtils.isNotEmpty(serviceResourceMatchers)) {
-
                                for (RangerServiceResourceMatcher 
resourceMatcher : serviceResourceMatchers) {
 
-                                       final 
RangerPolicyResourceMatcher.MatchType matchType = 
resourceMatcher.getMatchType(resource, request.getContext());
+                                       final 
RangerPolicyResourceMatcher.MatchType matchType = 
resourceMatcher.getMatchType(resource, 
request.getResourceElementMatchingScopes(), request.getContext());
 
                                        if (LOG.isDebugEnabled()) {
                                                LOG.debug("resource:[" + 
resource + ", MatchType:[" + matchType + "]");
@@ -771,7 +770,7 @@ public class RangerTagEnricher extends 
RangerAbstractContextEnricher {
                                perf = 
RangerPerfTracer.getPerfTracer(PERF_TRIE_OP_LOG, 
"RangerTagEnricher.getEvaluators(resource=" + resource.getAsString() + ")");
                        }
 
-                       ret = 
RangerResourceEvaluatorsRetriever.getEvaluators(serviceResourceTrie, 
resource.getAsMap(), request.getResourceMatchingScope());
+                       ret = 
RangerResourceEvaluatorsRetriever.getEvaluators(serviceResourceTrie, 
resource.getAsMap(), request.getResourceElementMatchingScopes());
 
                        RangerPerfTracer.logAlways(perf);
                }
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java
index 6a38747f4..01848df76 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java
@@ -19,14 +19,13 @@
 
 package org.apache.ranger.plugin.policyengine;
 
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 public interface RangerAccessRequest {
-       String RANGER_ACCESS_REQUEST_SCOPE_STRING = "Scope";
-
        RangerAccessResource getResource();
 
        String getAccessType();
@@ -67,5 +66,13 @@ public interface RangerAccessRequest {
 
        ResourceMatchingScope getResourceMatchingScope();
 
-       enum ResourceMatchingScope {SELF, SELF_OR_DESCENDANTS, SELF_OR_CHILD}
+       default Map<String, ResourceElementMatchingScope> 
getResourceElementMatchingScopes() {
+               return Collections.emptyMap();
+       }
+
+       enum ResourceMatchingScope { SELF, SELF_OR_DESCENDANTS }
+
+       enum ResourceElementMatchingScope { SELF, SELF_OR_CHILD, SELF_OR_PREFIX 
}
+
+       enum ResourceElementMatchType { NONE, SELF, CHILD, PREFIX }
 }
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestImpl.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestImpl.java
index e561c4c7c..019a0d893 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestImpl.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestImpl.java
@@ -20,6 +20,7 @@
 package org.apache.ranger.plugin.policyengine;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -56,6 +57,7 @@ public class RangerAccessRequestImpl implements 
RangerAccessRequest {
        private boolean isAccessTypeAny;
        private boolean isAccessTypeDelegatedAdmin;
        private ResourceMatchingScope resourceMatchingScope = 
ResourceMatchingScope.SELF;
+       private Map<String, ResourceElementMatchingScope> 
resourceElementMatchingScopes = Collections.emptyMap();
 
        public RangerAccessRequestImpl() {
                this(null, null, null, null, null);
@@ -96,6 +98,7 @@ public class RangerAccessRequestImpl implements 
RangerAccessRequest {
                setContext(request.getContext());
                setClusterName(request.getClusterName());
                setResourceMatchingScope(request.getResourceMatchingScope());
+               
setResourceElementMatchingScopes(request.getResourceElementMatchingScopes());
                setClientIPAddress(request.getClientIPAddress());
                setClusterType(request.getClusterType());
        }
@@ -171,6 +174,9 @@ public class RangerAccessRequestImpl implements 
RangerAccessRequest {
                return resourceMatchingScope;
        }
 
+       @Override
+       public Map<String, ResourceElementMatchingScope> 
getResourceElementMatchingScopes() { return this.resourceElementMatchingScopes; 
}
+
        @Override
        public boolean isAccessTypeAny() {
                return isAccessTypeAny;
@@ -265,6 +271,10 @@ public class RangerAccessRequestImpl implements 
RangerAccessRequest {
                }
        }
 
+       public void setResourceElementMatchingScopes(Map<String, 
ResourceElementMatchingScope> resourceElementMatchingScopes) {
+               this.resourceElementMatchingScopes = 
resourceElementMatchingScopes == null ? Collections.emptyMap() : 
resourceElementMatchingScopes;
+       }
+
        public void setContext(Map<String, Object> context) {
                if (context == null) {
                        this.context = new HashMap<>();
@@ -358,6 +368,7 @@ public class RangerAccessRequestImpl implements 
RangerAccessRequest {
                sb.append("requestData={").append(requestData).append("} ");
                sb.append("sessionId={").append(sessionId).append("} ");
                
sb.append("resourceMatchingScope={").append(resourceMatchingScope).append("} ");
+               
sb.append("resourceElementMatchingScopes={").append(resourceElementMatchingScopes).append("}
 ");
                sb.append("clusterName={").append(clusterName).append("} ");
                sb.append("clusterType={").append(clusterType).append("} ");
 
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestReadOnly.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestReadOnly.java
index 4887c0112..b732dfab6 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestReadOnly.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestReadOnly.java
@@ -98,6 +98,9 @@ public class RangerAccessRequestReadOnly implements 
RangerAccessRequest {
        @Override
        public ResourceMatchingScope getResourceMatchingScope() { return 
source.getResourceMatchingScope(); }
 
+       @Override
+       public Map<String, ResourceElementMatchingScope> 
getResourceElementMatchingScopes() { return 
source.getResourceElementMatchingScopes(); }
+
        @Override
        public String getClusterName() { return source.getClusterName();        
}
 
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestWrapper.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestWrapper.java
index 6aec330d7..96f851e9a 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestWrapper.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestWrapper.java
@@ -101,5 +101,8 @@ public class RangerAccessRequestWrapper implements 
RangerAccessRequest {
     @Override
     public ResourceMatchingScope getResourceMatchingScope() { return 
request.getResourceMatchingScope(); }
 
+    @Override
+    public Map<String, ResourceElementMatchingScope> 
getResourceElementMatchingScopes() { return 
request.getResourceElementMatchingScopes(); }
+
 }
 
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 e75bb722c..8ba0b1a7f 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
@@ -318,7 +318,7 @@ public class RangerPolicyEngineImpl implements 
RangerPolicyEngine {
                                                for 
(RangerPolicyResourceEvaluator resourceEvaluator : 
evaluator.getResourceEvaluators()) {
                                                        
RangerPolicyResourceMatcher matcher = 
resourceEvaluator.getPolicyResourceMatcher();
 
-                                                       matchType = 
matcher.getMatchType(request.getResource(), request.getContext());
+                                                       matchType = 
matcher.getMatchType(request.getResource(), 
request.getResourceElementMatchingScopes(), request.getContext());
                                                        isMatched = 
isMatch(matchType, request.getResourceMatchingScope());
 
                                                        if (isMatched) {
@@ -326,7 +326,7 @@ public class RangerPolicyEngineImpl implements 
RangerPolicyEngine {
 
                                                                break;
                                                        } else if 
(matcher.getNeedsDynamicEval() && !isConditionalMatch) {
-                                                               MatchType 
dynWildCardMatch = 
resourceEvaluator.getMacrosReplaceWithWildcardMatcher(policyEngine).getMatchType(request.getResource(),
 request.getContext());
+                                                               MatchType 
dynWildCardMatch = 
resourceEvaluator.getMacrosReplaceWithWildcardMatcher(policyEngine).getMatchType(request.getResource(),
 request.getResourceElementMatchingScopes(), request.getContext());
 
                                                                
isConditionalMatch = isMatch(dynWildCardMatch, 
request.getResourceMatchingScope());
                                                        }
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
index b5b26702c..68f4b5dfd 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
@@ -719,7 +719,7 @@ public class RangerPolicyRepository {
             perf = RangerPerfTracer.getPerfTracer(PERF_TRIE_OP_LOG, 
"RangerPolicyRepository.getLikelyMatchEvaluators(resource=" + 
resource.getAsString() + ")");
         }
 
-        Collection<RangerPolicyResourceEvaluator> smallestList = 
RangerResourceEvaluatorsRetriever.getEvaluators(resourceTrie, 
resource.getAsMap(), request.getResourceMatchingScope());
+        Collection<RangerPolicyResourceEvaluator> smallestList = 
RangerResourceEvaluatorsRetriever.getEvaluators(resourceTrie, 
resource.getAsMap(), request.getResourceElementMatchingScopes());
 
         if (smallestList != null) {
             if (smallestList.size() == 0) {
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java
index f89d51e35..07eb5815c 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java
@@ -25,6 +25,7 @@ import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
 import org.apache.ranger.plugin.policyresourcematcher.RangerResourceEvaluator;
 import org.apache.ranger.plugin.resourcematcher.RangerAbstractResourceMatcher;
@@ -44,6 +45,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.Stack;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 
@@ -184,10 +186,10 @@ public class RangerResourceTrie<T extends 
RangerResourceEvaluator> {
     }
 
     public Set<T> getEvaluatorsForResource(Object resource) {
-        return getEvaluatorsForResource(resource, 
RangerAccessRequest.ResourceMatchingScope.SELF);
+        return getEvaluatorsForResource(resource, 
ResourceElementMatchingScope.SELF);
     }
 
-    public Set<T> getEvaluatorsForResource(Object resource, 
RangerAccessRequest.ResourceMatchingScope scope) {
+    public Set<T> getEvaluatorsForResource(Object resource, 
ResourceElementMatchingScope scope) {
         if (resource instanceof String) {
             return getEvaluatorsForResource((String) resource, scope);
         } else if (resource instanceof Collection) {
@@ -576,7 +578,7 @@ public class RangerResourceTrie<T extends 
RangerResourceEvaluator> {
         return str.substring(0, minIndex);
     }
 
-    private Set<T> getEvaluatorsForResource(String resource, 
RangerAccessRequest.ResourceMatchingScope scope) {
+    private Set<T> getEvaluatorsForResource(String resource, 
ResourceElementMatchingScope scope) {
         if(LOG.isDebugEnabled()) {
             LOG.debug("==> RangerResourceTrie.getEvaluatorsForResource(" + 
resource + ", " + scope + ")");
         }
@@ -643,10 +645,10 @@ public class RangerResourceTrie<T extends 
RangerResourceEvaluator> {
             ret = accumulatedEvaluators;
         }
 
-        boolean includeEvaluatorsOfChildResources = scope == 
RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD;
+        final boolean includeChildEvaluators = scope == 
ResourceElementMatchingScope.SELF_OR_CHILD || scope == 
ResourceElementMatchingScope.SELF_OR_PREFIX;
+        final Set<T>  childEvalautors        = includeChildEvaluators ? new 
HashSet<>() : null;
 
-        if (includeEvaluatorsOfChildResources) {
-            final Set<T>  childEvalautors     = new HashSet<>();
+        if (scope == ResourceElementMatchingScope.SELF_OR_CHILD) {
             final boolean resourceEndsWithSep = 
resource.charAt(resource.length() - 1) == separatorChar;
 
             if (isSelfMatch) { // resource == path(curr)
@@ -671,14 +673,16 @@ public class RangerResourceTrie<T extends 
RangerResourceEvaluator> {
                     }
                 }
             }
+        } else if (scope == ResourceElementMatchingScope.SELF_OR_PREFIX) {
+            curr.collectChildEvaluators(resource, i, childEvalautors);
+        }
 
-            if (CollectionUtils.isNotEmpty(childEvalautors)) {
-                if (CollectionUtils.isNotEmpty(ret)) {
-                    childEvalautors.addAll(ret);
-                }
-
-                ret = childEvalautors;
+        if (CollectionUtils.isNotEmpty(childEvalautors)) {
+            if (CollectionUtils.isNotEmpty(ret)) {
+                childEvalautors.addAll(ret);
             }
+
+            ret = childEvalautors;
         }
 
         RangerPerfTracer.logAlways(perf);
@@ -731,7 +735,7 @@ public class RangerResourceTrie<T extends 
RangerResourceEvaluator> {
         return curr;
     }
 
-    private Set<T> getEvaluatorsForResources(Collection<String> resources, 
RangerAccessRequest.ResourceMatchingScope scope) {
+    private Set<T> getEvaluatorsForResources(Collection<String> resources, 
ResourceElementMatchingScope scope) {
         if(LOG.isDebugEnabled()) {
             LOG.debug("==> RangerResourceTrie.getEvaluatorsForResources(" + 
resources + ")");
         }
@@ -1228,6 +1232,64 @@ public class RangerResourceTrie<T extends 
RangerResourceEvaluator> {
             }
         }
 
+        void collectChildEvaluators(String resource, int startIndex, Set<U> 
childEvaluators) {
+            if (startIndex == resource.length()) {
+                collectChildEvaluators(childEvaluators);
+            } else if (startIndex < resource.length()) {
+                Character   startChar = getLookupChar(resource, startIndex);
+                TrieNode<U> childNode = children.get(startChar);
+
+                if (childNode != null) {
+                    if (!isOptimizedForSpace) {
+                        childNode.setupIfNeeded(childNode.getParent());
+                    }
+
+                    String childStr = childNode.getStr();
+                    int lenToMatch = Math.min(resource.length() - startIndex, 
childStr.length());
+
+                    if (resource.regionMatches(optIgnoreCase, startIndex, 
childStr, 0, lenToMatch)) {
+                        if (childNode.wildcardEvaluators != null) {
+                            
childEvaluators.addAll(childNode.wildcardEvaluators);
+                        }
+
+                        if (childNode.evaluators != null) {
+                            childEvaluators.addAll(childNode.evaluators);
+                        }
+
+                        if (resource.length() == (startIndex + lenToMatch)) {
+                            childNode.collectChildEvaluators(childEvaluators);
+                        } else {
+                            childNode.children.values().stream().forEach(c -> 
c.collectChildEvaluators(resource, startIndex + childStr.length(), 
childEvaluators));
+                        }
+                    }
+                }
+            }
+        }
+
+        private void collectChildEvaluators(Set<U> childEvaluators) {
+            Stack<TrieNode<U>> nodes = new Stack<>();
+
+            nodes.addAll(children.values());
+
+            while (!nodes.isEmpty()) {
+                TrieNode<U> childNode = nodes.pop();
+
+                if (!isOptimizedForSpace) {
+                    childNode.setupIfNeeded(childNode.getParent());
+                }
+
+                if (childNode.wildcardEvaluators != null) {
+                    childEvaluators.addAll(childNode.wildcardEvaluators);
+                }
+
+                if (childNode.evaluators != null) {
+                    childEvaluators.addAll(childNode.evaluators);
+                }
+
+                nodes.addAll(childNode.children.values());
+            }
+        }
+
         private void removeEvaluatorFromSubtree(U evaluator) {
             if (CollectionUtils.isNotEmpty(wildcardEvaluators) && 
wildcardEvaluators.contains(evaluator)) {
                 undoSetup();
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAuditPolicyEvaluator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAuditPolicyEvaluator.java
index 1c46f184c..ba24b8c3e 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAuditPolicyEvaluator.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerAuditPolicyEvaluator.java
@@ -129,7 +129,7 @@ public class RangerAuditPolicyEvaluator extends 
RangerDefaultPolicyEvaluator {
                     RangerPolicyResourceMatcher resourceMatcher = 
resourceEvaluator.getPolicyResourceMatcher();
 
                     if (resourceMatcher != null) {
-                        matchType = 
resourceMatcher.getMatchType(request.getResource(), request.getContext());
+                        matchType = 
resourceMatcher.getMatchType(request.getResource(), 
request.getResourceElementMatchingScopes(), request.getContext());
                     } else {
                         matchType = RangerPolicyResourceMatcher.MatchType.NONE;
                     }
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 eee1e1f1b..4ad2944a8 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
@@ -233,11 +233,7 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                                                        matchType = 
RangerPolicyResourceMatcher.MatchType.SELF;
                                                }
                                        } else {
-                                               if 
(request.getResourceMatchingScope() == 
RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) {
-                                                       
request.getContext().put(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING,
 RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD);
-                                               }
-                                               matchType = resourceMatcher != 
null ? resourceMatcher.getMatchType(request.getResource(), 
request.getContext()) : RangerPolicyResourceMatcher.MatchType.NONE;
-                                               
request.getContext().remove(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING);
+                                               matchType = resourceMatcher != 
null ? resourceMatcher.getMatchType(request.getResource(), 
request.getResourceElementMatchingScopes(), request.getContext()) : 
RangerPolicyResourceMatcher.MatchType.NONE;
                                        }
 
                                        final boolean isMatched;
@@ -473,7 +469,7 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                        if (RangerTagAccessRequest.class.isInstance(request)) {
                                matchType = ((RangerTagAccessRequest) 
request).getMatchType();
                        } else {
-                               matchType = resourceMatcher != null ? 
resourceMatcher.getMatchType(request.getResource(), request.getContext()) : 
RangerPolicyResourceMatcher.MatchType.NONE;
+                               matchType = resourceMatcher != null ? 
resourceMatcher.getMatchType(request.getResource(), 
request.getResourceElementMatchingScopes(), request.getContext()) : 
RangerPolicyResourceMatcher.MatchType.NONE;
                        }
 
                        final boolean isMatched = matchType != 
RangerPolicyResourceMatcher.MatchType.NONE;
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 e887730c9..f16157ce6 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
@@ -20,6 +20,7 @@
 package org.apache.ranger.plugin.policyresourcematcher;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
@@ -33,6 +34,7 @@ import 
org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.apache.ranger.plugin.policyengine.RangerAccessResource;
 import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
 import org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher;
@@ -378,6 +380,11 @@ public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceM
 
     @Override
     public boolean isMatch(RangerPolicy policy, MatchScope scope, Map<String, 
Object> evalContext) {
+        return isMatch(policy, Collections.emptyMap(), scope, evalContext);
+    }
+
+    @Override
+    public boolean isMatch(RangerPolicy policy, Map<String, 
ResourceElementMatchingScope> scopes, MatchScope scope, Map<String, Object> 
evalContext) {
         boolean ret = false;
 
         RangerPerfTracer perf = null;
@@ -428,7 +435,7 @@ public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceM
                             for (String value : policyResource.getValues()) {
                                 accessResource.setValue(name, value);
 
-                                matchType = getMatchType(accessResource, 
evalContext);
+                                matchType = getMatchType(accessResource, 
scopes, evalContext);
 
                                 if (matchType != MatchType.NONE) { // One 
value for this resourceDef matched
                                     ret = true;
@@ -458,6 +465,11 @@ public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceM
 
     @Override
     public boolean isMatch(RangerAccessResource resource, Map<String, Object> 
evalContext) {
+        return isMatch(resource, Collections.emptyMap(), evalContext);
+    }
+
+    @Override
+    public boolean isMatch(RangerAccessResource resource, Map<String, 
ResourceElementMatchingScope> scopes, Map<String, Object> evalContext) {
         RangerPerfTracer perf = null;
 
         
if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG)) 
{
@@ -487,7 +499,7 @@ public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceM
                 break;
             }
         }
-        final boolean ret = MapUtils.isNotEmpty(policyResources) && 
isMatch(policyResources, evalContext);
+        final boolean ret = MapUtils.isNotEmpty(policyResources) && 
isMatch(policyResources, scopes, evalContext);
 
         RangerPerfTracer.log(perf);
 
@@ -496,6 +508,11 @@ public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceM
 
     @Override
     public boolean isMatch(Map<String, RangerPolicyResource> resources, 
Map<String, Object> evalContext) {
+        return isMatch(resources, Collections.emptyMap(), evalContext);
+    }
+
+    @Override
+    public boolean isMatch(Map<String, RangerPolicyResource> resources, 
Map<String, ResourceElementMatchingScope> scopes, Map<String, Object> 
evalContext) {
         if(LOG.isDebugEnabled()) {
             LOG.debug("==> RangerDefaultPolicyResourceMatcher.isMatch(" + 
resources  + ", " + evalContext + ")");
         }
@@ -524,7 +541,8 @@ public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceM
                     if (matcher != null) {
                         if (CollectionUtils.isNotEmpty(values)) {
                             for (String value : values) {
-                                ret = matcher.isMatch(value, evalContext);
+                                ret = matcher.isMatch(value, 
scopes.get(resourceName), evalContext);
+
                                 if (!ret) {
                                     break;
                                 }
@@ -558,12 +576,22 @@ public class RangerDefaultPolicyResourceMatcher 
implements RangerPolicyResourceM
 
     @Override
     public boolean isMatch(RangerAccessResource resource, MatchScope scope, 
Map<String, Object> evalContext) {
-        MatchType matchType = getMatchType(resource, evalContext);
+        return isMatch(resource, Collections.emptyMap(), scope, evalContext);
+    }
+
+    @Override
+    public boolean isMatch(RangerAccessResource resource, Map<String, 
ResourceElementMatchingScope> scopes, MatchScope scope, Map<String, Object> 
evalContext) {
+        MatchType matchType = getMatchType(resource, scopes, evalContext);
         return isMatch(scope, matchType);
     }
 
     @Override
     public MatchType getMatchType(RangerAccessResource resource, Map<String, 
Object> evalContext) {
+        return getMatchType(resource, Collections.emptyMap(), evalContext);
+    }
+
+    @Override
+    public MatchType getMatchType(RangerAccessResource resource, Map<String, 
ResourceElementMatchingScope> scopes, Map<String, Object> evalContext) {
         if (LOG.isDebugEnabled()) {
             LOG.debug("==> RangerDefaultPolicyResourceMatcher.getMatchType(" + 
resource + evalContext + ")");
         }
@@ -582,6 +610,7 @@ public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceM
                 ret = MatchType.SELF;
             } else {
                 List<RangerResourceDef> hierarchy = 
getMatchingHierarchy(resource);
+
                 if (CollectionUtils.isNotEmpty(hierarchy)) {
 
                     int lastNonAnyMatcherIndex = -1;
@@ -610,7 +639,7 @@ public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceM
 
                         if (matcher != null) {
                             if (resourceValue != null || matcher.isMatchAny()) 
{
-                                if (matcher.isMatch(resourceValue, 
evalContext)) {
+                                if (matcher.isMatch(resourceValue, 
scopes.get(resourceDef.getName()), evalContext)) {
                                     ret = MatchType.SELF;
                                 } else {
                                     ret = MatchType.NONE;
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 0220feba7..052e2df78 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
@@ -25,6 +25,7 @@ import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.apache.ranger.plugin.policyengine.RangerAccessResource;
 import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
 
@@ -50,14 +51,24 @@ public interface RangerPolicyResourceMatcher {
 
        boolean isMatch(RangerAccessResource resource, Map<String, Object> 
evalContext);
 
+       boolean isMatch(RangerAccessResource resource, Map<String, 
ResourceElementMatchingScope> scopes, Map<String, Object> evalContext);
+
        boolean isMatch(Map<String, RangerPolicyResource> resources, 
Map<String, Object> evalContext);
 
+       boolean isMatch(Map<String, RangerPolicyResource> resources, 
Map<String, ResourceElementMatchingScope> scopes, Map<String, Object> 
evalContext);
+
        boolean isMatch(RangerAccessResource resource, MatchScope scope, 
Map<String, Object> evalContext);
 
+       boolean isMatch(RangerAccessResource resource, Map<String, 
ResourceElementMatchingScope> scopes, MatchScope scope, Map<String, Object> 
evalContext);
+
        boolean isMatch(RangerPolicy policy, MatchScope scope, Map<String, 
Object> evalContext);
 
+       boolean isMatch(RangerPolicy policy, Map<String, 
ResourceElementMatchingScope> scopes, MatchScope scope, Map<String, Object> 
evalContext);
+
        MatchType getMatchType(RangerAccessResource resource, Map<String, 
Object> evalContext);
 
+       MatchType getMatchType(RangerAccessResource resource, Map<String, 
ResourceElementMatchingScope> scopes, Map<String, Object> evalContext);
+
        boolean isCompleteMatch(RangerAccessResource resource, Map<String, 
Object> evalContext);
 
        boolean isCompleteMatch(Map<String, RangerPolicyResource> resources, 
Map<String, Object> evalContext);
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 032d4487c..cb8d46adf 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
@@ -390,9 +390,30 @@ public abstract class RangerAbstractResourceMatcher 
implements RangerResourceMat
        }
 }
 
-final class CaseSensitiveStringMatcher extends ResourceMatcher {
-       CaseSensitiveStringMatcher(String value, Map<String, String> options) {
+abstract class AbstractStringResourceMatcher extends ResourceMatcher {
+       private final boolean isCaseSensitive;
+
+       protected AbstractStringResourceMatcher(String value, Map<String, 
String> options, boolean isCaseSensitive) {
                super(value, options);
+
+               this.isCaseSensitive = isCaseSensitive;
+       }
+
+       @Override
+       public boolean isPrefixMatch(String resourceValue, Map<String, Object> 
evalContext) {
+               return isCaseSensitive ? 
StringUtils.startsWith(getExpandedValue(evalContext), resourceValue)
+                                              : 
StringUtils.startsWithIgnoreCase(getExpandedValue(evalContext), resourceValue);
+       }
+
+       @Override
+       public boolean isChildMatch(String resourceValue, Map<String, Object> 
evalContext) {
+               return false; // child-match is applicable only for path 
resource
+       }
+}
+
+final class CaseSensitiveStringMatcher extends AbstractStringResourceMatcher {
+       CaseSensitiveStringMatcher(String value, Map<String, String> options) {
+               super(value, options, true);
        }
 
        @Override
@@ -402,8 +423,8 @@ final class CaseSensitiveStringMatcher extends 
ResourceMatcher {
        int getPriority() { return 1 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0);}
 }
 
-final class CaseInsensitiveStringMatcher extends ResourceMatcher {
-       CaseInsensitiveStringMatcher(String value, Map<String, String> options) 
{ super(value, options); }
+final class CaseInsensitiveStringMatcher extends AbstractStringResourceMatcher 
{
+       CaseInsensitiveStringMatcher(String value, Map<String, String> options) 
{ super(value, options, false); }
 
        @Override
        boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
@@ -412,11 +433,11 @@ final class CaseInsensitiveStringMatcher extends 
ResourceMatcher {
        int getPriority() {return 2 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
-final class QuotedCaseSensitiveStringMatcher extends ResourceMatcher {
+final class QuotedCaseSensitiveStringMatcher extends 
AbstractStringResourceMatcher {
        private final String quoteChars;
 
        QuotedCaseSensitiveStringMatcher(String value, Map<String, String> 
options, String quoteChars) {
-               super(value, options);
+               super(value, options, true);
 
                this.quoteChars = quoteChars;
        }
@@ -433,9 +454,9 @@ final class QuotedCaseSensitiveStringMatcher extends 
ResourceMatcher {
        int getPriority() {return 2 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
-final class CaseSensitiveStartsWithMatcher extends ResourceMatcher {
+final class CaseSensitiveStartsWithMatcher extends 
AbstractStringResourceMatcher {
        CaseSensitiveStartsWithMatcher(String value, Map<String, String> 
options) {
-               super(value, options);
+               super(value, options, true);
        }
 
        @Override
@@ -445,8 +466,8 @@ final class CaseSensitiveStartsWithMatcher extends 
ResourceMatcher {
        int getPriority() { return 3 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0);}
 }
 
-final class CaseInsensitiveStartsWithMatcher extends ResourceMatcher {
-       CaseInsensitiveStartsWithMatcher(String value, Map<String, String> 
options) { super(value, options); }
+final class CaseInsensitiveStartsWithMatcher extends 
AbstractStringResourceMatcher {
+       CaseInsensitiveStartsWithMatcher(String value, Map<String, String> 
options) { super(value, options, false); }
 
        @Override
        boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
@@ -455,11 +476,11 @@ final class CaseInsensitiveStartsWithMatcher extends 
ResourceMatcher {
        int getPriority() { return 4 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
-final class QuotedCaseSensitiveStartsWithMatcher extends ResourceMatcher {
+final class QuotedCaseSensitiveStartsWithMatcher extends 
AbstractStringResourceMatcher {
        private final String quoteChars;
 
        QuotedCaseSensitiveStartsWithMatcher(String value, Map<String, String> 
options, String quoteChars) {
-               super(value, options);
+               super(value, options, true);
 
                this.quoteChars = quoteChars;
        }
@@ -476,9 +497,9 @@ final class QuotedCaseSensitiveStartsWithMatcher extends 
ResourceMatcher {
        int getPriority() { return 4 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
-final class CaseSensitiveEndsWithMatcher extends ResourceMatcher {
+final class CaseSensitiveEndsWithMatcher extends AbstractStringResourceMatcher 
{
        CaseSensitiveEndsWithMatcher(String value, Map<String, String> options) 
{
-               super(value, options);
+               super(value, options, true);
        }
 
        @Override
@@ -488,9 +509,9 @@ final class CaseSensitiveEndsWithMatcher extends 
ResourceMatcher {
        int getPriority() { return 3 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
-final class CaseInsensitiveEndsWithMatcher extends ResourceMatcher {
+final class CaseInsensitiveEndsWithMatcher extends 
AbstractStringResourceMatcher {
        CaseInsensitiveEndsWithMatcher(String value, Map<String, String> 
options) {
-               super(value, options);
+               super(value, options, false);
        }
 
        @Override
@@ -500,11 +521,11 @@ final class CaseInsensitiveEndsWithMatcher extends 
ResourceMatcher {
        int getPriority() { return 4 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
-final class QuotedCaseSensitiveEndsWithMatcher extends ResourceMatcher {
+final class QuotedCaseSensitiveEndsWithMatcher extends 
AbstractStringResourceMatcher {
        private final String quoteChars;
 
        QuotedCaseSensitiveEndsWithMatcher(String value, Map<String, String> 
options, String quoteChars) {
-               super(value, options);
+               super(value, options, true);
 
                this.quoteChars = quoteChars;
        }
@@ -521,9 +542,9 @@ final class QuotedCaseSensitiveEndsWithMatcher extends 
ResourceMatcher {
        int getPriority() { return 4 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
-final class CaseSensitiveWildcardMatcher extends ResourceMatcher {
+final class CaseSensitiveWildcardMatcher extends AbstractStringResourceMatcher 
{
        CaseSensitiveWildcardMatcher(String value, Map<String, String> options) 
{
-               super(value, options);
+               super(value, options, true);
        }
 
        @Override
@@ -534,9 +555,9 @@ final class CaseSensitiveWildcardMatcher extends 
ResourceMatcher {
 }
 
 
-final class CaseInsensitiveWildcardMatcher extends ResourceMatcher {
+final class CaseInsensitiveWildcardMatcher extends 
AbstractStringResourceMatcher {
        CaseInsensitiveWildcardMatcher(String value, Map<String, String> 
options) {
-               super(value, options);
+               super(value, options, false);
        }
 
        @Override
@@ -546,11 +567,11 @@ final class CaseInsensitiveWildcardMatcher extends 
ResourceMatcher {
        int getPriority() {return 6 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0); }
 }
 
-final class QuotedCaseSensitiveWildcardMatcher extends ResourceMatcher {
+final class QuotedCaseSensitiveWildcardMatcher extends 
AbstractStringResourceMatcher {
        private final String quoteChars;
 
        QuotedCaseSensitiveWildcardMatcher(String value, Map<String, String> 
options, String quoteChars) {
-               super(value, options);
+               super(value, options, true);
 
                this.quoteChars = quoteChars;
        }
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 c421388e7..702cb272f 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,6 +20,7 @@
 package org.apache.ranger.plugin.resourcematcher;
 
 
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -31,38 +32,45 @@ public class RangerDefaultResourceMatcher extends 
RangerAbstractResourceMatcher
        private static final Logger LOG = 
LoggerFactory.getLogger(RangerDefaultResourceMatcher.class);
 
        @Override
-       public boolean isMatch(Object resource, Map<String, Object> 
evalContext) {
+       public boolean isMatch(Object resource, ResourceElementMatchingScope 
matchingScope, Map<String, Object> evalContext) {
                if(LOG.isDebugEnabled()) {
                        LOG.debug("==> RangerDefaultResourceMatcher.isMatch(" + 
resource + ", " + evalContext + ")");
                }
 
                boolean ret = false;
                boolean allValuesRequested = isAllValuesRequested(resource);
+               boolean isPrefixMatch = matchingScope == 
ResourceElementMatchingScope.SELF_OR_PREFIX;
 
-               if(allValuesRequested || isMatchAny) {
+               if (isMatchAny || (allValuesRequested && !isPrefixMatch)) {
                        ret = isMatchAny;
                } else {
                        if (resource instanceof String) {
                                String strValue = (String) resource;
 
                                for (ResourceMatcher resourceMatcher : 
resourceMatchers.getResourceMatchers()) {
-                                       ret = resourceMatcher.isMatch(strValue, 
evalContext);
+                                       ret = resourceMatcher.isMatch(strValue, 
matchingScope, evalContext);
+
                                        if (ret) {
                                                break;
                                        }
                                }
                        } else if (resource instanceof Collection) {
                                @SuppressWarnings("unchecked")
-                               Collection<String> collValue = 
(Collection<String>) resource;
+                               Collection<String> resourceValues = 
(Collection<String>) resource;
 
                                for (ResourceMatcher resourceMatcher : 
resourceMatchers.getResourceMatchers()) {
-                                       ret = 
resourceMatcher.isMatchAny(collValue, evalContext);
+                                       for (String resourceValue : 
resourceValues) {
+                                               ret = 
resourceMatcher.isMatch(resourceValue, matchingScope, evalContext);
+
+                                               if (ret) {
+                                                       break;
+                                               }
+                                       }
                                        if (ret) {
                                                break;
                                        }
                                }
                        }
-
                }
 
                ret = applyExcludes(allValuesRequested, ret);
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 5fa5b68d4..1af967fbd 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
@@ -20,7 +20,6 @@
 package org.apache.ranger.plugin.resourcematcher;
 
 import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.collections.MapUtils;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOCase;
 import org.apache.commons.lang.ArrayUtils;
@@ -261,15 +260,15 @@ public class RangerPathResourceMatcher extends 
RangerDefaultResourceMatcher {
                if (needWildcardMatch) { // test?, test*a*, test*a*b, *test*a
                        ret = new WildcardResourceMatcher(policyValue, 
getOptions(), pathSeparatorChar, optIgnoreCase, FilenameUtils::wildcardMatch, 
6);
                } else if (wildcardStartIdx == -1) { // test, testa, testab
-                       ret = new StringResourceMatcher(policyValue, 
getOptions(), pathSeparatorChar, optIgnoreCase ? StringUtils::equalsIgnoreCase 
: StringUtils::equals, optIgnoreCase ? 2 : 1);
+                       ret = new PathResourceMatcher(policyValue, 
getOptions(), pathSeparatorChar, optIgnoreCase ? StringUtils::equalsIgnoreCase 
: StringUtils::equals, optIgnoreCase ? 2 : 1, !optIgnoreCase);
                } else if (wildcardStartIdx == 0) { // *test, **test, *testa, 
*testab
                        String matchStr = policyValue.substring(wildcardEndIdx 
+ 1);
-                       ret = new StringResourceMatcher(matchStr, getOptions(), 
pathSeparatorChar, optIgnoreCase ? StringUtils::endsWithIgnoreCase : 
StringUtils::endsWith, optIgnoreCase ? 4 : 3);
+                       ret = new PathResourceMatcher(matchStr, getOptions(), 
pathSeparatorChar, optIgnoreCase ? StringUtils::endsWithIgnoreCase : 
StringUtils::endsWith, optIgnoreCase ? 4 : 3, !optIgnoreCase);
                } else if (wildcardEndIdx != (len - 1)) { // test*a, test*ab
                        ret = new WildcardResourceMatcher(policyValue, 
getOptions(), pathSeparatorChar, optIgnoreCase, FilenameUtils::wildcardMatch, 
6);
                } else { // test*, test**, testa*, testab*
                        String matchStr = policyValue.substring(0, 
wildcardStartIdx);
-                       ret = new StringResourceMatcher(matchStr, getOptions(), 
pathSeparatorChar, optIgnoreCase ? StringUtils::startsWithIgnoreCase : 
StringUtils::startsWith, optIgnoreCase ? 4 : 3);
+                       ret = new PathResourceMatcher(matchStr, getOptions(), 
pathSeparatorChar, optIgnoreCase ? StringUtils::startsWithIgnoreCase : 
StringUtils::startsWith, optIgnoreCase ? 4 : 3, !optIgnoreCase);
                }
 
                if (optReplaceTokens) {
@@ -291,99 +290,132 @@ public class RangerPathResourceMatcher extends 
RangerDefaultResourceMatcher {
                R apply(T t, U u, V v, W w, X x);
        }
 
-       static abstract class PathResourceMatcher extends ResourceMatcher {
+       static abstract class AbstractPathResourceMatcher extends 
ResourceMatcher {
                final char    pathSeparatorChar;
                final int     priority;
+               final boolean isCaseSensitive;
 
-               PathResourceMatcher(String value, Map<String, String> options, 
char pathSeparatorChar, int priority) {
+               AbstractPathResourceMatcher(String value, Map<String, String> 
options, char pathSeparatorChar, int priority, boolean isCaseSensitive) {
                        super(value, options);
-                       this.pathSeparatorChar    = pathSeparatorChar;
-                       this.priority             = priority;
+
+                       this.pathSeparatorChar = pathSeparatorChar;
+                       this.priority          = priority;
+                       this.isCaseSensitive   = isCaseSensitive;
                }
                int getPriority() {
                        return priority + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0);
                }
+
+               @Override
+               public boolean isPrefixMatch(String resourceValue, Map<String, 
Object> evalContext) {
+                       return isCaseSensitive ? 
StringUtils.startsWith(getExpandedValue(evalContext), resourceValue)
+                                              : 
StringUtils.startsWithIgnoreCase(getExpandedValue(evalContext), resourceValue);
+               }
        }
 
-       static class StringResourceMatcher extends PathResourceMatcher {
+       static class PathResourceMatcher extends AbstractPathResourceMatcher {
                final BiFunction<String, String, Boolean> function;
-               StringResourceMatcher(String value, Map<String, String> 
options, char pathSeparatorChar, BiFunction<String, String, Boolean> function, 
int priority) {
-                       super(value, options, pathSeparatorChar, priority);
+
+               PathResourceMatcher(String value, Map<String, String> options, 
char pathSeparatorChar, BiFunction<String, String, Boolean> function, int 
priority, boolean isCaseSensitive) {
+                       super(value, options, pathSeparatorChar, priority, 
isCaseSensitive);
+
                        this.function = function;
                }
+
                @Override
                boolean isMatch(String resourceValue, Map<String, Object> 
evalContext) {
                        if (LOG.isDebugEnabled()) {
-                               LOG.debug("==> 
StringResourceMatcher.isMatch(resourceValue=" + resourceValue + ", 
evalContext=" + evalContext + ")");
-                       }
-                       String expandedValue = getExpandedValue(evalContext);
-                       boolean ret = function.apply(resourceValue, 
expandedValue);
-                       if (!ret) {
-                               RangerAccessRequest.ResourceMatchingScope scope 
= MapUtils.isNotEmpty(evalContext) ? 
(RangerAccessRequest.ResourceMatchingScope) 
evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null;
-                               if (scope == 
RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) {
-                                       int lastLevelSeparatorIndex = 
expandedValue.lastIndexOf(pathSeparatorChar);
-                                       if (lastLevelSeparatorIndex != -1) {
-                                               String shorterExpandedValue = 
expandedValue.substring(0, lastLevelSeparatorIndex);
-                                               if 
(resourceValue.charAt(resourceValue.length()-1) == pathSeparatorChar) {
-                                                       resourceValue = 
resourceValue.substring(0, resourceValue.length()-1);
-                                               }
-                                               ret = 
function.apply(resourceValue, shorterExpandedValue);
-                                       }
-                               }
+                               LOG.debug("==> 
PathResourceMatcher.isMatch(resourceValue=" + resourceValue + ", evalContext=" 
+ evalContext + ")");
                        }
+
+                       String  expandedValue = getExpandedValue(evalContext);
+                       boolean ret           = function.apply(resourceValue, 
expandedValue);
+
                        if (LOG.isDebugEnabled()) {
-                               LOG.debug("<== 
StringResourceMatcher.isMatch(resourceValue=" + resourceValue + ", 
expandedValue=" + expandedValue + ") : result:[" + ret + "]");
+                               LOG.debug("<== 
PathResourceMatcher.isMatch(resourceValue=" + resourceValue + ", 
expandedValue=" + expandedValue + ") : result:[" + ret + "]");
                        }
+
+                       return ret;
+               }
+
+               @Override
+               public boolean isChildMatch(String resourceValue, Map<String, 
Object> evalContext) {
+                       boolean ret                     = false;
+                       String  expandedValue           = 
getExpandedValue(evalContext);
+                       int     lastLevelSeparatorIndex = 
expandedValue.lastIndexOf(pathSeparatorChar);
+
+                       if (lastLevelSeparatorIndex != -1) {
+                               String shorterExpandedValue = 
expandedValue.substring(0, lastLevelSeparatorIndex);
+
+                               if 
(resourceValue.charAt(resourceValue.length()-1) == pathSeparatorChar) {
+                                       resourceValue = 
resourceValue.substring(0, resourceValue.length()-1);
+                               }
+
+                               ret = function.apply(resourceValue, 
shorterExpandedValue);
+                       }
+
                        return ret;
                }
 
        }
 
-       static class WildcardResourceMatcher extends PathResourceMatcher {
+       static class WildcardResourceMatcher extends 
AbstractPathResourceMatcher {
                final TriFunction<String, String, IOCase, Boolean> function;
-               final IOCase ioCase;
+               final IOCase                                       ioCase;
 
                WildcardResourceMatcher(String value, Map<String, String> 
options, char pathSeparatorChar, boolean optIgnoreCase, TriFunction<String, 
String, IOCase, Boolean> function, int priority) {
-                       super(value, options, pathSeparatorChar, priority);
+                       super(value, options, pathSeparatorChar, priority, 
!optIgnoreCase);
+
                        this.function = function;
                        this.ioCase   = optIgnoreCase ? IOCase.INSENSITIVE : 
IOCase.SENSITIVE;
                }
+
                @Override
                boolean isMatch(String resourceValue, Map<String, Object> 
evalContext) {
                        if (LOG.isDebugEnabled()) {
                                LOG.debug("==> 
WildcardResourceMatcher.isMatch(resourceValue=" + resourceValue + ", 
evalContext=" + evalContext + ")");
                        }
-                       String expandedValue = getExpandedValue(evalContext);
-                       boolean ret = function.apply(resourceValue, 
expandedValue, ioCase);
-                       if (!ret) {
-                               RangerAccessRequest.ResourceMatchingScope scope 
= MapUtils.isNotEmpty(evalContext) ? 
(RangerAccessRequest.ResourceMatchingScope) 
evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null;
-                               if (scope == 
RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) {
-                                       int lastLevelSeparatorIndex = 
expandedValue.lastIndexOf(pathSeparatorChar);
-                                       if (lastLevelSeparatorIndex != -1) {
-                                               String shorterExpandedValue = 
expandedValue.substring(0, lastLevelSeparatorIndex);
-                                               if 
(resourceValue.charAt(resourceValue.length()-1) == pathSeparatorChar) {
-                                                       resourceValue = 
resourceValue.substring(0, resourceValue.length()-1);
-                                               }
-                                               ret = 
function.apply(resourceValue, shorterExpandedValue, ioCase);
-                                       }
-                               }
-                       }
+
+                       String  expandedValue = getExpandedValue(evalContext);
+                       boolean ret           = function.apply(resourceValue, 
expandedValue, ioCase);
+
                        if (LOG.isDebugEnabled()) {
                                LOG.debug("<== 
WildcardResourceMatcher.isMatch(resourceValue=" + resourceValue + ", 
expandedValue=" + expandedValue + ") : result:[" + ret + "]");
                        }
                        return ret;
                }
+
+               @Override
+               public boolean isChildMatch(String resourceValue, Map<String, 
Object> evalContext) {
+                       boolean ret                     = false;
+                       String  expandedValue           = 
getExpandedValue(evalContext);
+                       int     lastLevelSeparatorIndex = 
expandedValue.lastIndexOf(pathSeparatorChar);
+
+                       if (lastLevelSeparatorIndex != -1) {
+                               String shorterExpandedValue = 
expandedValue.substring(0, lastLevelSeparatorIndex);
+
+                               if 
(resourceValue.charAt(resourceValue.length()-1) == pathSeparatorChar) {
+                                       resourceValue = 
resourceValue.substring(0, resourceValue.length()-1);
+                               }
+
+                               ret = function.apply(resourceValue, 
shorterExpandedValue, ioCase);
+                       }
+
+                       return ret;
+               }
        }
 
-       static class RecursiveWildcardResourceMatcher extends 
PathResourceMatcher {
+       static class RecursiveWildcardResourceMatcher extends 
AbstractPathResourceMatcher {
                final QuintFunction<String, String, Character, IOCase, Boolean, 
String[]> function;
                final IOCase ioCase;
                String[] wildcardPathElements;
 
                RecursiveWildcardResourceMatcher(String value, Map<String, 
String> options, char pathSeparatorChar, boolean optIgnoreCase, 
QuintFunction<String, String, Character, IOCase, Boolean, String[]> function, 
int priority) {
-                       super(value, options, pathSeparatorChar, priority);
+                       super(value, options, pathSeparatorChar, priority, 
!optIgnoreCase);
+
                        this.function = function;
                        this.ioCase   = optIgnoreCase ? IOCase.INSENSITIVE : 
IOCase.SENSITIVE;
+
                        if (!getNeedsDynamicEval()) {
                                wildcardPathElements = StringUtils.split(value, 
pathSeparatorChar);
                        }
@@ -402,28 +434,36 @@ public class RangerPathResourceMatcher extends 
RangerDefaultResourceMatcher {
                        }
 
                        boolean ret = function.apply(resourceValue, 
expandedValue, pathSeparatorChar, ioCase, wildcardPathElements);
-                       if (!ret) {
-                               RangerAccessRequest.ResourceMatchingScope scope 
= MapUtils.isNotEmpty(evalContext) ? 
(RangerAccessRequest.ResourceMatchingScope) 
evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null;
-                               if (scope == 
RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) {
-                                       int lastLevelSeparatorIndex = 
expandedValue.lastIndexOf(pathSeparatorChar);
-                                       if (lastLevelSeparatorIndex != -1) {
-                                               String shorterExpandedValue = 
expandedValue.substring(0, lastLevelSeparatorIndex);
-                                               if 
(resourceValue.charAt(resourceValue.length()-1) == pathSeparatorChar) {
-                                                       resourceValue = 
resourceValue.substring(0, resourceValue.length()-1);
-                                               }
-                                               String[] 
shorterWildCardPathElements = StringUtils.split(shorterExpandedValue, 
pathSeparatorChar);
-                                               ret = 
function.apply(resourceValue, shorterExpandedValue, pathSeparatorChar, ioCase, 
shorterWildCardPathElements);
-                                       }
-                               }
-                       }
+
                        if (LOG.isDebugEnabled()) {
                                LOG.debug("<== 
RecursiveWildcardResourceMatcher.isMatch(resourceValue=" + resourceValue + ", 
expandedValue=" + expandedValue + ") : result:[" + ret + "]");
                        }
                        return ret;
                }
+
+               @Override
+               public boolean isChildMatch(String resourceValue, Map<String, 
Object> evalContext) {
+                       boolean ret = false;
+                       String expandedValue = getExpandedValue(evalContext);
+                       int lastLevelSeparatorIndex = 
expandedValue.lastIndexOf(pathSeparatorChar);
+
+                       if (lastLevelSeparatorIndex != -1) {
+                               String shorterExpandedValue = 
expandedValue.substring(0, lastLevelSeparatorIndex);
+
+                               if (resourceValue.charAt(resourceValue.length() 
- 1) == pathSeparatorChar) {
+                                       resourceValue = 
resourceValue.substring(0, resourceValue.length() - 1);
+                               }
+
+                               String[] shorterWildCardPathElements = 
StringUtils.split(shorterExpandedValue, pathSeparatorChar);
+
+                               ret = function.apply(resourceValue, 
shorterExpandedValue, pathSeparatorChar, ioCase, shorterWildCardPathElements);
+                       }
+
+                       return ret;
+               }
        }
 
-       static class RecursivePathResourceMatcher extends PathResourceMatcher {
+       static class RecursivePathResourceMatcher extends 
AbstractPathResourceMatcher {
                String valueWithoutSeparator;
                String valueWithSeparator;
 
@@ -431,7 +471,8 @@ public class RangerPathResourceMatcher extends 
RangerDefaultResourceMatcher {
                final BiFunction<String, String, Boolean> fallbackFunction;
 
                RecursivePathResourceMatcher(String value, Map<String, String> 
options, char pathSeparatorChar, BiFunction<String, String, Boolean> 
primaryFunction, BiFunction<String, String, Boolean> fallbackFunction, int 
priority) {
-                       super(value, options, pathSeparatorChar, priority);
+                       super(value, options, pathSeparatorChar, priority, 
true);
+
                        this.primaryFunction    = primaryFunction;
                        this.fallbackFunction   = fallbackFunction;
                }
@@ -465,28 +506,44 @@ public class RangerPathResourceMatcher extends 
RangerDefaultResourceMatcher {
 
                        if (!ret && noSeparator != null) {
                                final String withSeparator = 
getNeedsDynamicEval() ? noSeparator + pathSeparatorChar : valueWithSeparator;
-                               ret = fallbackFunction.apply(resourceValue, 
withSeparator);
 
-                               if (!ret) {
-                                       
RangerAccessRequest.ResourceMatchingScope scope = 
MapUtils.isNotEmpty(evalContext) ? (RangerAccessRequest.ResourceMatchingScope) 
evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null;
-                                       if (scope == 
RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) {
-                                               final int 
lastLevelSeparatorIndex = noSeparator.lastIndexOf(pathSeparatorChar);
-                                               if (lastLevelSeparatorIndex != 
-1) {
-                                                       final String 
shorterExpandedValue = noSeparator.substring(0, lastLevelSeparatorIndex);
-                                                       if 
(resourceValue.charAt(resourceValue.length() - 1) == pathSeparatorChar) {
-                                                               resourceValue = 
resourceValue.substring(0, resourceValue.length() - 1);
-                                                       }
-                                                       ret = 
primaryFunction.apply(resourceValue, shorterExpandedValue);
-                                               }
-                                       }
-                               }
+                               ret = fallbackFunction.apply(resourceValue, 
withSeparator);
                        }
+
                        if (LOG.isDebugEnabled()) {
                                LOG.debug("<== 
RecursivePathResourceMatcher.isMatch(resourceValue=" + resourceValue + ", 
expandedValueWithoutTrailingSeparatorChar=" + noSeparator + ") : result:[" + 
ret + "]");
                        }
 
                        return ret;
                }
-       }
 
+               @Override
+               public boolean isChildMatch(String resourceValue, Map<String, 
Object> evalContext) {
+                       boolean ret = false;
+                       final String noSeparator;
+                       if (getNeedsDynamicEval()) {
+                               String expandedPolicyValue = 
getExpandedValue(evalContext);
+                               noSeparator = expandedPolicyValue != null ? 
getStringToCompare(expandedPolicyValue) : null;
+                       } else {
+                               if (valueWithoutSeparator == null && value != 
null) {
+                                       valueWithoutSeparator = 
getStringToCompare(value);
+                                       valueWithSeparator = 
valueWithoutSeparator + pathSeparatorChar;
+                               }
+                               noSeparator = valueWithoutSeparator;
+                       }
+                       final int lastLevelSeparatorIndex = 
noSeparator.lastIndexOf(pathSeparatorChar);
+
+                       if (lastLevelSeparatorIndex != -1) {
+                               final String shorterExpandedValue = 
noSeparator.substring(0, lastLevelSeparatorIndex);
+
+                               if (resourceValue.charAt(resourceValue.length() 
- 1) == pathSeparatorChar) {
+                                       resourceValue = 
resourceValue.substring(0, resourceValue.length() - 1);
+                               }
+
+                               ret = primaryFunction.apply(resourceValue, 
shorterExpandedValue);
+                       }
+
+                       return ret;
+               }
+       }
 }
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 0cb3e0fed..c4ce30d36 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
@@ -21,6 +21,7 @@ package org.apache.ranger.plugin.resourcematcher;
 
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 
 import java.util.Map;
 
@@ -33,7 +34,7 @@ public interface RangerResourceMatcher {
 
        boolean isMatchAny();
 
-       boolean isMatch(Object resource, Map<String, Object> evalContext);
+       boolean isMatch(Object resource, ResourceElementMatchingScope 
matchingScope, Map<String, Object> evalContext);
 
        boolean isCompleteMatch(String resource, Map<String, Object> 
evalContext);
 
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcher.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcher.java
index ee2fff3ed..ce73b3006 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcher.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcher.java
@@ -234,10 +234,10 @@ public class RangerURLResourceMatcher extends 
RangerDefaultResourceMatcher {
     }
 }
 
-final class CaseSensitiveURLRecursiveWildcardMatcher extends ResourceMatcher {
+final class CaseSensitiveURLRecursiveWildcardMatcher extends 
AbstractStringResourceMatcher {
     private final char levelSeparatorChar;
     CaseSensitiveURLRecursiveWildcardMatcher(String value, Map<String, String> 
options, char levelSeparatorChar) {
-        super(value, options);
+        super(value, options, true);
         this.levelSeparatorChar = levelSeparatorChar;
     }
 
@@ -248,10 +248,10 @@ final class CaseSensitiveURLRecursiveWildcardMatcher 
extends ResourceMatcher {
     int getPriority() { return 7 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0);}
 }
 
-final class CaseInsensitiveURLRecursiveWildcardMatcher extends ResourceMatcher 
{
+final class CaseInsensitiveURLRecursiveWildcardMatcher extends 
AbstractStringResourceMatcher {
     private final char levelSeparatorChar;
     CaseInsensitiveURLRecursiveWildcardMatcher(String value, Map<String, 
String> options, char levelSeparatorChar) {
-        super(value, options);
+        super(value, options, false);
         this.levelSeparatorChar = levelSeparatorChar;
     }
 
@@ -263,13 +263,13 @@ final class CaseInsensitiveURLRecursiveWildcardMatcher 
extends ResourceMatcher {
 
 }
 
-abstract class RecursiveMatcher extends ResourceMatcher {
+abstract class RecursiveMatcher extends AbstractStringResourceMatcher {
     final char levelSeparatorChar;
     String valueWithoutSeparator;
     String valueWithSeparator;
 
-    RecursiveMatcher(String value, Map<String, String> options, char 
levelSeparatorChar) {
-        super(value, options);
+    RecursiveMatcher(String value, Map<String, String> options, char 
levelSeparatorChar, boolean isCaseSensitive) {
+        super(value, options, isCaseSensitive);
         this.levelSeparatorChar = levelSeparatorChar;
     }
 
@@ -284,7 +284,7 @@ abstract class RecursiveMatcher extends ResourceMatcher {
 
 final class CaseSensitiveURLRecursiveMatcher extends RecursiveMatcher {
     CaseSensitiveURLRecursiveMatcher(String value, Map<String, String> 
options, char levelSeparatorChar) {
-        super(value, options, levelSeparatorChar);
+        super(value, options, levelSeparatorChar, true);
     }
 
     @Override
@@ -316,7 +316,7 @@ final class CaseSensitiveURLRecursiveMatcher extends 
RecursiveMatcher {
 
 final class CaseInsensitiveURLRecursiveMatcher extends RecursiveMatcher {
     CaseInsensitiveURLRecursiveMatcher(String value, Map<String, String> 
options, char levelSeparatorChar) {
-        super(value, options, levelSeparatorChar);
+        super(value, options, levelSeparatorChar, false);
     }
 
     @Override
@@ -345,4 +345,4 @@ final class CaseInsensitiveURLRecursiveMatcher extends 
RecursiveMatcher {
     }
 
     int getPriority() { return 8 + (getNeedsDynamicEval() ? 
DYNAMIC_EVALUATION_PENALTY : 0);}
-}
\ No newline at end of file
+}
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 5df4f1e3a..ad0942fbe 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
@@ -21,6 +21,8 @@ package org.apache.ranger.plugin.resourcematcher;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchType;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.apache.ranger.plugin.util.RangerRequestExprResolver;
 import org.apache.ranger.plugin.util.StringTokenReplacer;
@@ -28,7 +30,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.Serializable;
-import java.util.Collection;
 import java.util.Comparator;
 import java.util.Map;
 
@@ -52,24 +53,54 @@ abstract class ResourceMatcher {
     }
 
     abstract boolean isMatch(String resourceValue, Map<String, Object> 
evalContext);
-    abstract int getPriority();
 
-    boolean isMatchAny() { return value != null && value.length() == 0; }
+    abstract boolean isPrefixMatch(String resourceValue, Map<String, Object> 
evalContext);
 
-    boolean getNeedsDynamicEval() {
-        return exprResolver != null || tokenReplacer != null;
+    abstract boolean isChildMatch(String resourceValue, Map<String, Object> 
evalContext);
+
+    final boolean isMatch(String resourceValue, ResourceElementMatchingScope 
matchingScope, Map<String, Object> evalContext) {
+        final ResourceElementMatchType matchType = getMatchType(resourceValue, 
matchingScope, evalContext);
+        final boolean                  ret;
+
+        if (matchType == ResourceElementMatchType.SELF) {
+            ret = true;
+        } else if (matchType == ResourceElementMatchType.PREFIX) {
+            ret = matchingScope == ResourceElementMatchingScope.SELF_OR_PREFIX;
+        } else if (matchType == ResourceElementMatchType.CHILD) {
+            ret = matchingScope == ResourceElementMatchingScope.SELF_OR_CHILD;
+        } else {
+            ret = false;
+        }
+
+        return ret;
     }
 
-    public boolean isMatchAny(Collection<String> resourceValues, Map<String, 
Object> evalContext) {
-        if (resourceValues != null) {
-            for (String resourceValue : resourceValues) {
-                if (isMatch(resourceValue, evalContext)) {
-                    return true;
+    final ResourceElementMatchType getMatchType(String resourceValue, 
ResourceElementMatchingScope matchingScope, Map<String, Object> evalContext) {
+        ResourceElementMatchType ret = ResourceElementMatchType.NONE;
+
+        if (isMatch(resourceValue, evalContext)) {
+            ret = ResourceElementMatchType.SELF;
+        } else {
+            if (matchingScope == ResourceElementMatchingScope.SELF_OR_PREFIX) {
+                if (isPrefixMatch(resourceValue, evalContext)) {
+                    ret = ResourceElementMatchType.PREFIX;
+                }
+            } else if (matchingScope == 
ResourceElementMatchingScope.SELF_OR_CHILD) {
+                if (isChildMatch(resourceValue, evalContext)) {
+                    ret = ResourceElementMatchType.CHILD;
                 }
             }
         }
 
-        return false;
+        return ret;
+    }
+
+    abstract int getPriority();
+
+    boolean isMatchAny() { return value != null && value.length() == 0; }
+
+    boolean getNeedsDynamicEval() {
+        return exprResolver != null || tokenReplacer != null;
     }
 
     @Override
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceEvaluatorsRetriever.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceEvaluatorsRetriever.java
index e60fe055b..2ba8135b1 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceEvaluatorsRetriever.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceEvaluatorsRetriever.java
@@ -21,7 +21,7 @@ package org.apache.ranger.plugin.util;
 
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
-import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.apache.ranger.plugin.policyengine.RangerResourceTrie;
 import org.apache.ranger.plugin.policyresourcematcher.RangerResourceEvaluator;
 import org.slf4j.Logger;
@@ -39,15 +39,19 @@ public class RangerResourceEvaluatorsRetriever {
     private static final Logger LOG = 
LoggerFactory.getLogger(RangerResourceEvaluatorsRetriever.class);
 
     public static <T  extends RangerResourceEvaluator> Collection<T> 
getEvaluators(Map<String, RangerResourceTrie<T>> resourceTrie, Map<String, ?> 
resource) {
-        return getEvaluators(resourceTrie, resource, 
RangerAccessRequest.ResourceMatchingScope.SELF);
+        return getEvaluators(resourceTrie, resource, null);
     }
 
-    public static <T  extends RangerResourceEvaluator> Collection<T> 
getEvaluators(Map<String, RangerResourceTrie<T>> resourceTrie, Map<String, ?> 
resource, RangerAccessRequest.ResourceMatchingScope scope) {
+    public static <T  extends RangerResourceEvaluator> Collection<T> 
getEvaluators(Map<String, RangerResourceTrie<T>> resourceTrie, Map<String, ?> 
resource, Map<String, ResourceElementMatchingScope> scopes) {
         if (LOG.isDebugEnabled()) {
             LOG.debug("==> 
RangerPolicyResourceEvaluatorsRetriever.getEvaluators(" + resource + ")");
         }
         Set<T> ret = null;
 
+        if (scopes == null) {
+            scopes = Collections.emptyMap();
+        }
+
         if (MapUtils.isNotEmpty(resourceTrie) && 
MapUtils.isNotEmpty(resource)) {
             Set<String> resourceKeys = resource.keySet();
 
@@ -63,7 +67,7 @@ public class RangerResourceEvaluatorsRetriever {
                 Object resourceValues = resource.get(resourceDefName);
 
                 Set<T> inheritedMatchers   = trie.getInheritedEvaluators();
-                Set<T> matchersForResource = 
trie.getEvaluatorsForResource(resourceValues, scope);
+                Set<T> matchersForResource = 
trie.getEvaluatorsForResource(resourceValues, scopes.get(resourceDefName));
 
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("ResourceDefName:[" + resourceDefName + "], 
values:[" + resourceValues + "], resource-matchers:[" + matchersForResource + 
"], inherited-matchers:[" + inheritedMatchers + "]");
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPathResourceTrie.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPathResourceTrie.java
index 30a7215a6..d23509f86 100644
--- 
a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPathResourceTrie.java
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPathResourceTrie.java
@@ -21,6 +21,7 @@ package org.apache.ranger.plugin.policyengine;
 
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.apache.ranger.plugin.policyresourcematcher.RangerResourceEvaluator;
 import 
org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
 import org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher;
@@ -71,7 +72,7 @@ public class TestPathResourceTrie {
 
        @Test
        public void testChildrenScope() {
-               final RangerAccessRequest.ResourceMatchingScope scope = 
RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD;
+               final ResourceElementMatchingScope scope = 
ResourceElementMatchingScope.SELF_OR_CHILD;
 
                verifyEvaluators("/", scope, EVAL_, EVAL_nr, EVAL_HOME, 
EVAL_HOME_, EVAL_TMPnr, EVAL_TMP_nr, EVAL_TMPFILE, EVAL_TMPdTXT);
                verifyEvaluators("/tmp", scope, EVAL_, EVAL_TMPnr, EVAL_TMP_nr, 
EVAL_TMP_AB);
@@ -84,9 +85,24 @@ public class TestPathResourceTrie {
                verifyEvaluators("invalid: does-not-begin-with-sep", scope);
        }
 
+       @Test
+       public void testPrefixScope() {
+               final ResourceElementMatchingScope scope = 
ResourceElementMatchingScope.SELF_OR_PREFIX;
+
+               verifyEvaluators("/", scope, EVAL_, EVAL_nr, EVAL_HOME, 
EVAL_HOME_, EVAL_TMPnr, EVAL_TMP_nr, EVAL_TMP_AB, EVAL_TMP_A_B, 
EVAL_TMP_AC_D_E_F, EVAL_TMPFILE, EVAL_TMPdTXT, EVAL_TMPA_B);
+               verifyEvaluators("/tmp", scope, EVAL_, EVAL_TMPnr, EVAL_TMP_nr, 
EVAL_TMP_AB, EVAL_TMP_A_B, EVAL_TMP_AC_D_E_F, EVAL_TMPFILE, EVAL_TMPdTXT, 
EVAL_TMPA_B);
+               verifyEvaluators("/tmp/", scope, EVAL_, EVAL_TMP_nr, 
EVAL_TMP_AB, EVAL_TMP_A_B, EVAL_TMP_AC_D_E_F);
+               verifyEvaluators("/tmp/a", scope, EVAL_, EVAL_TMP_AB, 
EVAL_TMP_A_B, EVAL_TMP_AC_D_E_F);
+               verifyEvaluators("/tmp/ac", scope, EVAL_, EVAL_TMP_AC_D_E_F);
+               verifyEvaluators("/tmp/ac/d", scope, EVAL_, EVAL_TMP_AC_D_E_F);
+               verifyEvaluators("/tmp/ac/d/e", scope, EVAL_, 
EVAL_TMP_AC_D_E_F);
+               verifyEvaluators("/unmatched", scope, EVAL_);
+               verifyEvaluators("invalid: does-not-begin-with-sep", scope);
+       }
+
        @Test
        public void testSelfScope() {
-               final RangerAccessRequest.ResourceMatchingScope scope = 
RangerAccessRequest.ResourceMatchingScope.SELF;
+               final ResourceElementMatchingScope scope = 
ResourceElementMatchingScope.SELF;
 
                verifyEvaluators("/", scope, EVAL_, EVAL_nr);
                verifyEvaluators("/tmp", scope, EVAL_, EVAL_TMPnr);
@@ -99,7 +115,7 @@ public class TestPathResourceTrie {
                verifyEvaluators("invalid: does-not-begin-with-sep", scope);
        }
 
-       private void verifyEvaluators(String resource, 
RangerAccessRequest.ResourceMatchingScope scope, RangerResourceEvaluator... 
evaluators) {
+       private void verifyEvaluators(String resource, 
ResourceElementMatchingScope scope, RangerResourceEvaluator... evaluators) {
                Set<RangerResourceEvaluator> expected = evaluators.length == 0 
? null : new HashSet<>(Arrays.asList(evaluators));
                Set<RangerResourceEvaluator> result   = 
trie.getEvaluatorsForResource(resource, scope);
 
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
index b2a5151e5..6a3875ad5 100644
--- 
a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngine.java
@@ -482,6 +482,20 @@ public class TestPolicyEngine {
                runTestsFromResourceFiles(resourceFiles);
        }
 
+       @Test
+       public void testAnyResourceAccess_Kafka() throws Exception {
+               String[] resourceFiles = 
{"/policyengine/test_policyengine_kafka.json"};
+
+               runTestsFromResourceFiles(resourceFiles);
+       }
+
+       @Test
+       public void testAnyResourceAccess_S3() throws Exception {
+               String[] resourceFiles = 
{"/policyengine/test_policyengine_aws_s3.json"};
+
+               runTestsFromResourceFiles(resourceFiles);
+       }
+
        private void runTestsFromResourceFiles(String[] resourceNames) {
                for(String resourceName : resourceNames) {
                        InputStream inStream = 
this.getClass().getResourceAsStream(resourceName);
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 e31437fc1..767795e81 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
@@ -19,6 +19,7 @@
 
 package org.apache.ranger.plugin.resourcematcher;
 
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.junit.Test;
 
 import java.util.Map;
@@ -42,7 +43,7 @@ public class RangerAbstractResourceMatcherTest {
     static class AbstractMatcherWrapper extends RangerAbstractResourceMatcher {
 
         @Override
-        public boolean isMatch(Object resource, Map<String, Object> 
evalContext) {
+        public boolean isMatch(Object resource, ResourceElementMatchingScope 
matchingScope, Map<String, Object> evalContext) {
             fail("This method is not expected to be used by test!");
             return false;
         }
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 ad21b3239..e00bc834d 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
@@ -22,6 +22,7 @@ package org.apache.ranger.plugin.resourcematcher;
 import com.google.common.collect.Lists;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.junit.Test;
 
@@ -59,7 +60,7 @@ public class RangerDefaultResourceMatcherTest {
             RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
 
             MatcherWrapper matcher = new MatcherWrapper(policyValue, excludes);
-            assertEquals(getMessage(row), result, matcher.isMatch(resource, 
evalContext));
+            assertEquals(getMessage(row), result, matcher.isMatch(resource, 
ResourceElementMatchingScope.SELF, evalContext));
         }
     }
 
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 8fe3be9cc..5e8efb720 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
@@ -22,7 +22,7 @@ package org.apache.ranger.plugin.resourcematcher;
 import com.google.common.collect.Lists;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
-import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.junit.Test;
 
@@ -100,7 +100,7 @@ public class RangerPathResourceMatcherTest {
             RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
 
             MatcherWrapper matcher = new MatcherWrapper(policyValue, 
optWildcard, isRecursive);
-            assertEquals(getMessage(row), result, matcher.isMatch(resource, 
evalContext));
+            assertEquals(getMessage(row), result, matcher.isMatch(resource, 
ResourceElementMatchingScope.SELF, evalContext));
         }
     }
 
@@ -116,10 +116,9 @@ public class RangerPathResourceMatcherTest {
 
             Map<String, Object> evalContext = new HashMap<>();
             RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
-            
evalContext.put(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING, 
RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD);
 
             MatcherWrapper matcher = new MatcherWrapper(policyValue, 
optWildcard, isRecursive);
-            assertEquals(getMessage(row), result, matcher.isMatch(resource, 
evalContext));
+            assertEquals(getMessage(row), result, matcher.isMatch(resource, 
ResourceElementMatchingScope.SELF_OR_CHILD, evalContext));
         }
     }
 
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcherTest.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcherTest.java
index 2b7f27200..904cb61b2 100644
--- 
a/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcherTest.java
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/resourcematcher/RangerURLResourceMatcherTest.java
@@ -22,6 +22,7 @@ package org.apache.ranger.plugin.resourcematcher;
 import com.google.common.collect.Lists;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.junit.Test;
 
@@ -66,7 +67,7 @@ public class RangerURLResourceMatcherTest {
             RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
 
             MatcherWrapper matcher = new MatcherWrapper(policyValue, 
optWildcard, isRecursive);
-            assertEquals(getMessage(row), result, matcher.isMatch(resource, 
evalContext));
+            assertEquals(getMessage(row), result, matcher.isMatch(resource, 
ResourceElementMatchingScope.SELF, evalContext));
         }
     }
 
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 ea7bc01f2..ef8ee6c32 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
@@ -28,6 +28,7 @@ import java.util.Map;
 
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import 
org.apache.ranger.plugin.policyengine.RangerAccessRequest.ResourceElementMatchingScope;
 import 
org.apache.ranger.plugin.resourcematcher.TestResourceMatcher.ResourceMatcherTestCases.TestCase;
 import 
org.apache.ranger.plugin.resourcematcher.TestResourceMatcher.ResourceMatcherTestCases.TestCase.OneTest;
 import org.junit.After;
@@ -112,7 +113,7 @@ public class TestResourceMatcher {
                                }
 
                                boolean expected = oneTest.result;
-                               boolean result   = 
matcher.isMatch(oneTest.input, oneTest.evalContext);
+                               boolean result   = 
matcher.isMatch(oneTest.input, ResourceElementMatchingScope.SELF, 
oneTest.evalContext);
 
                                assertEquals("isMatch() failed! " + 
testCase.name + ":" + oneTest.name + ": input=" + oneTest.input, expected, 
result);
                        }
diff --git a/agents-common/src/test/resources/policyengine/aws_s3_tags.json 
b/agents-common/src/test/resources/policyengine/aws_s3_tags.json
new file mode 100644
index 000000000..be598893c
--- /dev/null
+++ b/agents-common/src/test/resources/policyengine/aws_s3_tags.json
@@ -0,0 +1,33 @@
+{
+    "op":          "add_or_update",
+    "serviceName": "dev_aws-s3",
+    "tagDefinitions": {
+      "1": { "id": 1, "name": "PII" },
+      "2": { "id": 2, "name": "PII-VENDOR" }
+    },
+    "tags": {
+      "1": { "id": 1, "type": "PII" },
+      "2": { "id": 2, "type": "PII-VENDOR" }
+    },
+    "serviceResources": [
+      {
+        "id": 1, "serviceName": "dev_aws-s3",
+        "resourceElements": {
+          "bucketname": { "values": [ "mycompany" ] },
+          "objectpath": { "values": [ "/pii" ], "isRecursive": true }
+        }
+     },
+      {
+        "id": 2, "serviceName": "dev_aws-s3",
+        "resourceElements": {
+          "bucketname": { "values": [ "mycompany" ] },
+          "objectpath": { "values": [ "/vendor/pii" ], "isRecursive": true }
+        }
+     }
+    ],
+    "resourceToTagIds": {
+      "1": [ 1 ],
+      "2": [ 2 ]
+    }
+}
+
diff --git 
a/agents-common/src/test/resources/policyengine/test_policyengine_aws.json 
b/agents-common/src/test/resources/policyengine/test_policyengine_aws.json
index 118bef534..56e082ad8 100644
--- a/agents-common/src/test/resources/policyengine/test_policyengine_aws.json
+++ b/agents-common/src/test/resources/policyengine/test_policyengine_aws.json
@@ -108,14 +108,14 @@
   "tests":[
     {"name":"ALLOW 'write /tmp/scott' for u=scott for scope SELF_OR_CHILD",
       "request":{
-        "resource":{"elements":{"path":"/tmp/scott"}}, 
"resourceMatchingScope": "SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/tmp/scott"}}, 
"resourceElementMatchingScopes": { "path": "SELF_OR_CHILD" },
         
"accessType":"write","user":"scott","userGroups":[],"requestData":"write 
/tmp/scott"
       },
       "result":{"isAudited":true,"isAllowed":true,"policyId": 200}
     },
     {"name":"DENY 'ANY /tmp/scott' for u=joe for scope SELF_OR_CHILD",
       "request":{
-        "resource":{"elements":{"path":"/tmp/scott"}}, 
"resourceMatchingScope": "SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/tmp/scott"}}, 
"resourceElementMatchingScopes": { "path": "SELF_OR_CHILD" },
         "accessType":"","user":"joe","userGroups":[],"requestData":"ANY 
/tmp/scott"
       },
       "result":{"isAudited":false,"isAllowed":false,"policyId": -1}
@@ -136,7 +136,7 @@
     },
     {"name":"ALLOW 'write /user/dir' for u=scott for scope SELF_OR_CHILD",
       "request":{
-        "resource":{"elements":{"path":"/user/dir"}}, "resourceMatchingScope": 
"SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/user/dir"}}, 
"resourceElementMatchingScopes": { "path": "SELF_OR_CHILD" },
         
"accessType":"write","user":"scott","userGroups":[],"requestData":"write 
/user/dir"
       },
       "result":{"isAudited":true,"isAllowed":true,"policyId": 400}
@@ -150,14 +150,14 @@
     },
     {"name":"DENY 'ANY /user/dir' for u=joe for scope SELF_OR_CHILD",
       "request":{
-        "resource":{"elements":{"path":"/user/dir"}}, "resourceMatchingScope": 
"SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/user/dir"}}, 
"resourceElementMatchingScopes": { "path": "SELF_OR_CHILD" },
         "accessType":"","user":"joe","userGroups":[],"requestData":"ANY 
/user/dir"
       },
       "result":{"isAudited":true,"isAllowed":false,"policyId": -1}
     },
     {"name":"ALLOW 'read /user/scott' for u=scott for scope SELF_OR_CHILD",
       "request":{
-        "resource":{"elements":{"path":"/user/scott"}}, 
"resourceMatchingScope": "SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/user/scott"}}, 
"resourceElementMatchingScopes": { "path": "SELF_OR_CHILD" },
         "accessType":"read","user":"scott","userGroups":[],"requestData":"read 
/tmp/scott"
       },
       "result":{"isAudited":true,"isAllowed":true,"policyId": 500}
@@ -171,7 +171,7 @@
     },
     {"name":"ALLOW 'ANY /' for u=user1",
       "request":{
-        "resource":{"elements":{"path":"/"}}, "resourceMatchingScope": 
"SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/"}}, "resourceElementMatchingScopes": 
{ "path": "SELF_OR_CHILD" },
         "accessType":"","user":"user1","userGroups":[],"requestData":"ANY /"
       },
       "result":{"isAudited":true,"isAllowed":true,"policyId":20}
@@ -179,7 +179,7 @@
   ,
     {"name":"ALLOW 'ANY /tmp' for u=user1",
       "request":{
-        "resource":{"elements":{"path":"/tmp"}}, "resourceMatchingScope": 
"SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/tmp"}}, 
"resourceElementMatchingScopes": { "path": "SELF_OR_CHILD" },
         "accessType":"","user":"user1","userGroups":[],"requestData":"ANY /tmp"
       },
       "result":{"isAudited":true,"isAllowed":true,"policyId":40}
@@ -187,7 +187,7 @@
   ,
     {"name":"ALLOW 'ANY /tmp/' for u=user1",
       "request":{
-        "resource":{"elements":{"path":"/tmp/"}}, "resourceMatchingScope": 
"SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/tmp/"}}, 
"resourceElementMatchingScopes": { "path": "SELF_OR_CHILD" },
         "accessType":"","user":"user1","userGroups":[],"requestData":"ANY 
/tmp/"
       },
       "result":{"isAudited":true,"isAllowed":true,"policyId":40}
@@ -195,7 +195,7 @@
   ,
     {"name":"ALLOW 'ANY /tmp/a' for u=user1",
       "request":{
-        "resource":{"elements":{"path":"/tmp/a"}}, "resourceMatchingScope": 
"SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/tmp/a"}}, 
"resourceElementMatchingScopes": { "path": "SELF_OR_CHILD" },
         "accessType":"","user":"user1","userGroups":[],"requestData":"ANY 
/tmp/a"
       },
       "result":{"isAudited":true,"isAllowed":true,"policyId":50}
@@ -203,7 +203,7 @@
   ,
     {"name":"DENY 'ANY /tmp/ac' for u=user1",
       "request":{
-        "resource":{"elements":{"path":"/tmp/ac"}}, "resourceMatchingScope": 
"SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/tmp/ac"}}, 
"resourceElementMatchingScopes": { "path": "SELF_OR_CHILD" },
         "accessType":"","user":"user1","userGroups":[],"requestData":"ANY 
/tmp/ac"
       },
       "result":{"isAudited":false,"isAllowed":false,"policyId":-1}
@@ -211,7 +211,7 @@
   ,
     {"name":"DENY 'ANY /tmp/ac/d' for u=user1",
       "request":{
-        "resource":{"elements":{"path":"/tmp/ac/d"}}, "resourceMatchingScope": 
"SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/tmp/ac/d"}}, 
"resourceElementMatchingScopes": { "path": "SELF_OR_CHILD" },
         "accessType":"","user":"user1","userGroups":[],"requestData":"ANY 
/tmp/ac/d"
       },
       "result":{"isAudited":false,"isAllowed":false,"policyId":-1}
@@ -219,7 +219,7 @@
   ,
     {"name":"ALLOW 'ANY /tmp/ac/d/e' for u=user1",
       "request":{
-        "resource":{"elements":{"path":"/tmp/ac/d/e"}}, 
"resourceMatchingScope": "SELF_OR_CHILD",
+        "resource":{"elements":{"path":"/tmp/ac/d/e"}}, 
"resourceElementMatchingScopes": { "path": "SELF_OR_CHILD" },
         "accessType":"","user":"user1","userGroups":[],"requestData":"ANY 
/tmp/ac/d/e"
       },
       "result":{"isAudited":true,"isAllowed":true,"policyId":10}
diff --git 
a/agents-common/src/test/resources/policyengine/test_policyengine_aws_s3.json 
b/agents-common/src/test/resources/policyengine/test_policyengine_aws_s3.json
new file mode 100644
index 000000000..e2373164c
--- /dev/null
+++ 
b/agents-common/src/test/resources/policyengine/test_policyengine_aws_s3.json
@@ -0,0 +1,211 @@
+{
+  "serviceName": "dev_aws-s3",
+
+  "serviceDef": {
+    "name": "aws-s3", "id": 1,
+    "resources": [
+      { "name": "bucketname", "parent":"",           "level": 1, "mandatory": 
true, "lookupSupported": true, "matcher": 
"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", 
"matcherOptions": { "wildCard": true, "ignoreCase": false }, "label": "Bucket 
Name", "description": "Bucket Name" },
+      { "name": "objectpath", "parent":"bucketname", "level": 2, "mandatory": 
true, "lookupSupported": true, "matcher": 
"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher",    
"matcherOptions": { "wildCard": true, "ignoreCase": false }, "label": "Object 
Path", "description": "Object Path" }
+    ],
+    "accessTypes": [
+      { "name": "read",   "label": "Read" },
+      { "name": "write",  "label": "Write" },
+      { "name": "delete", "label": "Delete" }
+    ]
+  },
+
+  "policies": [
+    {
+      "id": 10, "name": "s3://mycompany/public", "isEnabled": true, 
"isAuditEnabled": true,
+      "resources": {
+        "bucketname": { "values": [ "mycompany" ] },
+        "objectpath": { "values": [ "/public" ], "isRecursive": true } },
+      "policyItems": [
+        { "accesses": [ { "type": "read", "isAllowed": true } ], "groups": [ 
"public" ] }
+      ]
+    },
+    {
+      "id": 20, "name": "s3://mycompany/home/{USER}", "isEnabled": true, 
"isAuditEnabled": true,
+      "resources": {
+        "bucketname": { "values": [ "mycompany" ] },
+        "objectpath": { "values": [ "/home/{USER}" ], "isRecursive": true } },
+      "policyItems": [
+        { "accesses": [ { "type": "read", "isAllowed": true },  { "type": 
"write", "isAllowed": true },  { "type": "delete", "isAllowed": true } ], 
"users": [ "{USER}" ] }
+      ]
+    },
+    {
+      "id": 30, "name": "s3://mycompany/dept/hr", "isEnabled": true, 
"isAuditEnabled": true,
+      "resources": {
+        "bucketname": { "values": [ "mycompany" ] },
+        "objectpath": { "values": [ "/dept/hr" ], "isRecursive": true } },
+      "policyItems": [
+        { "accesses": [ { "type": "read", "isAllowed": true },  { "type": 
"write", "isAllowed": true },  { "type": "delete", "isAllowed": true } ], 
"groups": [ "hr-admins" ] },
+        { "accesses": [ { "type": "read", "isAllowed": true } ], "groups": [ 
"hr-users" ] }
+      ]
+    }
+  ],
+  "tagPolicyInfo": {
+    "serviceName":"tagdev",
+    "serviceDef": {
+      "name":      "tag", "id": 100,
+      "resources": [
+        { "name": "tag", "type": "string", "level": 1, "parent": "", 
"mandatory": true, "lookupSupported": true, "matcher": 
"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", 
"matcherOptions": { "wildCard": true, "ignoreCase": false }, "label": "TAG", 
"description": "TAG"
+        }
+      ],
+      "accessTypes": [
+        { "name": "aws-s3:read",   "label": "aws-s3:read" },
+        { "name": "aws-s3:write",  "label": "aws-s3:write" },
+        { "name": "aws-s3:delete", "label": "aws-s3:delete" }
+      ],
+      "contextEnrichers": [
+        {
+          "name" :     "TagEnricher",
+          "enricher" : 
"org.apache.ranger.plugin.contextenricher.RangerTagEnricher",
+          "enricherOptions" : {
+             "tagRetrieverClassName":       
"org.apache.ranger.plugin.contextenricher.RangerFileBasedTagRetriever",
+             "tagRefresherPollingInterval": 60000,
+             "serviceTagsFileName":         "/policyengine/aws_s3_tags.json"}
+        }
+      ]
+    },
+    "tagPolicies": [
+      {
+        "id": 1001, "name": "PII", "isEnabled": true, "isAuditEnabled": true,
+        "resources": { "tag": { "values": [ "PII" ] } },
+        "policyItems": [
+          { "accesses": [ { "type": "aws-s3:read", "isAllowed": true } ], 
"users": [ "user3" ] }
+        ]
+      },
+      {
+        "id": 1002, "name": "PII-VENDOR", "isEnabled": true, "isAuditEnabled": 
true,
+        "resources": { "tag": { "values": [ "PII-VENDOR" ] } },
+        "policyItems": [
+          { "accesses": [ { "type": "aws-s3:read", "isAllowed": true } ], 
"users": [ "user4" ] }
+        ]
+      }
+    ]
+  },
+  "tests": [
+    {
+      "name":    "Verify user1 has read access to some object under 
s3://mycompany",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/" } }, "resourceElementMatchingScopes": { "objectpath": "SELF_OR_PREFIX" },
+        "accessType": "read", "user": "user1"
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 10 }
+    },
+    {
+      "name":    "Verify user1 has read access to some object under 
s3://mycompany/public",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/public/" } }, "resourceElementMatchingScopes": { "objectpath": 
"SELF_OR_PREFIX" },
+        "accessType": "read", "user": "user1"
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 10 }
+    },
+    {
+      "name":    "Verify user1 has no write access to any object under 
s3://mycompany/public",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/public/" } }, "resourceElementMatchingScopes": { "objectpath": 
"SELF_OR_PREFIX" },
+        "accessType": "write", "user": "user1"
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1 }
+    },
+    {
+      "name":    "Verify user1 has write access to some object under 
s3://mycompany/home",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/home" } }, "resourceElementMatchingScopes": { "objectpath": "SELF_OR_PREFIX" 
},
+        "accessType": "write", "user": "user1"
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 20 }
+    },
+    {
+      "name":    "Verify user1 has no write access to any object under 
s3://mycompany/dept",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/dept" } }, "resourceElementMatchingScopes": { "objectpath": "SELF_OR_PREFIX" 
},
+        "accessType": "write", "user": "user1"
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1 }
+    },
+    {
+      "name":    "Verify user3 has read access to some objects under 
s3://mycompany/",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/" } }, "resourceElementMatchingScopes": { "objectpath": "SELF_OR_PREFIX" },
+        "accessType": "read", "user": "user3"
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 1001 }
+    },
+    {
+      "name":    "Verify user3 has write access to some objects under 
s3://mycompany/",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/" } }, "resourceElementMatchingScopes": { "objectpath": "SELF_OR_PREFIX" },
+        "accessType": "write", "user": "user3"
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 20 }
+    },
+    {
+      "name":    "Verify user3 has read access to some objects under 
s3://mycompany/pii",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/pii" } }, "resourceElementMatchingScopes": { "objectpath": "SELF_OR_PREFIX" },
+        "accessType": "read", "user": "user3"
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 1001 }
+    },
+    {
+      "name":    "Verify user3 has no write access to any object under 
s3://mycompany/pii",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/pii" } }, "resourceElementMatchingScopes": { "objectpath": "SELF_OR_PREFIX" },
+        "accessType": "write", "user": "user3"
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1 }
+    },
+    {
+      "name":    "Verify user3 has no read access to any object under 
s3://mycompany/vendor/pii",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/vendor/pii" } }, "resourceElementMatchingScopes": { "objectpath": 
"SELF_OR_PREFIX" },
+        "accessType": "read", "user": "user3"
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1 }
+    },
+    {
+      "name":    "Verify user4 has read access to some objects under 
s3://mycompany/vendor",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/vendor" } }, "resourceElementMatchingScopes": { "objectpath": 
"SELF_OR_PREFIX" },
+        "accessType": "read", "user": "user4"
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 1002 }
+    },
+    {
+      "name":    "Verify user4 has read access to some objects under 
s3://mycompany/vendor/pii",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/vendor/pii" } }, "resourceElementMatchingScopes": { "objectpath": 
"SELF_OR_PREFIX" },
+        "accessType": "read", "user": "user4"
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 1002 }
+    },
+    {
+      "name":    "Verify user4 has read access to some objects under 
s3://mycompany/vendor/pii/test",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/vendor/pii/test" } }, "resourceElementMatchingScopes": { "objectpath": 
"SELF_OR_PREFIX" },
+        "accessType": "read", "user": "user4"
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 1002 }
+    },
+    {
+      "name":    "Verify user4 has no read access to any object under 
s3://mycompany/pii",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/pii" } }, "resourceElementMatchingScopes": { "objectpath": "SELF_OR_PREFIX" },
+        "accessType": "read", "user": "user4"
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1 }
+    },
+    {
+      "name":    "Verify user4 has no write access to any object under 
s3://mycompany/pii",
+      "request": {
+        "resource":   { "elements": { "bucketname": "mycompany", "objectpath": 
"/pii" } }, "resourceElementMatchingScopes": { "objectpath": "SELF_OR_PREFIX" },
+        "accessType": "write", "user": "user4"
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1 }
+    }
+  ]
+}
+
diff --git 
a/agents-common/src/test/resources/policyengine/test_policyengine_kafka.json 
b/agents-common/src/test/resources/policyengine/test_policyengine_kafka.json
new file mode 100644
index 000000000..89ab9c0b5
--- /dev/null
+++ b/agents-common/src/test/resources/policyengine/test_policyengine_kafka.json
@@ -0,0 +1,157 @@
+{
+  "serviceName": "kafkadev",
+
+  "serviceDef": {
+    "name": "kafka", "id": 9,
+    "resources": [
+      { "name": "topic",           "level": 1, "mandatory": true, 
"lookupSupported": true, "matcher": 
"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", 
"matcherOptions": { "wildCard": true, "ignoreCase": true }, "label": "Topic",   
         "description": "Topic",            "accessTypeRestrictions": [ 
"create", "delete", "configure", "alter", "alter_configs", "describe", 
"describe_configs", "consume", "publish" ] },
+      { "name": "transactionalid", "level": 1, "mandatory": true, 
"lookupSupported": true, "matcher": 
"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", 
"matcherOptions": { "wildCard": true, "ignoreCase": true }, "label": 
"Transactional Id", "description": "Transactional Id", 
"accessTypeRestrictions": [ "describe", "publish" ] },
+      { "name": "cluster",         "level": 1, "mandatory": true, 
"lookupSupported": true, "matcher": 
"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", 
"matcherOptions": { "wildCard": true, "ignoreCase": true }, "label": "Cluster", 
         "description": "Cluster",          "accessTypeRestrictions": [ 
"create", "configure", "alter", "alter_configs", "describe", 
"describe_configs", "kafka_admin", "idempotent_write", "cluster_action" ] },
+      { "name": "delegationtoken", "level": 1, "mandatory": true, 
"lookupSupported": true, "matcher": 
"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", 
"matcherOptions": { "wildCard": true, "ignoreCase": true }, "label": 
"Delegation Token", "description": "Delegation Token", 
"accessTypeRestrictions": [ "describe" ] },
+      { "name": "consumergroup",   "level": 1, "mandatory": true, 
"lookupSupported": true, "matcher": 
"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", 
"matcherOptions": { "wildCard": true, "ignoreCase": true }, "label": "Consumer 
Group",   "description": "Consumer Group",   "accessTypeRestrictions": [ 
"consume", "describe", "delete" ] }
+    ],
+    "accessTypes": [
+      { "name": "publish",     "label": "Publish",     "impliedGrants": [ 
"describe" ] },
+      { "name": "consume",     "label": "Consume",     "impliedGrants": [ 
"describe" ] },
+      { "name": "configure",   "label": "Configure",   "impliedGrants": [ 
"describe" ] },
+      { "name": "describe",    "label": "Describe" },
+      { "name": "kafka_admin", "label": "Kafka Admin", "impliedGrants": [ 
"publish", "consume", "configure", "describe", "create", "delete", 
"describe_configs", "alter_configs", "alter", "idempotent_write", 
"cluster_action" ] },
+      { "name": "create",           "label": "Create" },
+      { "name": "delete",           "label": "Delete", "impliedGrants": [ 
"describe" ] },
+      { "name": "idempotent_write", "label": "Idempotent Write" },
+      { "name": "describe_configs", "label": "Describe Configs" },
+      { "name": "alter_configs",    "label": "Alter Configs" },
+      { "name": "cluster_action",   "label": "Cluster Action" },
+      { "name": "alter",            "label": "alter" }
+    ]
+  },
+
+  "policies": [
+    {
+      "id": 10,"name": "10: test-topic publish/consume allowed","isEnabled": 
true,"isAuditEnabled": true,
+      "resources": { "topic": {"values": [ "test-topic-1" ], "isRecursive": 
true } },
+      "policyItems": [
+        {"accesses": [{"type": "publish", "isAllowed": true },{"type": 
"consume", "isAllowed": true }], "users": [ "user1" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 101,"name": "101: test-topic publish/consume allowed","isEnabled": 
true,"isAuditEnabled": true,
+      "resources": { "topic": {"values": [ "test-topic-2" ], "isRecursive": 
true } },
+      "policyItems": [
+        {"accesses": [{"type": "publish", "isAllowed": true },{"type": 
"consume", "isAllowed": true }], "users": [ "user2" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 102,"name": "102: test-topic publish/consume allowed","isEnabled": 
true,"isAuditEnabled": true,
+      "resources": {"topic": {"values": [ "test-topic-1","test-topic-4" ], 
"isRecursive": true } },
+      "policyItems": [
+        {"accesses": [{"type": "consume", "isAllowed": true }], "users": [ 
"user3" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 103,"name": "103: test-topic publish/consume allowed","isEnabled": 
true,"isAuditEnabled": true,
+      "resources": { "topic": {"values": [ "test-topic-1","test-topic-5" ], 
"isRecursive": true } },
+      "policyItems": [
+        {"accesses": [{"type": "consume", "isAllowed": true }], "users": [ 
"user4", "user5" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 104,"name": "104: test-topic publish/consume allowed","isEnabled": 
true,"isAuditEnabled": true,
+      "resources": { "topic": {"values": [ "test-topic-7" ], "isRecursive": 
true } },
+      "policyItems": [
+        {"accesses": [{"type": "publish", "isAllowed": true },{"type": 
"consume", "isAllowed": true }], "users": [ "user6" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 20,"name": "02: transation id","isEnabled": true,"isAuditEnabled": 
true,"policyType": 1,
+      "resources": { "delegationtoken": {"values": [ "tid-1" ], "isRecursive": 
true } },
+      "policyItems": [
+        {"accesses": [{"type": "publish", "isAllowed": true }], "users": [ 
"user1" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 30,"name": "create/alter access for user1 on 
cluster-1","isEnabled": true,"isAuditEnabled": true,
+      "resources": { "cluster": {"values": [ "cluseter-1" ], "isRecursive": 
true } },
+      "policyItems": [
+        {"accesses": [{"type": "create", "isAllowed": true },{"type": "alter", 
"isAllowed": true }], "users": [ "user1" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 301,"name": "Alter access for user31 on cluster-2","isEnabled": 
true,"isAuditEnabled": true,
+      "resources": { "cluster": {"values": [ "cluster-2" ], "isRecursive": 
true } },
+      "policyItems": [
+        {"accesses": [{"type": "alter", "isAllowed": true }], "users": [ 
"user31" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 302,"name": "Alter access for user32 on cluster-1","isEnabled": 
true,"isAuditEnabled": true,
+      "resources": { "cluster": {"values": [ "cluseter-1" ], "isRecursive": 
true } },
+      "policyItems": [
+        {"accesses": [{"type": "alter", "isAllowed": true }], "users": [ 
"user32" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 40,"name": "delegationtoken","isEnabled": true,"isAuditEnabled": 
true,
+      "resources": { "delegationtoken": {"values": [ "dt-1" ], "isRecursive": 
true } },
+      "policyItems": [
+        {"accesses": [{"type": "describe", "isAllowed": true }], "users": [ 
"user1" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 50,"name": "consumergroup-1 access","isEnabled": 
true,"isAuditEnabled": true,
+      "resources": { "consumergroup": {"values": [ "consumergroup-1" ], 
"isRecursive": true } },
+      "policyItems": [
+        {"accesses": [{"type": "consume", "isAllowed": true }], "users": [ 
"user1" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 52,"name": "consumergroup-2 access for user4","isEnabled": 
true,"isAuditEnabled": true,
+      "resources": { "consumergroup": {"values": [ "consumergroup-2" ], 
"isRecursive": true } },
+      "policyItems": [
+        {"accesses": [{"type": "consume", "isAllowed": true }], "users": [ 
"user4" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 110,"name": "110: test-topic-1/2 consume allowed for 
user2","isEnabled": true,"isAuditEnabled": true,
+      "resources": { "topic": {"values": [ "test-topic-1", "test-topic-2" ], 
"isRecursive": true } },
+      "policyItems": [
+        {"accesses": [{"type": "consume", "isAllowed": true }], "users": [ 
"user2" ], "groups": [] }
+      ]
+    },
+    {
+      "id": 111, "name": "110: new-topic-1/2 allowed for user2", "isEnabled": 
true, "isAuditEnabled": true,
+      "resources": { "topic": { "values": [ "new-topic-1", "new-topic-2" ], 
"isRecursive": true } },
+      "policyItems": [
+        { "accesses": [ { "type": "consume", "isAllowed": true } ], "users": [ 
"user2" ], "groups": [] }
+      ]
+    }
+  ],
+  "tests": [
+    {
+      "name":    "Any topic Consume access for user3",
+      "request": {
+        "resource":   { "elements": { "topic": "" } }, 
"resourceElementMatchingScopes": { "topic": "SELF_OR_PREFIX" },
+        "accessType": "consume", "user": "user3", "userGroups": []
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 102 }
+    },
+    {
+      "name":    "Any consumergroup consume access for user1",
+      "request": {
+        "resource":   { "elements": { "consumergroup": "" } }, 
"resourceElementMatchingScopes": { "consumergroup": "SELF_OR_PREFIX" },
+        "accessType": "consume", "user": "user1", "userGroups": []
+      },
+      "result": { "isAudited": true, "isAllowed": true," policyId": 50 }
+    },
+
+    {
+      "name":    "Any consumergroup consume access for user3",
+      "request": {
+        "resource":   { "elements": { "consumergroup": "" } }, 
"resourceElementMatchingScopes": { "consumergroup": "SELF_OR_PREFIX" },
+        "accessType": "consume", "user": "user3", "userGroups": []
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1 }
+    }
+  ]
+}
+

Reply via email to