| /* |
| * 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.biz; |
| |
| 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.plugin.contextenricher.RangerTagForEval; |
| import org.apache.ranger.plugin.model.RangerPolicy; |
| import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; |
| import org.apache.ranger.plugin.policyengine.PolicyEngine; |
| import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl; |
| import org.apache.ranger.plugin.policyengine.RangerAccessRequestProcessor; |
| import org.apache.ranger.plugin.policyengine.RangerAccessResource; |
| import org.apache.ranger.plugin.policyengine.RangerPluginContext; |
| import org.apache.ranger.plugin.policyengine.RangerPolicyEngine; |
| import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; |
| import org.apache.ranger.plugin.policyengine.RangerPolicyRepository; |
| import org.apache.ranger.plugin.policyengine.RangerTagResource; |
| import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator; |
| import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher; |
| import org.apache.ranger.plugin.service.RangerDefaultRequestProcessor; |
| import org.apache.ranger.plugin.util.RangerAccessRequestUtil; |
| import org.apache.ranger.plugin.util.RangerPerfTracer; |
| import org.apache.ranger.plugin.util.RangerRoles; |
| import org.apache.ranger.plugin.util.ServicePolicies; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| public class RangerPolicyAdminImpl implements RangerPolicyAdmin { |
| private static final Log LOG = LogFactory.getLog(RangerPolicyAdminImpl.class); |
| |
| private static final Log PERF_POLICYENGINE_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policyengine.request"); |
| |
| private final PolicyEngine policyEngine; |
| private final RangerAccessRequestProcessor requestProcessor; |
| |
| static public RangerPolicyAdmin getPolicyAdmin(final RangerPolicyAdminImpl other, final ServicePolicies servicePolicies) { |
| RangerPolicyAdmin ret = null; |
| |
| if (other != null && servicePolicies != null) { |
| PolicyEngine policyEngine = other.policyEngine.cloneWithDelta(servicePolicies); |
| if (policyEngine != null) { |
| ret = new RangerPolicyAdminImpl(policyEngine); |
| } |
| } |
| return ret; |
| } |
| |
| RangerPolicyAdminImpl(String appId, ServicePolicies servicePolicies, RangerPolicyEngineOptions options, RangerPluginContext rangerPluginContext, RangerRoles rangerRoles) { |
| policyEngine = new PolicyEngine(appId, servicePolicies, options, rangerPluginContext, rangerRoles); |
| this.requestProcessor = new RangerDefaultRequestProcessor(policyEngine); |
| } |
| |
| private RangerPolicyAdminImpl(final PolicyEngine policyEngine) { |
| this.policyEngine = policyEngine; |
| this.requestProcessor = new RangerDefaultRequestProcessor(policyEngine); |
| } |
| |
| @Override |
| public boolean isAccessAllowed(RangerAccessResource resource, String user, Set<String> userGroups, String accessType) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("==> RangerPolicyAdminImpl.isAccessAllowed(" + resource + ", " + user + ", " + userGroups + ", " + accessType + ")"); |
| } |
| boolean ret = false; |
| |
| RangerPerfTracer perf = null; |
| |
| if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_REQUEST_LOG)) { |
| perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REQUEST_LOG, "RangerPolicyAdminImpl.isAccessAllowed(user=" + user + ",accessType=" + accessType + "resource=" + resource.getAsString() + ")"); |
| } |
| |
| final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForMatchedZone(resource); |
| |
| if (matchedRepository != null) { |
| |
| Set<String> roles = getRolesFromUserAndGroups(user, userGroups); |
| |
| for (RangerPolicyEvaluator evaluator : matchedRepository.getLikelyMatchPolicyEvaluators(resource, RangerPolicy.POLICY_TYPE_ACCESS)) { |
| ret = evaluator.isAccessAllowed(resource, user, userGroups, roles, accessType); |
| |
| if (ret) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("Access granted by policy:[" + evaluator.getPolicy() + "]"); |
| } |
| break; |
| } |
| } |
| |
| } |
| |
| RangerPerfTracer.log(perf); |
| |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("<== RangerPolicyAdminImpl.isAccessAllowed(" + resource + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret); |
| } |
| |
| return ret; |
| } |
| |
| @Override |
| public boolean isAccessAllowed(RangerPolicy policy, String user, Set<String> userGroups, Set<String> roles, String accessType) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("==> RangerPolicyAdminImpl.isAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ")"); |
| } |
| |
| boolean ret = false; |
| |
| RangerPerfTracer perf = null; |
| |
| if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_REQUEST_LOG)) { |
| perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REQUEST_LOG, "RangerPolicyEngine.isAccessAllowed(user=" + user + "," + userGroups + ", roles=" + roles + ",accessType=" + accessType + ")"); |
| } |
| |
| final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForMatchedZone(policy); |
| |
| if (matchedRepository != null) { |
| |
| for (RangerPolicyEvaluator evaluator : matchedRepository.getPolicyEvaluators()) { |
| ret = evaluator.isAccessAllowed(policy, user, userGroups, roles, accessType); |
| |
| if (ret) { |
| break; |
| } |
| } |
| } |
| |
| RangerPerfTracer.log(perf); |
| |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("<== RangerPolicyAdminImpl.isAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + "): " + ret); |
| } |
| |
| return ret; |
| } |
| |
| @Override |
| public List<RangerPolicy> getExactMatchPolicies(RangerAccessResource resource, Map<String, Object> evalContext) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("==> RangerPolicyAdminImpl.getExactMatchPolicies(" + resource + ", " + evalContext + ")"); |
| } |
| |
| List<RangerPolicy> ret = null; |
| |
| RangerPolicyRepository policyRepository = policyEngine.getRepositoryForMatchedZone(resource); |
| |
| if (policyRepository != null) { |
| for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) { |
| if (evaluator.isCompleteMatch(resource, evalContext)) { |
| if (ret == null) { |
| ret = new ArrayList<>(); |
| } |
| |
| ret.add(evaluator.getPolicy()); |
| } |
| } |
| } |
| |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("<== RangerPolicyAdminImpl.getExactMatchPolicies(" + resource + ", " + evalContext + "): " + ret); |
| } |
| |
| return ret; |
| } |
| |
| @Override |
| public List<RangerPolicy> getExactMatchPolicies(RangerPolicy policy, Map<String, Object> evalContext) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("==> RangerPolicyAdminImpl.getExactMatchPolicies(" + policy + ", " + evalContext + ")"); |
| } |
| |
| List<RangerPolicy> ret = null; |
| |
| RangerPolicyRepository policyRepository = policyEngine.getRepositoryForMatchedZone(policy); |
| |
| if (policyRepository != null) { |
| Map<String, RangerPolicyResource> resources = policy.getResources(); |
| |
| for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) { |
| if (evaluator.isCompleteMatch(resources, evalContext)) { |
| if (ret == null) { |
| ret = new ArrayList<>(); |
| } |
| |
| ret.add(evaluator.getPolicy()); |
| } |
| } |
| } |
| |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("<== RangerPolicyAdminImpl.getExactMatchPolicies(" + policy + ", " + evalContext + "): " + ret); |
| } |
| |
| return ret; |
| } |
| |
| @Override |
| public List<RangerPolicy> getMatchingPolicies(RangerAccessResource resource) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("==> RangerPolicyAdminImpl.getMatchingPolicies(" + resource + ")"); |
| } |
| |
| List<RangerPolicy> ret = getMatchingPolicies(resource, RangerPolicyEngine.ANY_ACCESS); |
| |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("<== RangerPolicyAdminImpl.getMatchingPolicies(" + resource + ") : " + ret.size()); |
| } |
| |
| return ret; |
| } |
| |
| @Override |
| public long getPolicyVersion() { return policyEngine.getPolicyVersion(); } |
| |
| @Override |
| public long getRoleVersion() { return policyEngine.getRoleVersion(); } |
| |
| @Override |
| public String getServiceName() { return policyEngine.getServiceName(); } |
| |
| @Override |
| public void setRangerRoles(RangerRoles rangerRoles) { |
| policyEngine.setRangerRoles(rangerRoles); |
| } |
| |
| @Override |
| public Set<String> getRolesFromUserAndGroups(String user, Set<String> groups) { |
| return policyEngine.getPluginContext().getAuthContext().getRolesForUserAndGroups(user, groups); |
| } |
| |
| // This API is used only by test-code; checks only policies within default security-zone |
| @Override |
| public boolean isAccessAllowedByUnzonedPolicies(Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, String accessType) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("==> RangerPolicyAdminImpl.isAccessAllowedByUnzonedPolicies(" + resources + ", " + user + ", " + userGroups + ", " + accessType + ")"); |
| } |
| |
| boolean ret = false; |
| |
| RangerPerfTracer perf = null; |
| |
| if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_REQUEST_LOG)) { |
| perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REQUEST_LOG, "RangerPolicyEngine.isAccessAllowed(user=" + user + "," + userGroups + ",accessType=" + accessType + ")"); |
| } |
| |
| for (RangerPolicyEvaluator evaluator : policyEngine.getPolicyRepository().getPolicyEvaluators()) { |
| ret = evaluator.isAccessAllowed(resources, user, userGroups, accessType); |
| |
| if (ret) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("Access granted by policy:[" + evaluator.getPolicy() + "]"); |
| } |
| break; |
| } |
| } |
| |
| RangerPerfTracer.log(perf); |
| |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("<== RangerPolicyAdminImpl.isAccessAllowedByUnzonedPolicies(" + resources + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret); |
| } |
| |
| return ret; |
| } |
| |
| // This API is used only by test-code; checks only policies within default security-zone |
| @Override |
| public List<RangerPolicy> getAllowedUnzonedPolicies(String user, Set<String> userGroups, String accessType) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("==> RangerPolicyAdminImpl.getAllowedByUnzonedPolicies(" + user + ", " + userGroups + ", " + accessType + ")"); |
| } |
| |
| List<RangerPolicy> ret = new ArrayList<>(); |
| |
| |
| // TODO: run through evaluator in tagPolicyRepository as well |
| for (RangerPolicyEvaluator evaluator : policyEngine.getPolicyRepository().getPolicyEvaluators()) { |
| RangerPolicy policy = evaluator.getPolicy(); |
| |
| boolean isAccessAllowed = isAccessAllowedByUnzonedPolicies(policy.getResources(), user, userGroups, accessType); |
| |
| if (isAccessAllowed) { |
| ret.add(policy); |
| } |
| } |
| |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("<== RangerPolicyAdminImpl.getAllowedByUnzonedPolicies(" + user + ", " + userGroups + ", " + accessType + "): policyCount=" + ret.size()); |
| } |
| |
| return ret; |
| } |
| |
| void releaseResources() { |
| if (policyEngine != null) { |
| policyEngine.preCleanup(); |
| } |
| } |
| |
| private List<RangerPolicy> getMatchingPolicies(RangerAccessResource resource, String accessType) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("==> RangerPolicyAdminImpl.getMatchingPolicies(" + resource + ", " + accessType + ")"); |
| } |
| |
| List<RangerPolicy> ret = new ArrayList<>(); |
| |
| RangerAccessRequestImpl request = new RangerAccessRequestImpl(resource, accessType, null, null); |
| requestProcessor.preProcess(request); |
| |
| String zoneName = policyEngine.getMatchedZoneName(resource); |
| |
| final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForMatchedZone(resource); |
| |
| if (matchedRepository != null) { |
| |
| if (policyEngine.hasTagPolicies(policyEngine.getTagPolicyRepository())) { |
| |
| Set<RangerTagForEval> tags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext()); |
| |
| if (CollectionUtils.isNotEmpty(tags)) { |
| |
| final boolean useTagPoliciesFromDefaultZone = !policyEngine.isResourceZoneAssociatedWithTagService(zoneName); |
| |
| for (RangerTagForEval tag : tags) { |
| RangerAccessResource tagResource = new RangerTagResource(tag.getType(), policyEngine.getTagPolicyRepository().getServiceDef()); |
| List<RangerPolicyEvaluator> likelyEvaluators = policyEngine.getTagPolicyRepository().getLikelyMatchPolicyEvaluators(tagResource); |
| |
| for (RangerPolicyEvaluator evaluator : likelyEvaluators) { |
| String policyZoneName = evaluator.getPolicy().getZoneName(); |
| if (useTagPoliciesFromDefaultZone) { |
| if (StringUtils.isNotEmpty(policyZoneName)) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("Tag policy [zone:" + policyZoneName + "] does not belong to default zone. Not evaluating this policy:[" + evaluator.getPolicy() + "]"); |
| } |
| continue; |
| } |
| } else { |
| if (!StringUtils.equals(zoneName, policyZoneName)) { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("Tag policy [zone:" + policyZoneName + "] does not belong to the zone:[" + zoneName + "] of the accessed resource. Not evaluating this policy:[" + evaluator.getPolicy() + "]"); |
| } |
| continue; |
| } |
| } |
| RangerPolicyResourceMatcher matcher = evaluator.getPolicyResourceMatcher(); |
| if (matcher != null && |
| (request.isAccessTypeAny() ? matcher.isMatch(tagResource, RangerPolicyResourceMatcher.MatchScope.ANY, null) : matcher.isMatch(tagResource, null))) { |
| ret.add(evaluator.getPolicy()); |
| } |
| } |
| |
| } |
| } |
| } |
| |
| |
| if (policyEngine.hasResourcePolicies(matchedRepository)) { |
| List<RangerPolicyEvaluator> likelyEvaluators = matchedRepository.getLikelyMatchPolicyEvaluators(request.getResource()); |
| |
| for (RangerPolicyEvaluator evaluator : likelyEvaluators) { |
| RangerPolicyResourceMatcher matcher = evaluator.getPolicyResourceMatcher(); |
| if (matcher != null && |
| (request.isAccessTypeAny() ? matcher.isMatch(request.getResource(), RangerPolicyResourceMatcher.MatchScope.ANY, null) : matcher.isMatch(request.getResource(), null))) { |
| ret.add(evaluator.getPolicy()); |
| } |
| } |
| } |
| |
| } |
| |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("<== RangerPolicyAdminImpl.getMatchingPolicies(" + resource + ", " + accessType + ") : " + ret.size()); |
| } |
| return ret; |
| } |
| |
| } |
| |