/* * 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.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ranger.authorization.hadoop.config.RangerConfiguration; import org.apache.ranger.plugin.contextenricher.RangerContextEnricher; import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.policyevaluator.RangerCachedPolicyEvaluator; import org.apache.ranger.plugin.policyevaluator.RangerOptimizedPolicyEvaluator; import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator; import org.apache.ranger.plugin.store.AbstractServiceStore; import org.apache.ranger.plugin.util.RangerPerfTracer; import org.apache.ranger.plugin.util.RangerResourceTrie; import org.apache.ranger.plugin.util.ServiceDefUtil; import org.apache.ranger.plugin.util.ServicePolicies; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; class RangerPolicyRepository { private static final Log LOG = LogFactory.getLog(RangerPolicyRepository.class); private static final Log PERF_CONTEXTENRICHER_INIT_LOG = RangerPerfTracer.getPerfLogger("contextenricher.init"); enum AuditModeEnum { AUDIT_ALL, AUDIT_NONE, AUDIT_DEFAULT } static private final class AuditInfo { final boolean isAudited; final long auditPolicyId; AuditInfo() { this(false, -1); } AuditInfo(boolean isAudited, long auditPolicyId) { this.isAudited = isAudited; this.auditPolicyId = auditPolicyId; } long getAuditPolicyId() { return this.auditPolicyId; } boolean getIsAudited() { return isAudited; } } private final String serviceName; private final String appId; private final RangerServiceDef serviceDef; private final List<RangerPolicy> policies; private final long policyVersion; private List<RangerContextEnricher> contextEnrichers; private List<RangerPolicyEvaluator> policyEvaluators; private List<RangerPolicyEvaluator> dataMaskPolicyEvaluators; private List<RangerPolicyEvaluator> rowFilterPolicyEvaluators; private final AuditModeEnum auditModeEnum; private final Map<String, AuditInfo> accessAuditCache; private final String componentServiceName; private final RangerServiceDef componentServiceDef; private final Map<String, RangerResourceTrie> policyResourceTrie; private final Map<String, RangerResourceTrie> dataMaskResourceTrie; private final Map<String, RangerResourceTrie> rowFilterResourceTrie; RangerPolicyRepository(String appId, ServicePolicies servicePolicies, RangerPolicyEngineOptions options) { super(); this.componentServiceName = this.serviceName = servicePolicies.getServiceName(); this.componentServiceDef = this.serviceDef = ServiceDefUtil.normalize(servicePolicies.getServiceDef()); this.appId = appId; this.policies = Collections.unmodifiableList(servicePolicies.getPolicies()); this.policyVersion = servicePolicies.getPolicyVersion() != null ? servicePolicies.getPolicyVersion() : -1; if(LOG.isDebugEnabled()) { LOG.debug("RangerPolicyRepository : building resource-policy-repository for service " + serviceName); } String auditMode = servicePolicies.getAuditMode(); if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_ALL)) { auditModeEnum = AuditModeEnum.AUDIT_ALL; } else if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_NONE)) { auditModeEnum = AuditModeEnum.AUDIT_NONE; } else { auditModeEnum = AuditModeEnum.AUDIT_DEFAULT; } if (auditModeEnum == AuditModeEnum.AUDIT_DEFAULT) { String propertyName = "ranger.plugin." + serviceName + ".policyengine.auditcachesize"; if (options.cacheAuditResults) { final int RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE = 64 * 1024; int auditResultCacheSize = RangerConfiguration.getInstance().getInt(propertyName, RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE); accessAuditCache = Collections.synchronizedMap(new CacheMap<String, AuditInfo>(auditResultCacheSize)); } else { accessAuditCache = null; } } else { this.accessAuditCache = null; } if(LOG.isDebugEnabled()) { LOG.debug("RangerPolicyRepository : building policy-repository for service[" + serviceName + "] with auditMode[" + auditModeEnum + "]"); } init(options); if(options.disableTrieLookupPrefilter) { policyResourceTrie = null; dataMaskResourceTrie = null; rowFilterResourceTrie = null; } else { policyResourceTrie = createResourceTrieMap(policyEvaluators); dataMaskResourceTrie = createResourceTrieMap(dataMaskPolicyEvaluators); rowFilterResourceTrie = createResourceTrieMap(rowFilterPolicyEvaluators); } } RangerPolicyRepository(String appId, ServicePolicies.TagPolicies tagPolicies, RangerPolicyEngineOptions options, RangerServiceDef componentServiceDef, String componentServiceName) { super(); this.serviceName = tagPolicies.getServiceName(); this.componentServiceName = componentServiceName; this.serviceDef = normalizeAccessTypeDefs(ServiceDefUtil.normalize(tagPolicies.getServiceDef()), componentServiceDef.getName()); this.componentServiceDef = componentServiceDef; this.appId = appId; this.policies = Collections.unmodifiableList(normalizeAndPrunePolicies(tagPolicies.getPolicies(), componentServiceDef.getName())); this.policyVersion = tagPolicies.getPolicyVersion() != null ? tagPolicies.getPolicyVersion() : -1; String auditMode = tagPolicies.getAuditMode(); if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_ALL)) { auditModeEnum = AuditModeEnum.AUDIT_ALL; } else if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_NONE)) { auditModeEnum = AuditModeEnum.AUDIT_NONE; } else { auditModeEnum = AuditModeEnum.AUDIT_DEFAULT; } this.accessAuditCache = null; if(LOG.isDebugEnabled()) { LOG.debug("RangerPolicyRepository : building tag-policy-repository for tag service[" + serviceName + "] with auditMode[" + auditModeEnum +"]"); } init(options); if(options.disableTrieLookupPrefilter) { policyResourceTrie = null; dataMaskResourceTrie = null; rowFilterResourceTrie = null; } else { policyResourceTrie = createResourceTrieMap(policyEvaluators); dataMaskResourceTrie = createResourceTrieMap(dataMaskPolicyEvaluators); rowFilterResourceTrie = createResourceTrieMap(rowFilterPolicyEvaluators); } } public String getServiceName() { return serviceName; } public RangerServiceDef getServiceDef() { return serviceDef; } public List<RangerPolicy> getPolicies() { return policies; } public long getPolicyVersion() { return policyVersion; } public List<RangerContextEnricher> getContextEnrichers() { return contextEnrichers; } List<RangerPolicyEvaluator> getPolicyEvaluators() { return policyEvaluators; } List<RangerPolicyEvaluator> getPolicyEvaluators(RangerAccessResource resource) { String resourceStr = resource == null ? null : resource.getAsString(); return policyResourceTrie == null || StringUtils.isEmpty(resourceStr) ? getPolicyEvaluators() : getPolicyEvaluators(policyResourceTrie, resource); } List<RangerPolicyEvaluator> getDataMaskPolicyEvaluators() { return dataMaskPolicyEvaluators; } List<RangerPolicyEvaluator> getDataMaskPolicyEvaluators(RangerAccessResource resource) { String resourceStr = resource == null ? null : resource.getAsString(); return dataMaskResourceTrie == null || StringUtils.isEmpty(resourceStr) ? getDataMaskPolicyEvaluators() : getPolicyEvaluators(dataMaskResourceTrie, resource); } List<RangerPolicyEvaluator> getRowFilterPolicyEvaluators() { return rowFilterPolicyEvaluators; } List<RangerPolicyEvaluator> getRowFilterPolicyEvaluators(RangerAccessResource resource) { String resourceStr = resource == null ? null : resource.getAsString(); return rowFilterResourceTrie == null || StringUtils.isEmpty(resourceStr) ? getRowFilterPolicyEvaluators() : getPolicyEvaluators(rowFilterResourceTrie, resource); } AuditModeEnum getAuditModeEnum() { return auditModeEnum; } private List<RangerPolicyEvaluator> getPolicyEvaluators(Map<String, RangerResourceTrie> resourceTrie, RangerAccessResource resource) { List<RangerPolicyEvaluator> ret = null; Set<String> resourceKeys = resource == null ? null : resource.getKeys(); if(CollectionUtils.isNotEmpty(resourceKeys)) { boolean isRetModifiable = false; for(String resourceName : resourceKeys) { RangerResourceTrie trie = resourceTrie.get(resourceName); if(trie == null) { // if no trie exists for this resource level, ignore and continue to next level continue; } List<RangerPolicyEvaluator> resourceEvaluators = trie.getEvaluatorsForResource(resource.getValue(resourceName)); if(CollectionUtils.isEmpty(resourceEvaluators)) { // no policies for this resource, bail out ret = null; } else if(ret == null) { // initialize ret with policies found for this resource ret = resourceEvaluators; } else { // remove policies from ret that are not in resourceEvaluators if(isRetModifiable) { ret.retainAll(resourceEvaluators); } else { final List<RangerPolicyEvaluator> shorterList; final List<RangerPolicyEvaluator> longerList; if (ret.size() < resourceEvaluators.size()) { shorterList = ret; longerList = resourceEvaluators; } else { shorterList = resourceEvaluators; longerList = ret; } ret = new ArrayList<>(shorterList); ret.retainAll(longerList); isRetModifiable = true; } } if(CollectionUtils.isEmpty(ret)) { // if no policy exists, bail out and return empty list ret = null; break; } } } if(ret == null) { ret = Collections.emptyList(); } if(LOG.isDebugEnabled()) { LOG.debug("<== RangerPolicyRepository.getPolicyEvaluators(" + resource.getAsString() + "): evaluatorCount=" + ret.size()); } return ret; } private RangerServiceDef normalizeAccessTypeDefs(RangerServiceDef serviceDef, final String componentType) { if (serviceDef != null && StringUtils.isNotBlank(componentType)) { List<RangerServiceDef.RangerAccessTypeDef> accessTypeDefs = serviceDef.getAccessTypes(); if (CollectionUtils.isNotEmpty(accessTypeDefs)) { String prefix = componentType + AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR; List<RangerServiceDef.RangerAccessTypeDef> unneededAccessTypeDefs = null; for (RangerServiceDef.RangerAccessTypeDef accessTypeDef : accessTypeDefs) { String accessType = accessTypeDef.getName(); if (StringUtils.startsWith(accessType, prefix)) { String newAccessType = StringUtils.removeStart(accessType, prefix); accessTypeDef.setName(newAccessType); Collection<String> impliedGrants = accessTypeDef.getImpliedGrants(); if (CollectionUtils.isNotEmpty(impliedGrants)) { Collection<String> newImpliedGrants = null; for (String impliedGrant : impliedGrants) { if (StringUtils.startsWith(impliedGrant, prefix)) { String newImpliedGrant = StringUtils.removeStart(impliedGrant, prefix); if (newImpliedGrants == null) { newImpliedGrants = new ArrayList<>(); } newImpliedGrants.add(newImpliedGrant); } } accessTypeDef.setImpliedGrants(newImpliedGrants); } } else if (StringUtils.contains(accessType, AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR)) { if(unneededAccessTypeDefs == null) { unneededAccessTypeDefs = new ArrayList<>(); } unneededAccessTypeDefs.add(accessTypeDef); } } if(unneededAccessTypeDefs != null) { accessTypeDefs.removeAll(unneededAccessTypeDefs); } } } return serviceDef; } private List<RangerPolicy> normalizeAndPrunePolicies(List<RangerPolicy> rangerPolicies, final String componentType) { if (CollectionUtils.isNotEmpty(rangerPolicies) && StringUtils.isNotBlank(componentType)) { List<RangerPolicy> policiesToPrune = null; for (RangerPolicy policy : rangerPolicies) { normalizeAndPrunePolicyItems(policy.getPolicyItems(), componentType); normalizeAndPrunePolicyItems(policy.getDenyPolicyItems(), componentType); normalizeAndPrunePolicyItems(policy.getAllowExceptions(), componentType); normalizeAndPrunePolicyItems(policy.getDenyExceptions(), componentType); normalizeAndPrunePolicyItems(policy.getDataMaskPolicyItems(), componentType); normalizeAndPrunePolicyItems(policy.getRowFilterPolicyItems(), componentType); if (!policy.getIsAuditEnabled() && CollectionUtils.isEmpty(policy.getPolicyItems()) && CollectionUtils.isEmpty(policy.getDenyPolicyItems()) && CollectionUtils.isEmpty(policy.getAllowExceptions()) && CollectionUtils.isEmpty(policy.getDenyExceptions()) && CollectionUtils.isEmpty(policy.getDataMaskPolicyItems()) && CollectionUtils.isEmpty(policy.getRowFilterPolicyItems())) { if(policiesToPrune == null) { policiesToPrune = new ArrayList<>(); } policiesToPrune.add(policy); } } if(policiesToPrune != null) { rangerPolicies.removeAll(policiesToPrune); } } return rangerPolicies; } private List<? extends RangerPolicy.RangerPolicyItem> normalizeAndPrunePolicyItems(List<? extends RangerPolicy.RangerPolicyItem> policyItems, final String componentType) { if(CollectionUtils.isNotEmpty(policyItems)) { final String prefix = componentType + AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR; List<RangerPolicy.RangerPolicyItem> itemsToPrune = null; for (RangerPolicy.RangerPolicyItem policyItem : policyItems) { List<RangerPolicy.RangerPolicyItemAccess> policyItemAccesses = policyItem.getAccesses(); if (CollectionUtils.isNotEmpty(policyItemAccesses)) { List<RangerPolicy.RangerPolicyItemAccess> accessesToPrune = null; for (RangerPolicy.RangerPolicyItemAccess access : policyItemAccesses) { String accessType = access.getType(); if (StringUtils.startsWith(accessType, prefix)) { String newAccessType = StringUtils.removeStart(accessType, prefix); access.setType(newAccessType); } else if (accessType.contains(AbstractServiceStore.COMPONENT_ACCESSTYPE_SEPARATOR)) { if(accessesToPrune == null) { accessesToPrune = new ArrayList<>(); } accessesToPrune.add(access); } } if(accessesToPrune != null) { policyItemAccesses.removeAll(accessesToPrune); } if (policyItemAccesses.isEmpty() && !policyItem.getDelegateAdmin()) { if(itemsToPrune == null) { itemsToPrune = new ArrayList<>(); } itemsToPrune.add(policyItem); } } } if(itemsToPrune != null) { policyItems.removeAll(itemsToPrune); } } return policyItems; } private static boolean isDelegateAdminPolicy(RangerPolicy policy) { boolean ret = hasDelegateAdminItems(policy.getPolicyItems()) || hasDelegateAdminItems(policy.getDenyPolicyItems()) || hasDelegateAdminItems(policy.getAllowExceptions()) || hasDelegateAdminItems(policy.getDenyExceptions()); return ret; } private static boolean hasDelegateAdminItems(List<RangerPolicy.RangerPolicyItem> items) { boolean ret = false; if (CollectionUtils.isNotEmpty(items)) { for (RangerPolicy.RangerPolicyItem item : items) { if(item.getDelegateAdmin()) { ret = true; break; } } } return ret; } private static boolean skipBuildingPolicyEvaluator(RangerPolicy policy, RangerPolicyEngineOptions options) { boolean ret = false; if (!policy.getIsEnabled()) { ret = true; } else if (options.evaluateDelegateAdminOnly && !isDelegateAdminPolicy(policy)) { ret = true; } return ret; } private void init(RangerPolicyEngineOptions options) { List<RangerPolicyEvaluator> policyEvaluators = new ArrayList<>(); List<RangerPolicyEvaluator> dataMaskPolicyEvaluators = new ArrayList<>(); List<RangerPolicyEvaluator> rowFilterPolicyEvaluators = new ArrayList<>(); for (RangerPolicy policy : policies) { if (skipBuildingPolicyEvaluator(policy, options)) { continue; } RangerPolicyEvaluator evaluator = buildPolicyEvaluator(policy, serviceDef, options); if (evaluator != null) { if(policy.getPolicyType() == null || policy.getPolicyType() == RangerPolicy.POLICY_TYPE_ACCESS) { policyEvaluators.add(evaluator); } else if(policy.getPolicyType() == RangerPolicy.POLICY_TYPE_DATAMASK) { dataMaskPolicyEvaluators.add(evaluator); } else if(policy.getPolicyType() == RangerPolicy.POLICY_TYPE_ROWFILTER) { rowFilterPolicyEvaluators.add(evaluator); } else { LOG.warn("RangerPolicyEngine: ignoring policy id=" + policy.getId() + " - invalid policyType '" + policy.getPolicyType() + "'"); } } } Collections.sort(policyEvaluators); this.policyEvaluators = Collections.unmodifiableList(policyEvaluators); Collections.sort(dataMaskPolicyEvaluators); this.dataMaskPolicyEvaluators = Collections.unmodifiableList(dataMaskPolicyEvaluators); Collections.sort(rowFilterPolicyEvaluators); this.rowFilterPolicyEvaluators = Collections.unmodifiableList(rowFilterPolicyEvaluators); List<RangerContextEnricher> contextEnrichers = new ArrayList<RangerContextEnricher>(); if (CollectionUtils.isNotEmpty(this.policyEvaluators)) { if (!options.disableContextEnrichers && !CollectionUtils.isEmpty(serviceDef.getContextEnrichers())) { for (RangerServiceDef.RangerContextEnricherDef enricherDef : serviceDef.getContextEnrichers()) { if (enricherDef == null) { continue; } RangerContextEnricher contextEnricher = buildContextEnricher(enricherDef); if (contextEnricher != null) { contextEnrichers.add(contextEnricher); } } } } this.contextEnrichers = Collections.unmodifiableList(contextEnrichers); if(LOG.isDebugEnabled()) { LOG.debug("policy evaluation order: " + this.policyEvaluators.size() + " policies"); int order = 0; for(RangerPolicyEvaluator policyEvaluator : this.policyEvaluators) { RangerPolicy policy = policyEvaluator.getPolicy(); LOG.debug("policy evaluation order: #" + (++order) + " - policy id=" + policy.getId() + "; name=" + policy.getName() + "; evalOrder=" + policyEvaluator.getEvalOrder()); } LOG.debug("dataMask policy evaluation order: " + this.dataMaskPolicyEvaluators.size() + " policies"); order = 0; for(RangerPolicyEvaluator policyEvaluator : this.dataMaskPolicyEvaluators) { RangerPolicy policy = policyEvaluator.getPolicy(); LOG.debug("dataMask policy evaluation order: #" + (++order) + " - policy id=" + policy.getId() + "; name=" + policy.getName() + "; evalOrder=" + policyEvaluator.getEvalOrder()); } LOG.debug("rowFilter policy evaluation order: " + this.dataMaskPolicyEvaluators.size() + " policies"); order = 0; for(RangerPolicyEvaluator policyEvaluator : this.rowFilterPolicyEvaluators) { RangerPolicy policy = policyEvaluator.getPolicy(); LOG.debug("rowFilter policy evaluation order: #" + (++order) + " - policy id=" + policy.getId() + "; name=" + policy.getName() + "; evalOrder=" + policyEvaluator.getEvalOrder()); } } } private RangerContextEnricher buildContextEnricher(RangerServiceDef.RangerContextEnricherDef enricherDef) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerPolicyRepository.buildContextEnricher(" + enricherDef + ")"); } RangerContextEnricher ret = null; RangerPerfTracer perf = null; if(RangerPerfTracer.isPerfTraceEnabled(PERF_CONTEXTENRICHER_INIT_LOG)) { perf = RangerPerfTracer.getPerfTracer(PERF_CONTEXTENRICHER_INIT_LOG, "RangerContextEnricher.init(appId=" + appId + ",name=" + enricherDef.getName() + ")"); } String name = enricherDef != null ? enricherDef.getName() : null; String clsName = enricherDef != null ? enricherDef.getEnricher() : null; if(! StringUtils.isEmpty(clsName)) { try { @SuppressWarnings("unchecked") Class<RangerContextEnricher> enricherClass = (Class<RangerContextEnricher>)Class.forName(clsName); ret = enricherClass.newInstance(); } catch(Exception excp) { LOG.error("failed to instantiate context enricher '" + clsName + "' for '" + name + "'", excp); } } if(ret != null) { ret.setEnricherDef(enricherDef); ret.setServiceName(componentServiceName); ret.setServiceDef(componentServiceDef); ret.setAppId(appId); ret.init(); } RangerPerfTracer.log(perf); if(LOG.isDebugEnabled()) { LOG.debug("<== RangerPolicyRepository.buildContextEnricher(" + enricherDef + "): " + ret); } return ret; } private RangerPolicyEvaluator buildPolicyEvaluator(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerPolicyRepository.buildPolicyEvaluator(" + policy + "," + serviceDef + ", " + options + ")"); } scrubPolicy(policy); RangerPolicyEvaluator ret; if(StringUtils.equalsIgnoreCase(options.evaluatorType, RangerPolicyEvaluator.EVALUATOR_TYPE_CACHED)) { ret = new RangerCachedPolicyEvaluator(); } else { ret = new RangerOptimizedPolicyEvaluator(); } ret.init(policy, serviceDef, options); if(LOG.isDebugEnabled()) { LOG.debug("<== RangerPolicyRepository.buildPolicyEvaluator(" + policy + "," + serviceDef + "): " + ret); } return ret; } boolean setAuditEnabledFromCache(RangerAccessRequest request, RangerAccessResult result) { if (LOG.isDebugEnabled()) { LOG.debug("==> RangerPolicyRepository.setAuditEnabledFromCache()"); } final AuditInfo auditInfo = accessAuditCache != null ? accessAuditCache.get(request.getResource().getAsString()) : null; if (auditInfo != null) { result.setIsAudited(auditInfo.getIsAudited()); result.setAuditPolicyId(auditInfo.getAuditPolicyId()); } if (LOG.isDebugEnabled()) { LOG.debug("<== RangerPolicyRepository.setAuditEnabledFromCache():" + (auditInfo != null)); } return auditInfo != null; } void storeAuditEnabledInCache(RangerAccessRequest request, RangerAccessResult result) { if (LOG.isDebugEnabled()) { LOG.debug("==> RangerPolicyRepository.storeAuditEnabledInCache()"); } if (accessAuditCache != null && result.getIsAuditedDetermined()) { accessAuditCache.put(request.getResource().getAsString(), new AuditInfo(result.getIsAudited(), result.getAuditPolicyId())); } if (LOG.isDebugEnabled()) { LOG.debug("<== RangerPolicyRepository.storeAuditEnabledInCache()"); } } private boolean scrubPolicy(RangerPolicy policy) { if (LOG.isDebugEnabled()) { LOG.debug("==> RangerPolicyRepository.scrubPolicy(" + policy + ")"); } boolean altered = false; Long policyId = policy.getId(); Map<String, RangerPolicy.RangerPolicyResource> resourceMap = policy.getResources(); for (Map.Entry<String, RangerPolicy.RangerPolicyResource> entry : resourceMap.entrySet()) { String resourceName = entry.getKey(); RangerPolicy.RangerPolicyResource resource = entry.getValue(); Iterator<String> iterator = resource.getValues().iterator(); while (iterator.hasNext()) { String value = iterator.next(); if (value == null) { LOG.warn("RangerPolicyRepository.scrubPolicyResource: found null resource value for " + resourceName + " in policy " + policyId + "! Removing..."); iterator.remove(); altered = true; } } } scrubPolicyItems(policyId, policy.getPolicyItems()); scrubPolicyItems(policyId, policy.getAllowExceptions()); scrubPolicyItems(policyId, policy.getDenyPolicyItems()); scrubPolicyItems(policyId, policy.getDenyExceptions()); scrubPolicyItems(policyId, policy.getRowFilterPolicyItems()); scrubPolicyItems(policyId, policy.getDataMaskPolicyItems()); if (LOG.isDebugEnabled()) { LOG.debug("<== RangerPolicyRepository.scrubPolicy(" + policy + "): " + altered); } return altered; } private void scrubPolicyItems(final Long policyId, final List<? extends RangerPolicy.RangerPolicyItem> policyItems) { if (LOG.isDebugEnabled()) { LOG.debug("==> RangerPolicyRepository.scrubPolicyItems(" + policyId + "): "); } for (RangerPolicy.RangerPolicyItem policyItem : policyItems) { removeNulls(policyItem.getUsers(), policyId, policyItem); removeNulls(policyItem.getGroups(), policyId, policyItem); } if (LOG.isDebugEnabled()) { LOG.debug("<== RangerPolicyRepository.scrubPolicyItems(" + policyId + "): "); } } private void removeNulls(Collection<String> strings, final Long policyId, final RangerPolicy.RangerPolicyItem policyItem) { Iterator<String> iterator = strings.iterator(); while (iterator.hasNext()) { String value = iterator.next(); if (value == null) { LOG.warn("RangerPolicyRepository.removeNulls: found null user/group in policyItem '" + policyItem + "' in policy " + policyId + "! Removing..."); iterator.remove(); } } } void reorderPolicyEvaluators() { if (LOG.isDebugEnabled()) { LOG.debug("==> reorderEvaluators()"); } if(policyResourceTrie != null) { reorderPolicyEvaluators(policyResourceTrie); } else { policyEvaluators = getReorderedPolicyEvaluators(policyEvaluators); } if(dataMaskResourceTrie != null) { reorderPolicyEvaluators(dataMaskResourceTrie); } else { dataMaskPolicyEvaluators = getReorderedPolicyEvaluators(dataMaskPolicyEvaluators); } if(rowFilterResourceTrie != null) { reorderPolicyEvaluators(rowFilterResourceTrie); } else { rowFilterPolicyEvaluators = getReorderedPolicyEvaluators(rowFilterPolicyEvaluators); } if (LOG.isDebugEnabled()) { LOG.debug("<== reorderEvaluators()"); } } private void reorderPolicyEvaluators(Map<String, RangerResourceTrie> trieMap) { if(trieMap != null) { for(Map.Entry<String, RangerResourceTrie> entry : trieMap.entrySet()) { RangerResourceTrie trie = entry.getValue(); if(trie != null) { trie.reorderEvaluators(); } } } } private List<RangerPolicyEvaluator> getReorderedPolicyEvaluators(List<RangerPolicyEvaluator> evaluators) { List<RangerPolicyEvaluator> ret = evaluators; if (CollectionUtils.isNotEmpty(evaluators)) { ret = new ArrayList<>(evaluators); Collections.sort(ret); ret = Collections.unmodifiableList(ret); } return ret; } private Map<String, RangerResourceTrie> createResourceTrieMap(List<RangerPolicyEvaluator> evaluators) { final Map<String, RangerResourceTrie> ret; if (CollectionUtils.isNotEmpty(evaluators) && serviceDef != null && CollectionUtils.isNotEmpty(serviceDef.getResources())) { ret = new HashMap<>(); for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) { ret.put(resourceDef.getName(), new RangerResourceTrie(resourceDef, evaluators)); } } else { ret = null; } return ret; } @Override public String toString( ) { StringBuilder sb = new StringBuilder(); toString(sb); return sb.toString(); } public StringBuilder toString(StringBuilder sb) { sb.append("RangerPolicyRepository={"); sb.append("serviceName={").append(serviceName).append("} "); sb.append("serviceDef={").append(serviceDef).append("} "); sb.append("appId={").append(appId).append("} "); sb.append("policyEvaluators={"); if (policyEvaluators != null) { for (RangerPolicyEvaluator policyEvaluator : policyEvaluators) { if (policyEvaluator != null) { sb.append(policyEvaluator).append(" "); } } } if (contextEnrichers != null) { for (RangerContextEnricher contextEnricher : contextEnrichers) { if (contextEnricher != null) { sb.append(contextEnricher).append(" "); } } } sb.append("} "); return sb; } }