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 0558fa9cc RANGER-4507: refactoring to move security-zone finder to RangerSecurityZoneMatcher 0558fa9cc is described below commit 0558fa9cc63ab3ea17c42b471a7e6b834bc368fa Author: Madhan Neethiraj <mad...@apache.org> AuthorDate: Tue Oct 31 13:14:19 2023 -0700 RANGER-4507: refactoring to move security-zone finder to RangerSecurityZoneMatcher --- .../ranger/plugin/policyengine/PolicyEngine.java | 177 ++--------------- .../policyengine/RangerSecurityZoneMatcher.java | 209 +++++++++++++++++++++ .../ranger/plugin/service/RangerAuthContext.java | 13 +- .../plugin/policyengine/TestPolicyEngine.java | 13 +- .../TestRangerSecurityZoneMatcher.java | 159 ++++++++++++++++ 5 files changed, 397 insertions(+), 174 deletions(-) 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 063b685d0..858c3f542 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 @@ -24,7 +24,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -37,20 +36,17 @@ 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; import org.apache.ranger.plugin.resourcematcher.RangerAbstractResourceMatcher; 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.ServiceDefUtil; import org.apache.ranger.plugin.util.ServicePolicies; import org.apache.ranger.plugin.util.StringTokenReplacer; +import org.apache.ranger.plugin.util.RangerUserStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,8 +62,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<RangerZoneResourceMatcher>> resourceZoneTrie = new HashMap<>(); - private final Map<String, String> zoneTagServiceMap = new HashMap<>(); + private final RangerSecurityZoneMatcher zoneMatcher; private boolean useForwardedIPAddress; private String[] trustedProxyAddresses; private final Map<String, StringTokenReplacer> tokenReplacers = new HashMap<>(); @@ -189,8 +184,8 @@ public class PolicyEngine { return zoneResourceRepository == null ? Collections.emptyList() : zoneResourceRepository.getPolicies(); } - Map<String, RangerResourceTrie<RangerZoneResourceMatcher>> getResourceZoneTrie() { - return resourceZoneTrie; + RangerSecurityZoneMatcher getZoneMatcher() { + return zoneMatcher; } public PolicyEngine(ServicePolicies servicePolicies, RangerPluginContext pluginContext, RangerRoles roles, boolean isUseReadWriteLock) { @@ -213,6 +208,7 @@ public class PolicyEngine { this.pluginContext = pluginContext; this.lock = new RangerReadWriteLock(isUseReadWriteLock); + this.zoneMatcher = new RangerSecurityZoneMatcher(servicePolicies.getSecurityZones(), servicePolicies.getServiceDef(), pluginContext); Boolean hasPolicyDeltas = RangerPolicyDeltaUtil.hasPolicyDeltas(servicePolicies); @@ -224,7 +220,11 @@ public class PolicyEngine { } } - this.pluginContext.setAuthContext(new RangerAuthContext(null, roles)); + RangerAuthContext currAuthContext = pluginContext.getAuthContext(); + RangerUserStore userStore = currAuthContext != null ? currAuthContext.getUserStoreUtil().getUserStore() : null; + RangerAuthContext authContext = new RangerAuthContext(null, zoneMatcher, roles, userStore); + + this.pluginContext.setAuthContext(authContext); RangerPolicyEngineOptions options = pluginContext.getConfig().getPolicyEngineOptions(); @@ -271,8 +271,6 @@ public class PolicyEngine { this.allContextEnrichers = tmpList; if (MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) { - buildZoneTrie(servicePolicies); - for (Map.Entry<String, ServicePolicies.SecurityZoneInfo> zone : servicePolicies.getSecurityZones().entrySet()) { RangerPolicyRepository policyRepository = new RangerPolicyRepository(servicePolicies, this.pluginContext, zone.getKey()); @@ -386,29 +384,27 @@ public class PolicyEngine { } public Set<String> getMatchedZonesForResourceAndChildren(Map<String, ?> resource) { - return getMatchedZonesForResourceAndChildren(convertToAccessResource(resource)); - } + Set<String> ret = zoneMatcher.getZonesForResourceAndChildren(resource); - public Set<String> getMatchedZonesForResourceAndChildren(RangerAccessResource accessResource) { if (LOG.isDebugEnabled()) { - LOG.debug("==> PolicyEngine.getMatchedZonesForResourceAndChildren(" + accessResource + ")"); + LOG.debug("getMatchedZonesForResourceAndChildren(resource={}): ret={}", resource, ret); } - Set<String> ret = null; + return ret; + } - if (MapUtils.isNotEmpty(this.resourceZoneTrie)) { - ret = getMatchedZonesForResourceAndChildren(accessResource.getAsMap(), accessResource); - } + public Set<String> getMatchedZonesForResourceAndChildren(RangerAccessResource resource) { + Set<String> ret = zoneMatcher.getZonesForResourceAndChildren(resource); if (LOG.isDebugEnabled()) { - LOG.debug("<== PolicyEngine.getMatchedZonesForResourceAndChildren(" + accessResource + ") : " + ret); + LOG.debug("getMatchedZonesForResourceAndChildren(resource={}): ret={}", resource, ret); } return ret; } public String getUniquelyMatchedZoneName(Map<String, ?> resourceAsMap) { - Set<String> matchedZones = getMatchedZonesForResourceAndChildren(resourceAsMap, convertToAccessResource(resourceAsMap)); + Set<String> matchedZones = zoneMatcher.getZonesForResourceAndChildren(resourceAsMap); String ret = (matchedZones != null && matchedZones.size() == 1) ? matchedZones.iterator().next() : null; if (LOG.isDebugEnabled()) { @@ -449,7 +445,7 @@ public class PolicyEngine { public boolean isResourceZoneAssociatedWithTagService(String resourceZoneName) { final boolean ret; - if (StringUtils.isNotEmpty(resourceZoneName) && tagPolicyRepository != null && zoneTagServiceMap.get(resourceZoneName) != null) { + if (StringUtils.isNotEmpty(resourceZoneName) && tagPolicyRepository != null && zoneMatcher.hasTagService(resourceZoneName)) { if (LOG.isDebugEnabled()) { LOG.debug("Accessed resource is in a zone:[" + resourceZoneName + "] which is associated with the tag-service:[" + tagPolicyRepository.getServiceName() + "]"); } @@ -512,76 +508,13 @@ public class PolicyEngine { } } - private Set<String> getMatchedZonesForResourceAndChildren(Map<String, ?> resource, RangerAccessResource accessResource) { - if (LOG.isDebugEnabled()) { - LOG.debug("==> PolicyEngine.getMatchedZonesForResourceAndChildren(" + resource + ", " + accessResource + ")"); - } - - Set<String> ret = null; - - if (MapUtils.isNotEmpty(this.resourceZoneTrie)) { - - Collection<RangerZoneResourceMatcher> smallestList = RangerResourceEvaluatorsRetriever.getEvaluators(resourceZoneTrie, resource); - - if (CollectionUtils.isNotEmpty(smallestList)) { - - if (LOG.isDebugEnabled()) { - LOG.debug("Resource:[" + resource + "], matched-zones:[" + smallestList + "]"); - } - - ret = new HashSet<>(); - - 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("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 + "]"); - } - } - } - - if (LOG.isDebugEnabled()) { - LOG.debug("The following zone-names matched resource:[" + accessResource + "]: " + ret); - } - } - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== PolicyEngine.getMatchedZonesForResourceAndChildren(" + resource + ", " + accessResource + ") : " + ret); - } - - return ret; - } - - private RangerAccessResource convertToAccessResource(Map<String, ?> resource) { - RangerAccessResourceImpl ret = new RangerAccessResourceImpl(); - - ret.setServiceDef(getServiceDef()); - - for (Map.Entry<String, ?> entry : resource.entrySet()) { - ret.setValue(entry.getKey(), entry.getValue()); - } - - return ret; - } - private PolicyEngine(final PolicyEngine other, ServicePolicies servicePolicies) { this.useForwardedIPAddress = other.useForwardedIPAddress; this.trustedProxyAddresses = other.trustedProxyAddresses; this.serviceDefHelper = other.serviceDefHelper; this.pluginContext = other.pluginContext; this.lock = other.lock; + this.zoneMatcher = new RangerSecurityZoneMatcher(servicePolicies.getSecurityZones(), servicePolicies.getServiceDef(), pluginContext); long policyVersion = servicePolicies.getPolicyVersion() != null ? servicePolicies.getPolicyVersion() : -1L; List<RangerPolicyDelta> defaultZoneDeltas = new ArrayList<>(); @@ -666,74 +599,6 @@ public class PolicyEngine { reorderPolicyEvaluators(); } - private void buildZoneTrie(ServicePolicies servicePolicies) { - if (LOG.isDebugEnabled()) { - LOG.debug("==> PolicyEngine.buildZoneTrie()"); - } - - Map<String, ServicePolicies.SecurityZoneInfo> securityZones = servicePolicies.getSecurityZones(); - - if (MapUtils.isNotEmpty(securityZones)) { - RangerServiceDef serviceDef = servicePolicies.getServiceDef(); - List<RangerZoneResourceMatcher> matchers = new ArrayList<>(); - - for (Map.Entry<String, ServicePolicies.SecurityZoneInfo> securityZone : securityZones.entrySet()) { - String zoneName = securityZone.getKey(); - ServicePolicies.SecurityZoneInfo zoneDetails = securityZone.getValue(); - - if (LOG.isDebugEnabled()) { - LOG.debug("Building matchers for zone:[" + zoneName +"]"); - } - - for (Map<String, List<String>> resource : zoneDetails.getResources()) { - if (LOG.isDebugEnabled()) { - LOG.debug("Building matcher for resource:[" + resource + "] in zone:[" + zoneName +"]"); - } - - Map<String, RangerPolicy.RangerPolicyResource> policyResources = new HashMap<>(); - - for (Map.Entry<String, List<String>> entry : resource.entrySet()) { - String resourceDefName = entry.getKey(); - List<String> resourceValues = entry.getValue(); - RangerPolicy.RangerPolicyResource policyResource = new RangerPolicy.RangerPolicyResource(); - policyResource.setIsExcludes(false); - policyResource.setIsRecursive(EmbeddedServiceDefsUtil.isRecursiveEnabled(serviceDef, resourceDefName)); - policyResource.setValues(resourceValues); - policyResources.put(resourceDefName, policyResource); - } - - matchers.add(new RangerZoneResourceMatcher(zoneName, policyResources, serviceDef)); - - if (LOG.isDebugEnabled()) { - LOG.debug("Built matcher for resource:[" + resource +"] in zone:[" + zoneName + "]"); - } - } - - if (LOG.isDebugEnabled()) { - LOG.debug("Built all matchers for zone:[" + zoneName +"]"); - } - - if (zoneDetails.getContainsAssociatedTagService()) { - zoneTagServiceMap.put(zoneName, zoneName); - } - } - - if (LOG.isDebugEnabled()) { - LOG.debug("Built matchers for all Zones"); - } - - RangerPolicyEngineOptions options = pluginContext.getConfig().getPolicyEngineOptions(); - - for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) { - resourceZoneTrie.put(resourceDef.getName(), new RangerResourceTrie<>(resourceDef, matchers, options.optimizeTrieForSpace, options.optimizeTrieForRetrieval, pluginContext)); - } - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== PolicyEngine.buildZoneTrie()"); - } - } - private RangerPolicyRepository shareWith(RangerPolicyRepository other) { if (other != null) { other.setShared(); @@ -839,8 +704,6 @@ public class PolicyEngine { } if (MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) { - buildZoneTrie(servicePolicies); - Map<String, List<RangerPolicyDelta>> zoneDeltasMap = new HashMap<>(); for (Map.Entry<String, ServicePolicies.SecurityZoneInfo> zone : servicePolicies.getSecurityZones().entrySet()) { diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerSecurityZoneMatcher.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerSecurityZoneMatcher.java new file mode 100644 index 000000000..a36eda0b8 --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerSecurityZoneMatcher.java @@ -0,0 +1,209 @@ +/* + * 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.policyengine; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; +import org.apache.ranger.plugin.model.validation.RangerZoneResourceMatcher; +import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; +import org.apache.ranger.plugin.util.RangerResourceEvaluatorsRetriever; +import org.apache.ranger.plugin.util.ServicePolicies.SecurityZoneInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +public class RangerSecurityZoneMatcher { + private static final Logger LOG = LoggerFactory.getLogger(RangerSecurityZoneMatcher.class); + + private final Map<String, RangerResourceTrie<RangerZoneResourceMatcher>> resourceZoneTrie; + private final Set<String> zonesWithTagService; + private final RangerServiceDef serviceDef; + + public RangerSecurityZoneMatcher(Map<String, SecurityZoneInfo> securityZones, RangerServiceDef serviceDef, RangerPluginContext pluginContext) { + this.resourceZoneTrie = new HashMap<>(); + this.zonesWithTagService = new HashSet<>(); + this.serviceDef = serviceDef; + + buildZoneTrie(securityZones, serviceDef, pluginContext); + } + + public boolean hasTagService(String zoneName) { + return zonesWithTagService.contains(zoneName); + } + + public Set<String> getZonesForResourceAndChildren(Map<String, ?> resource) { + return getZonesForResourceAndChildren(resource, convertToAccessResource(resource)); + } + + public Set<String> getZonesForResourceAndChildren(RangerAccessResource resource) { + return getZonesForResourceAndChildren(resource.getAsMap(), resource); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj == null || !getClass().equals(obj.getClass())) { + return false; + } + + RangerSecurityZoneMatcher other = (RangerSecurityZoneMatcher) obj; + + return Objects.equals(resourceZoneTrie, other.resourceZoneTrie) && + Objects.equals(zonesWithTagService, other.zonesWithTagService); + } + + @Override + public int hashCode() { + return Objects.hash(resourceZoneTrie, zonesWithTagService); + } + + private Set<String> getZonesForResourceAndChildren(Map<String, ?> resource, RangerAccessResource accessResource) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerSecurityZoneMatcher.getZonesForResourceAndChildren({})", accessResource); + } + + Set<String> ret = null; + + if (MapUtils.isNotEmpty(this.resourceZoneTrie)) { + Collection<RangerZoneResourceMatcher> matchers = RangerResourceEvaluatorsRetriever.getEvaluators(resourceZoneTrie, resource); + + if (CollectionUtils.isNotEmpty(matchers)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Resource:[{}], matchers:[{}]", resource, matchers); + } + + ret = new HashSet<>(matchers.size()); + + // These are potential matches. Try to really match them + for (RangerZoneResourceMatcher matcher : matchers) { + if (LOG.isDebugEnabled()) { + LOG.debug("Trying to match resource:[{}] using matcher:[{}]", accessResource, matcher); + } + + if (matcher.getPolicyResourceMatcher().isMatch(accessResource, RangerPolicyResourceMatcher.MatchScope.ANY, null)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Matched resource:[{}] using matcher:[{}]", accessResource, matcher); + } + + // Actual match happened + ret.add(matcher.getSecurityZoneName()); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Did not match resource:[{}] using matcher:[{}]", accessResource, matcher); + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("zone-names matched resource:[{}]: {}", accessResource, ret); + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerSecurityZoneMatcher.getZonesForResourceAndChildren({}): ret={}", accessResource, ret); + } + + return ret; + } + + private void buildZoneTrie(Map<String, SecurityZoneInfo> securityZones, RangerServiceDef serviceDef, RangerPluginContext pluginContext) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerSecurityZoneMatcher.buildZoneTrie()"); + } + + Map<String, Boolean> resourceIsRecursive = new HashMap<>(); + + if (MapUtils.isNotEmpty(securityZones)) { + List<RangerZoneResourceMatcher> matchers = new ArrayList<>(); + + for (Map.Entry<String, SecurityZoneInfo> securityZone : securityZones.entrySet()) { + String zoneName = securityZone.getKey(); + SecurityZoneInfo zoneDetails = securityZone.getValue(); + + if (LOG.isDebugEnabled()) { + LOG.debug("Building matchers for zone:[{}]", zoneName); + } + + for (Map<String, List<String>> resource : zoneDetails.getResources()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Building matcher for resource:[{}] in zone:[{}]", resource, zoneName); + } + + Map<String, RangerPolicyResource> policyResources = new HashMap<>(); + + for (Map.Entry<String, List<String>> entry : resource.entrySet()) { + String resourceDefName = entry.getKey(); + List<String> resourceValues = entry.getValue(); + Boolean isRecursive = resourceIsRecursive.computeIfAbsent(resourceDefName, f -> EmbeddedServiceDefsUtil.isRecursiveEnabled(serviceDef, resourceDefName)); + + policyResources.put(resourceDefName, new RangerPolicyResource(resourceValues, false, isRecursive)); + } + + matchers.add(new RangerZoneResourceMatcher(zoneName, policyResources, serviceDef)); + + if (LOG.isDebugEnabled()) { + LOG.debug("Built matcher for resource:[{}] in zone:[{}]", resource, zoneName); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Built all matchers for zone:[{}]", zoneName); + } + + if (Boolean.TRUE.equals(zoneDetails.getContainsAssociatedTagService())) { + zonesWithTagService.add(zoneName); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Built matchers for all Zones"); + } + + RangerPolicyEngineOptions options = pluginContext.getConfig().getPolicyEngineOptions(); + + for (RangerResourceDef resourceDef : serviceDef.getResources()) { + resourceZoneTrie.put(resourceDef.getName(), new RangerResourceTrie<>(resourceDef, matchers, options.optimizeTrieForSpace, options.optimizeTrieForRetrieval, pluginContext)); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerSecurityZoneMatcher.buildZoneTrie()"); + } + } + + private RangerAccessResource convertToAccessResource(Map<String, ?> resource) { + RangerAccessResourceImpl ret = new RangerAccessResourceImpl(); + + ret.setServiceDef(serviceDef); + + for (Map.Entry<String, ?> entry : resource.entrySet()) { + ret.setValue(entry.getKey(), entry.getValue()); + } + + return ret; + } +} diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerAuthContext.java b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerAuthContext.java index 56e4d782d..f3da19fe5 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerAuthContext.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerAuthContext.java @@ -24,6 +24,7 @@ import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.ranger.plugin.contextenricher.RangerContextEnricher; import org.apache.ranger.plugin.policyengine.RangerPolicyEngine; +import org.apache.ranger.plugin.policyengine.RangerSecurityZoneMatcher; import org.apache.ranger.plugin.util.RangerRoles; import org.apache.ranger.plugin.util.RangerRolesUtil; import org.apache.ranger.plugin.util.RangerUserStore; @@ -36,15 +37,13 @@ import java.util.concurrent.ConcurrentHashMap; public class RangerAuthContext { private final Map<RangerContextEnricher, Object> requestContextEnrichers; + private final RangerSecurityZoneMatcher zoneMatcher; private RangerRolesUtil rolesUtil; private RangerUserStoreUtil userStoreUtil; - public RangerAuthContext(Map<RangerContextEnricher, Object> requestContextEnrichers, RangerRoles roles) { - this(requestContextEnrichers, roles, null); - } - - public RangerAuthContext(Map<RangerContextEnricher, Object> requestContextEnrichers, RangerRoles roles, RangerUserStore userStore) { + public RangerAuthContext(Map<RangerContextEnricher, Object> requestContextEnrichers, RangerSecurityZoneMatcher zoneMatcher, RangerRoles roles, RangerUserStore userStore) { this.requestContextEnrichers = requestContextEnrichers != null ? requestContextEnrichers : new ConcurrentHashMap<>(); + this.zoneMatcher = zoneMatcher;; setRoles(roles); setUserStore(userStore); @@ -54,6 +53,10 @@ public class RangerAuthContext { return requestContextEnrichers; } + public RangerSecurityZoneMatcher getZoneMatcher() { + return zoneMatcher; + } + public void addOrReplaceRequestContextEnricher(RangerContextEnricher enricher, Object database) { // concurrentHashMap does not allow null to be inserted into it, so insert a dummy which is checked // when enrich() is called 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 ba2e6439e..fc24ca752 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,7 +44,6 @@ 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; @@ -986,17 +985,7 @@ public class TestPolicyEngine { } if (ret) { - ret = Objects.equals(me.getResourceZoneTrie().keySet(), other.getResourceZoneTrie().keySet()); - - if (ret) { - for (Map.Entry<String, RangerResourceTrie<RangerZoneResourceMatcher>> entry : me.getResourceZoneTrie().entrySet()) { - ret = compareSubtree(entry.getValue(), other.getResourceZoneTrie().get(entry.getKey())); - - if (!ret) { - break; - } - } - } + ret = Objects.equals(me.getZoneMatcher(), other.getZoneMatcher()); } if (ret) { diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestRangerSecurityZoneMatcher.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestRangerSecurityZoneMatcher.java new file mode 100644 index 000000000..254184403 --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestRangerSecurityZoneMatcher.java @@ -0,0 +1,159 @@ +/* + * 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.policyengine; + + +import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; +import org.apache.ranger.plugin.util.ServicePolicies.SecurityZoneInfo; +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.*; + +public class TestRangerSecurityZoneMatcher { + final RangerPluginContext pluginContext = new RangerPluginContext(new RangerPluginConfig("hive", null, "hive", "cl1", "on-prem", null)); + final Map<String, SecurityZoneInfo> securityZones = createSecurityZones(); + final RangerServiceDef serviceDef = createServiceDef(); + + @Test + public void testZoneMatcher() { + RangerSecurityZoneMatcher zoneMatcher = new RangerSecurityZoneMatcher(securityZones, serviceDef, pluginContext); + + RangerAccessResource res; + Set<String> zones; + + res = createResource("database", "db1", "table", "tbl1"); + zones = zoneMatcher.getZonesForResourceAndChildren(res); + assertEquals(createSet("z1"), zones); + + res = createResource("database", "db2", "table", "tbl1"); + zones = zoneMatcher.getZonesForResourceAndChildren(res); + assertEquals(createSet("z2"), zones); + + res = createResource("database", "db3", "table", "test_1"); + zones = zoneMatcher.getZonesForResourceAndChildren(res); + assertEquals(createSet("z3"), zones); + + res = createResource("database", "db3", "table", "test_2"); + zones = zoneMatcher.getZonesForResourceAndChildren(res); + assertEquals(createSet("z3"), zones); + + res = createResource("database", "db3", "table", "orders"); + zones = zoneMatcher.getZonesForResourceAndChildren(res); + assertNull(zones); + + res = createResource("database", "db3", "table", "user_1"); + zones = zoneMatcher.getZonesForResourceAndChildren(res); + assertEquals(createSet("z4"), zones); + + res = createResource("database", "db3", "table", "user_2"); + zones = zoneMatcher.getZonesForResourceAndChildren(res); + assertEquals(createSet("z4"), zones); + + res = createResource("database", "db3"); + zones = zoneMatcher.getZonesForResourceAndChildren(res); + assertEquals(createSet("z3", "z4"), zones); + } + + private Map<String, SecurityZoneInfo> createSecurityZones() { + HashMap<String, List<String>> db1 = new HashMap<String, List<String>>() {{ put("database", Arrays.asList("db1")); }}; + HashMap<String, List<String>> db2 = new HashMap<String, List<String>>() {{ put("database", Arrays.asList("db2")); }}; + HashMap<String, List<String>> db3Test = new HashMap<String, List<String>>() {{ put("database", Arrays.asList("db3")); put("table", Arrays.asList("test_*")); }}; + HashMap<String, List<String>> db4User = new HashMap<String, List<String>>() {{ put("database", Arrays.asList("db3")); put("table", Arrays.asList("user_*")); }}; + + SecurityZoneInfo z1 = new SecurityZoneInfo(); + SecurityZoneInfo z2 = new SecurityZoneInfo(); + SecurityZoneInfo z3 = new SecurityZoneInfo(); + SecurityZoneInfo z4 = new SecurityZoneInfo(); + + z1.setZoneName("z1"); + z1.setResources(Arrays.asList(db1)); + + z2.setZoneName("z2"); + z2.setResources(Arrays.asList(db2)); + + z3.setZoneName("z3"); + z3.setResources(Arrays.asList(db3Test)); + + z4.setZoneName("z4"); + z4.setResources(Arrays.asList(db4User)); + + Map<String, SecurityZoneInfo> ret = new HashMap<>(); + + ret.put(z1.getZoneName(), z1); + ret.put(z2.getZoneName(), z2); + ret.put(z3.getZoneName(), z3); + ret.put(z4.getZoneName(), z4); + + return ret; + } + + private RangerServiceDef createServiceDef() { + RangerServiceDef ret = new RangerServiceDef(); + + ret.setName("hive"); + ret.setResources(createResourceDefs()); + + return ret; + } + + private List<RangerResourceDef> createResourceDefs() { + List<RangerResourceDef> ret = new ArrayList<>(); + + ret.add(createResourceDef("database", null)); + ret.add(createResourceDef("table", "database")); + ret.add(createResourceDef("column", "table")); + + return ret; + } + + private RangerResourceDef createResourceDef(String name, String parent) { + RangerResourceDef ret = new RangerResourceDef(); + + ret.setName(name); + ret.setType("string"); + ret.setParent(parent); + + return ret; + } + + private RangerAccessResource createResource(String...args) { + RangerAccessResourceImpl ret = new RangerAccessResourceImpl(); + + for (int i = 1; i < args.length; i += 2) { + ret.setValue(args[i - 1], args[i]); + } + + return ret; + } + + private Set<String> createSet(String...args) { + Set<String> ret = new HashSet<>(); + + for (String arg : args) { + ret.add(arg); + } + + return ret; + } +}