You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2023/02/23 00:18:31 UTC
[ranger] branch ranger-2.4 updated: RANGER-4100: Efficient computation of the smallest set of evaluators returned by search of multiple Trie trees
This is an automated email from the ASF dual-hosted git repository.
madhan pushed a commit to branch ranger-2.4
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.4 by this push:
new 7ec75608e RANGER-4100: Efficient computation of the smallest set of evaluators returned by search of multiple Trie trees
7ec75608e is described below
commit 7ec75608e7bcdfe286885fecaf00ea3a8d7a318f
Author: Abhay Kulkarni <ab...@apache.org>
AuthorDate: Mon Feb 20 14:11:05 2023 -0800
RANGER-4100: Efficient computation of the smallest set of evaluators returned by search of multiple Trie trees
(cherry picked from commit 85f5483ed444bf40caa588ec5b788a51532c3095)
---
.../plugin/contextenricher/RangerTagEnricher.java | 75 +---------
.../validation/RangerSecurityZoneValidator.java | 65 +--------
.../ranger/plugin/policyengine/PolicyEngine.java | 111 ++++-----------
.../util/RangerResourceEvaluatorsRetriever.java | 158 +++++++++++++++++++++
.../plugin/policyengine/TestPolicyEngine.java | 3 +-
5 files changed, 195 insertions(+), 217 deletions(-)
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 da06e4161..93d1e9d08 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
@@ -44,6 +44,7 @@ import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
import org.apache.ranger.plugin.util.RangerCommonConstants;
import org.apache.ranger.plugin.util.RangerPerfTracer;
import org.apache.ranger.plugin.util.RangerReadWriteLock;
+import org.apache.ranger.plugin.util.RangerResourceEvaluatorsRetriever;
import org.apache.ranger.plugin.util.RangerServiceNotFoundException;
import org.apache.ranger.plugin.util.RangerServiceTagsDeltaUtil;
import org.apache.ranger.plugin.util.ServiceTags;
@@ -548,7 +549,7 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
RangerAccessRequestImpl request = new RangerAccessRequestImpl();
request.setResource(accessResource);
- List<RangerServiceResourceMatcher> oldMatchers = getEvaluators(request, enrichedServiceTags);
+ Collection<RangerServiceResourceMatcher> oldMatchers = getEvaluators(request, enrichedServiceTags);
if (LOG.isDebugEnabled()) {
LOG.debug("Found [" + oldMatchers.size() + "] matchers for service-resource[" + serviceResource + "]");
@@ -669,7 +670,7 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
ret = enrichedServiceTags.getTagsForEmptyResourceAndAnyAccess();
} else {
- final List<RangerServiceResourceMatcher> serviceResourceMatchers = getEvaluators(request, enrichedServiceTags);
+ final Collection<RangerServiceResourceMatcher> serviceResourceMatchers = getEvaluators(request, enrichedServiceTags);
if (CollectionUtils.isNotEmpty(serviceResourceMatchers)) {
@@ -715,11 +716,11 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
return ret;
}
- private List<RangerServiceResourceMatcher> getEvaluators(RangerAccessRequest request, EnrichedServiceTags enrichedServiceTags) {
+ private Collection<RangerServiceResourceMatcher> getEvaluators(RangerAccessRequest request, EnrichedServiceTags enrichedServiceTags) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerTagEnricher.getEvaluators(request=" + request + ")");
}
- List<RangerServiceResourceMatcher> ret = Collections.EMPTY_LIST;
+ Collection<RangerServiceResourceMatcher> ret;
RangerAccessResource resource = request.getResource();
@@ -734,71 +735,7 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
perf = RangerPerfTracer.getPerfTracer(PERF_TRIE_OP_LOG, "RangerTagEnricher.getEvaluators(resource=" + resource.getAsString() + ")");
}
- List<String> resourceKeys = serviceDefHelper.getOrderedResourceNames(resource.getKeys());
- Set<RangerServiceResourceMatcher> smallestList = null;
-
- if (CollectionUtils.isNotEmpty(resourceKeys)) {
-
- for (String resourceName : resourceKeys) {
- RangerResourceTrie<RangerServiceResourceMatcher> trie = serviceResourceTrie.get(resourceName);
-
- if (trie == null) { // if no trie exists for this resource level, ignore and continue to next level
- continue;
- }
-
- Set<RangerServiceResourceMatcher> serviceResourceMatchersForResource = trie.getEvaluatorsForResource(resource.getValue(resourceName), request.getResourceMatchingScope());
- Set<RangerServiceResourceMatcher> inheritedResourceMatchers = trie.getInheritedEvaluators();
-
- if (smallestList != null) {
- if (CollectionUtils.isEmpty(inheritedResourceMatchers) && CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
- smallestList = null;
- } else if (CollectionUtils.isEmpty(inheritedResourceMatchers)) {
- smallestList.retainAll(serviceResourceMatchersForResource);
- } else if (CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
- smallestList.retainAll(inheritedResourceMatchers);
- } else {
- Set<RangerServiceResourceMatcher> smaller, bigger;
- if (serviceResourceMatchersForResource.size() < inheritedResourceMatchers.size()) {
- smaller = serviceResourceMatchersForResource;
- bigger = inheritedResourceMatchers;
- } else {
- smaller = inheritedResourceMatchers;
- bigger = serviceResourceMatchersForResource;
- }
- Set<RangerServiceResourceMatcher> tmp = new HashSet<>();
- if (smallestList.size() < smaller.size()) {
- smallestList.stream().filter(smaller::contains).forEach(tmp::add);
- smallestList.stream().filter(bigger::contains).forEach(tmp::add);
- } else {
- smaller.stream().filter(smallestList::contains).forEach(tmp::add);
- if (smallestList.size() < bigger.size()) {
- smallestList.stream().filter(bigger::contains).forEach(tmp::add);
- } else {
- bigger.stream().filter(smallestList::contains).forEach(tmp::add);
- }
- }
- smallestList = tmp;
- }
- } else {
- if (CollectionUtils.isEmpty(inheritedResourceMatchers) || CollectionUtils.isEmpty(serviceResourceMatchersForResource)) {
- Set<RangerServiceResourceMatcher> tmp = CollectionUtils.isEmpty(inheritedResourceMatchers) ? serviceResourceMatchersForResource : inheritedResourceMatchers;
- smallestList = resourceKeys.size() == 1 || CollectionUtils.isEmpty(tmp) ? tmp : new HashSet<>(tmp);
- } else {
- smallestList = new HashSet<>(serviceResourceMatchersForResource);
- smallestList.addAll(inheritedResourceMatchers);
- }
- }
-
- if (CollectionUtils.isEmpty(smallestList)) {// no tags for this resource, bail out
- smallestList = null;
- break;
- }
- }
- }
-
- if (smallestList != null) {
- ret = new ArrayList<>(smallestList);
- }
+ ret = RangerResourceEvaluatorsRetriever.getEvaluators(serviceResourceTrie, resource.getAsMap(), request.getResourceMatchingScope());
RangerPerfTracer.logAlways(perf);
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java
index f1045ad60..ca899979a 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerSecurityZoneValidator.java
@@ -35,11 +35,13 @@ import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatche
import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
import org.apache.ranger.plugin.store.SecurityZoneStore;
import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.RangerResourceEvaluatorsRetriever;
import org.apache.ranger.plugin.util.SearchFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -407,69 +409,12 @@ public class RangerSecurityZoneValidator extends RangerValidator {
// flag error if there are more than one matching evaluators with different zone-ids.
//
- RangerServiceDefHelper serviceDefHelper = new RangerServiceDefHelper(serviceDef, true);
-
for (RangerSecurityZone zone : zones) {
List<HashMap<String, List<String>>> resources = zone.getServices().get(serviceName).getResources();
for (Map<String, List<String>> resource : resources) {
- Set<RangerZoneResourceMatcher> smallestList = null;
-
- List<String> resourceKeys = serviceDefHelper.getOrderedResourceNames(resource.keySet());
-
- for (String resourceDefName : resourceKeys) {
- List<String> resourceValues = resource.get(resourceDefName);
-
- RangerResourceTrie<RangerZoneResourceMatcher> trie = trieMap.get(resourceDefName);
-
- Set<RangerZoneResourceMatcher> zoneMatchersForResource = trie.getEvaluatorsForResource(resourceValues);
- Set<RangerZoneResourceMatcher> inheritedZoneMatchers = trie.getInheritedEvaluators();
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("ResourceDefName:[" + resourceDefName + "], values:[" + resourceValues + "], matched-zones:[" + zoneMatchersForResource + "], inherited-zones:[" + inheritedZoneMatchers + "]");
- }
-
- if (smallestList != null) {
- if (CollectionUtils.isEmpty(inheritedZoneMatchers) && CollectionUtils.isEmpty(zoneMatchersForResource)) {
- smallestList = null;
- } else if (CollectionUtils.isEmpty(inheritedZoneMatchers)) {
- smallestList.retainAll(zoneMatchersForResource);
- } else if (CollectionUtils.isEmpty(zoneMatchersForResource)) {
- smallestList.retainAll(inheritedZoneMatchers);
- } else {
- Set<RangerZoneResourceMatcher> smaller, bigger;
- if (zoneMatchersForResource.size() < inheritedZoneMatchers.size()) {
- smaller = zoneMatchersForResource;
- bigger = inheritedZoneMatchers;
- } else {
- smaller = inheritedZoneMatchers;
- bigger = zoneMatchersForResource;
- }
- Set<RangerZoneResourceMatcher> tmp = new HashSet<>();
- if (smallestList.size() < smaller.size()) {
- smallestList.stream().filter(smaller::contains).forEach(tmp::add);
- smallestList.stream().filter(bigger::contains).forEach(tmp::add);
- } else {
- smaller.stream().filter(smallestList::contains).forEach(tmp::add);
- if (smallestList.size() < bigger.size()) {
- smallestList.stream().filter(bigger::contains).forEach(tmp::add);
- } else {
- bigger.stream().filter(smallestList::contains).forEach(tmp::add);
- }
- }
- smallestList = tmp;
- }
- } else {
- if (CollectionUtils.isEmpty(inheritedZoneMatchers) || CollectionUtils.isEmpty(zoneMatchersForResource)) {
- Set<RangerZoneResourceMatcher> tmp = CollectionUtils.isEmpty(inheritedZoneMatchers) ? zoneMatchersForResource : inheritedZoneMatchers;
- smallestList = resourceKeys.size() == 1 || CollectionUtils.isEmpty(tmp) ? tmp : new HashSet<>(tmp);
- } else {
- smallestList = new HashSet<>(zoneMatchersForResource);
- smallestList.addAll(inheritedZoneMatchers);
- }
- }
- }
+ Collection<RangerZoneResourceMatcher> smallestList = RangerResourceEvaluatorsRetriever.getEvaluators(trieMap, resource);
if (LOG.isDebugEnabled()) {
LOG.debug("Resource:[" + resource +"], matched-zones:[" + smallestList +"]");
@@ -479,8 +424,6 @@ public class RangerSecurityZoneValidator extends RangerValidator {
continue;
}
- final Set<RangerZoneResourceMatcher> intersection = smallestList;
-
RangerAccessResourceImpl accessResource = new RangerAccessResourceImpl();
accessResource.setServiceDef(serviceDef);
@@ -491,7 +434,7 @@ public class RangerSecurityZoneValidator extends RangerValidator {
Set<String> matchedZoneNames = new HashSet<>();
- for (RangerZoneResourceMatcher zoneMatcher : intersection) {
+ for (RangerZoneResourceMatcher zoneMatcher : smallestList) {
if (LOG.isDebugEnabled()) {
LOG.debug("Trying to match resource:[" + accessResource +"] using zoneMatcher:[" + zoneMatcher + "]");
}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java
index f44570623..3864f30d2 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java
@@ -21,6 +21,8 @@ package org.apache.ranger.plugin.policyengine;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -28,14 +30,12 @@ import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.collections.ListUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ranger.plugin.contextenricher.RangerContextEnricher;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicyDelta;
import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper;
import org.apache.ranger.plugin.model.validation.RangerZoneResourceMatcher;
import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
@@ -44,6 +44,7 @@ import org.apache.ranger.plugin.service.RangerAuthContext;
import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
import org.apache.ranger.plugin.util.RangerPerfTracer;
import org.apache.ranger.plugin.util.RangerPolicyDeltaUtil;
+import org.apache.ranger.plugin.util.RangerResourceEvaluatorsRetriever;
import org.apache.ranger.plugin.util.RangerReadWriteLock;
import org.apache.ranger.plugin.util.RangerRoles;
import org.apache.ranger.plugin.util.ServicePolicies;
@@ -62,7 +63,7 @@ public class PolicyEngine {
private final List<RangerContextEnricher> allContextEnrichers;
private final RangerPluginContext pluginContext;
private final Map<String, RangerPolicyRepository> zonePolicyRepositories = new HashMap<>();
- private final Map<String, RangerResourceTrie> resourceZoneTrie = new HashMap<>();
+ private final Map<String, RangerResourceTrie<RangerZoneResourceMatcher>> resourceZoneTrie = new HashMap<>();
private final Map<String, String> zoneTagServiceMap = new HashMap<>();
private boolean useForwardedIPAddress;
private String[] trustedProxyAddresses;
@@ -173,10 +174,10 @@ public class PolicyEngine {
public List<RangerPolicy> getResourcePolicies(String zoneName) {
RangerPolicyRepository zoneResourceRepository = zonePolicyRepositories.get(zoneName);
- return zoneResourceRepository == null ? ListUtils.EMPTY_LIST : zoneResourceRepository.getPolicies();
+ return zoneResourceRepository == null ? Collections.emptyList() : zoneResourceRepository.getPolicies();
}
- Map<String, RangerResourceTrie> getResourceZoneTrie() {
+ Map<String, RangerResourceTrie<RangerZoneResourceMatcher>> getResourceZoneTrie() {
return resourceZoneTrie;
}
@@ -466,101 +467,39 @@ public class PolicyEngine {
Set<String> ret = null;
if (MapUtils.isNotEmpty(this.resourceZoneTrie)) {
- Set<RangerZoneResourceMatcher> smallestList = null;
- RangerServiceDefHelper serviceDefHelper = policyRepository.getOptions().getServiceDefHelper();
- List<String> resourceKeys = resource == null ? new ArrayList<>() : serviceDefHelper.getOrderedResourceNames(resource.keySet());
-
- for (String resourceDefName : resourceKeys) {
- RangerResourceTrie<RangerZoneResourceMatcher> trie = resourceZoneTrie.get(resourceDefName);
-
- if (trie == null) {
- continue;
- }
-
- Object resourceValues = resource.get(resourceDefName);
-
- Set<RangerZoneResourceMatcher> zoneMatchersForResource = trie.getEvaluatorsForResource(resourceValues);
- Set<RangerZoneResourceMatcher> inheritedZoneMatchers = trie.getInheritedEvaluators();
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("ResourceDefName:[" + resourceDefName + "], values:[" + resourceValues + "], matched-zones:[" + zoneMatchersForResource + "], inherited-zones:[" + inheritedZoneMatchers + "]");
- }
-
- if (smallestList != null) {
- if (CollectionUtils.isEmpty(inheritedZoneMatchers) && CollectionUtils.isEmpty(zoneMatchersForResource)) {
- smallestList = null;
- } else if (CollectionUtils.isEmpty(inheritedZoneMatchers)) {
- smallestList.retainAll(zoneMatchersForResource);
- } else if (CollectionUtils.isEmpty(zoneMatchersForResource)) {
- smallestList.retainAll(inheritedZoneMatchers);
- } else {
- Set<RangerZoneResourceMatcher> smaller, bigger;
- if (zoneMatchersForResource.size() < inheritedZoneMatchers.size()) {
- smaller = zoneMatchersForResource;
- bigger = inheritedZoneMatchers;
- } else {
- smaller = inheritedZoneMatchers;
- bigger = zoneMatchersForResource;
- }
- Set<RangerZoneResourceMatcher> tmp = new HashSet<>();
- if (smallestList.size() < smaller.size()) {
- smallestList.stream().filter(smaller::contains).forEach(tmp::add);
- smallestList.stream().filter(bigger::contains).forEach(tmp::add);
- } else {
- smaller.stream().filter(smallestList::contains).forEach(tmp::add);
- if (smallestList.size() < bigger.size()) {
- smallestList.stream().filter(bigger::contains).forEach(tmp::add);
- } else {
- bigger.stream().filter(smallestList::contains).forEach(tmp::add);
- }
- }
- smallestList = tmp;
- }
- } else {
- if (CollectionUtils.isEmpty(inheritedZoneMatchers) || CollectionUtils.isEmpty(zoneMatchersForResource)) {
- Set<RangerZoneResourceMatcher> tmp = CollectionUtils.isEmpty(inheritedZoneMatchers) ? zoneMatchersForResource : inheritedZoneMatchers;
- smallestList = resourceKeys.size() == 1 || CollectionUtils.isEmpty(tmp) ? tmp : new HashSet<>(tmp);
- } else {
- smallestList = new HashSet<>(zoneMatchersForResource);
- smallestList.addAll(inheritedZoneMatchers);
- }
- }
- }
+ Collection<RangerZoneResourceMatcher> smallestList = RangerResourceEvaluatorsRetriever.getEvaluators(resourceZoneTrie, resource);
if (CollectionUtils.isNotEmpty(smallestList)) {
- final Set<RangerZoneResourceMatcher> intersection = smallestList;
if (LOG.isDebugEnabled()) {
- LOG.debug("Resource:[" + resource + "], matched-zones:[" + intersection + "]");
+ LOG.debug("Resource:[" + resource + "], matched-zones:[" + smallestList + "]");
}
- if (intersection.size() > 0) {
- ret = new HashSet<>();
+ ret = new HashSet<>();
- for (RangerZoneResourceMatcher zoneMatcher : intersection) {
+ for (RangerZoneResourceMatcher zoneMatcher : smallestList) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Trying to match resource:[" + accessResource + "] using zoneMatcher:[" + zoneMatcher + "]");
+ }
+
+ // These are potential matches. Try to really match them
+ if (zoneMatcher.getPolicyResourceMatcher().isMatch(accessResource, RangerPolicyResourceMatcher.MatchScope.ANY, null)) {
if (LOG.isDebugEnabled()) {
- LOG.debug("Trying to match resource:[" + accessResource + "] using zoneMatcher:[" + zoneMatcher + "]");
+ LOG.debug("Matched resource:[" + accessResource + "] using zoneMatcher:[" + zoneMatcher + "]");
}
- // These are potential matches. Try to really match them
- if (zoneMatcher.getPolicyResourceMatcher().isMatch(accessResource, RangerPolicyResourceMatcher.MatchScope.ANY, null)) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Matched resource:[" + accessResource + "] using zoneMatcher:[" + zoneMatcher + "]");
- }
-
- // Actual match happened
- ret.add(zoneMatcher.getSecurityZoneName());
- } else {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Did not match resource:[" + accessResource + "] using zoneMatcher:[" + zoneMatcher + "]");
- }
+ // Actual match happened
+ ret.add(zoneMatcher.getSecurityZoneName());
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Did not match resource:[" + accessResource + "] using zoneMatcher:[" + zoneMatcher + "]");
}
}
+ }
- if (LOG.isDebugEnabled()) {
- LOG.debug("The following zone-names matched resource:[" + accessResource + "]: " + ret);
- }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("The following zone-names matched resource:[" + accessResource + "]: " + ret);
}
}
}
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
new file mode 100644
index 000000000..dfe591c59
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerResourceEvaluatorsRetriever.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.util;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerResourceTrie;
+import org.apache.ranger.plugin.policyresourcematcher.RangerResourceEvaluator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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);
+ }
+
+ public static <T extends RangerResourceEvaluator> Collection<T> getEvaluators(Map<String, RangerResourceTrie<T>> resourceTrie, Map<String, ?> resource, RangerAccessRequest.ResourceMatchingScope scope) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerPolicyResourceEvaluatorsRetriever.getEvaluators(" + resource + ")");
+ }
+ Set<T> ret = null;
+
+ if (MapUtils.isNotEmpty(resourceTrie) && MapUtils.isNotEmpty(resource)) {
+ Set<String> resourceKeys = resource.keySet();
+
+ List<Evaluators<T>> sortedEvaluators = new ArrayList<>(resourceKeys.size());
+
+ for (String resourceDefName : resourceKeys) {
+ RangerResourceTrie<T> trie = resourceTrie.get(resourceDefName);
+
+ if (trie == null) {
+ continue;
+ }
+
+ Object resourceValues = resource.get(resourceDefName);
+
+ Set<T> inheritedMatchers = trie.getInheritedEvaluators();
+ Set<T> matchersForResource = trie.getEvaluatorsForResource(resourceValues, scope);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("ResourceDefName:[" + resourceDefName + "], values:[" + resourceValues + "], resource-matchers:[" + matchersForResource + "], inherited-matchers:[" + inheritedMatchers + "]");
+ }
+ if (CollectionUtils.isEmpty(inheritedMatchers) && CollectionUtils.isEmpty(matchersForResource)) {
+ sortedEvaluators.clear();
+ break;
+ }
+ sortedEvaluators.add(new Evaluators<>(inheritedMatchers, matchersForResource));
+ }
+
+ if (CollectionUtils.isNotEmpty(sortedEvaluators)) {
+ Collections.sort(sortedEvaluators);
+
+ ret = sortedEvaluators.remove(0).getMatchers();
+
+ for (Evaluators<T> evaluators : sortedEvaluators) {
+ if (CollectionUtils.isEmpty(evaluators.inheritedMatchers)) {
+ ret.retainAll(evaluators.resourceMatchers);
+ } else if (CollectionUtils.isEmpty(evaluators.resourceMatchers)) {
+ ret.retainAll(evaluators.inheritedMatchers);
+ } else {
+ Set<T> smaller = evaluators.getSmaller();
+ Set<T> bigger = evaluators.getBigger();
+
+ Set<T> tmp = new HashSet<>(ret.size());
+
+ if (ret.size() < smaller.size()) {
+ ret.stream().filter(smaller::contains).forEach(tmp::add);
+ ret.stream().filter(bigger::contains).forEach(tmp::add);
+ } else {
+ smaller.stream().filter(ret::contains).forEach(tmp::add);
+ if (ret.size() < bigger.size()) {
+ ret.stream().filter(bigger::contains).forEach(tmp::add);
+ } else {
+ bigger.stream().filter(ret::contains).forEach(tmp::add);
+ }
+ }
+ ret = tmp;
+ }
+ if (ret.isEmpty()) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerResourceEvaluatorsRetriever.getEvaluators(" + resource + ") : evaluator:[" + ret + "]");
+ }
+ return ret;
+ }
+
+ static class Evaluators<T> implements Comparable<Evaluators<T>> {
+ private final Set<T> inheritedMatchers;
+ private final Set<T> resourceMatchers;
+ private final Set<T> smaller;
+ private final Set<T> bigger;
+ private final int size;
+
+ Evaluators(Set<T> inherited, Set<T> matched) {
+ inheritedMatchers = inherited == null ? Collections.emptySet() : inherited;
+ resourceMatchers = matched == null ? Collections.emptySet() : matched;
+ size = inheritedMatchers.size() + resourceMatchers.size();
+ smaller = inheritedMatchers.size() < resourceMatchers.size() ? inheritedMatchers : resourceMatchers;
+ bigger = smaller == inheritedMatchers ? resourceMatchers : inheritedMatchers;
+ }
+
+ // Should be called at most once
+ Set<T> getMatchers() {
+ Set<T> ret = new HashSet<>(size);
+
+ ret.addAll(inheritedMatchers);
+ ret.addAll(resourceMatchers);
+
+ return ret;
+ }
+
+ Set<T> getSmaller() {
+ return smaller;
+ }
+
+ Set<T> getBigger() {
+ return bigger;
+ }
+
+ @Override
+ public int compareTo(Evaluators<T> other) {
+ return Integer.compare(size, other.size);
+ }
+ }
+}
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 eb3d0ff46..632d7cf7e 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
@@ -44,6 +44,7 @@ import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerServiceResource;
import org.apache.ranger.plugin.model.RangerValiditySchedule;
import org.apache.ranger.plugin.model.validation.RangerValidityScheduleValidator;
+import org.apache.ranger.plugin.model.validation.RangerZoneResourceMatcher;
import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
import org.apache.ranger.plugin.policyengine.TestPolicyEngine.PolicyEngineTestCase.TestData;
import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator.RangerPolicyResourceEvaluator;
@@ -958,7 +959,7 @@ public class TestPolicyEngine {
ret = Objects.equals(me.getResourceZoneTrie().keySet(), other.getResourceZoneTrie().keySet());
if (ret) {
- for (Map.Entry<String, RangerResourceTrie> entry : me.getResourceZoneTrie().entrySet()) {
+ for (Map.Entry<String, RangerResourceTrie<RangerZoneResourceMatcher>> entry : me.getResourceZoneTrie().entrySet()) {
ret = compareSubtree(entry.getValue(), other.getResourceZoneTrie().get(entry.getKey()));
if (!ret) {