/*
* 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.policyevaluator;
import java.util.ArrayList;
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;
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.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicy.RangerDataMaskPolicyItem;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.RangerPolicy.RangerRowFilterPolicyItem;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.apache.ranger.plugin.policyengine.RangerAccessResource;
import org.apache.ranger.plugin.policyengine.RangerAccessResult;
import org.apache.ranger.plugin.policyengine.RangerDataMaskResult;
import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
import org.apache.ranger.plugin.policyengine.RangerResourceAccessInfo;
import org.apache.ranger.plugin.policyengine.RangerRowFilterResult;
import org.apache.ranger.plugin.policyengine.RangerTagAccessRequest;
import org.apache.ranger.plugin.policyresourcematcher.RangerDefaultPolicyResourceMatcher;
import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
import org.apache.ranger.plugin.util.RangerPerfTracer;
import org.apache.ranger.plugin.util.ServiceDefUtil;
public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator {
private static final Log LOG = LogFactory.getLog(RangerDefaultPolicyEvaluator.class);
private static final Log PERF_POLICY_INIT_LOG = RangerPerfTracer.getPerfLogger("policy.init");
private static final Log PERF_POLICY_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policy.request");
private RangerPolicyResourceMatcher resourceMatcher;
private List<RangerPolicyItemEvaluator> allowEvaluators;
private List<RangerPolicyItemEvaluator> denyEvaluators;
private List<RangerPolicyItemEvaluator> allowExceptionEvaluators;
private List<RangerPolicyItemEvaluator> denyExceptionEvaluators;
private int customConditionsCount;
private List<RangerDataMaskPolicyItemEvaluator> dataMaskEvaluators;
private List<RangerRowFilterPolicyItemEvaluator> rowFilterEvaluators;
private String perfTag;
protected boolean needsDynamicEval() { return resourceMatcher != null && resourceMatcher.getNeedsDynamicEval(); }
@Override
public int getCustomConditionsCount() {
return customConditionsCount;
}
@Override
public RangerPolicyResourceMatcher getPolicyResourceMatcher() { return resourceMatcher; }
@Override
public RangerResourceMatcher getResourceMatcher(String resourceName) {
return resourceMatcher != null ? resourceMatcher.getResourceMatcher(resourceName) : null;
}
@Override
public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.init()");
}
StringBuilder perfTagBuffer = new StringBuilder();
if (policy != null) {
perfTagBuffer.append("policyId=").append(policy.getId()).append(", policyName=").append(policy.getName());
}
perfTag = perfTagBuffer.toString();
RangerPerfTracer perf = null;
if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_INIT_LOG)) {
perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_INIT_LOG, "RangerPolicyEvaluator.init(" + perfTag + ")");
}
super.init(policy, serviceDef, options);
preprocessPolicy(policy, serviceDef);
resourceMatcher = new RangerDefaultPolicyResourceMatcher();
resourceMatcher.setServiceDef(serviceDef);
resourceMatcher.setPolicy(policy);
resourceMatcher.init();
if(policy != null) {
allowEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW);
denyEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY);
allowExceptionEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS);
denyExceptionEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS);
dataMaskEvaluators = createDataMaskPolicyItemEvaluators(policy, serviceDef, options, policy.getDataMaskPolicyItems());
rowFilterEvaluators = createRowFilterPolicyItemEvaluators(policy, serviceDef, options, policy.getRowFilterPolicyItems());
} else {
allowEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList();
denyEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList();
allowExceptionEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList();
denyExceptionEvaluators = Collections.<RangerPolicyItemEvaluator>emptyList();
dataMaskEvaluators = Collections.<RangerDataMaskPolicyItemEvaluator>emptyList();
rowFilterEvaluators = Collections.<RangerRowFilterPolicyItemEvaluator>emptyList();
}
Collections.sort(allowEvaluators);
Collections.sort(denyEvaluators);
Collections.sort(allowExceptionEvaluators);
Collections.sort(denyExceptionEvaluators);
/* dataMask, rowFilter policyItems must be evaulated in the order given in the policy; hence no sort
Collections.sort(dataMaskEvaluators);
Collections.sort(rowFilterEvaluators);
*/
RangerPerfTracer.log(perf);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.init()");
}
}
@Override
public void evaluate(RangerAccessRequest request, RangerAccessResult result) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.evaluate(" + request + ", " + result + ")");
}
RangerPerfTracer perf = null;
if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_REQUEST_LOG)) {
perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.evaluate(requestHashCode=" + Integer.toHexString(System.identityHashCode(request)) + ","
+ perfTag + ")");
}
if (request != null && result != null) {
if (!result.getIsAccessDetermined() || !result.getIsAuditedDetermined()) {
RangerPolicyResourceMatcher.MatchType matchType = resourceMatcher != null ? resourceMatcher.getMatchType(request.getResource(), request.getContext()) : RangerPolicyResourceMatcher.MatchType.NONE;
final boolean isMatched;
if (request.isAccessTypeAny()) {
isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE;
} else if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) {
isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.DESCENDANT;
} else {
isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.ANCESTOR;
}
if (isMatched) {
if (RangerTagAccessRequest.class.isInstance(request)) {
matchType = ((RangerTagAccessRequest) request).getMatchType();
}
if (!result.getIsAuditedDetermined()) {
if (isAuditEnabled()) {
result.setIsAudited(true);
result.setAuditPolicyId(getPolicy().getId());
}
}
if (!result.getIsAccessDetermined()) {
if (hasMatchablePolicyItem(request)) {
evaluatePolicyItems(request, result, matchType != RangerPolicyResourceMatcher.MatchType.DESCENDANT);
}
}
}
}
}
RangerPerfTracer.log(perf);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.evaluate(" + request + ", " + result + ")");
}
}
@Override
public void evaluate(RangerAccessRequest request, RangerDataMaskResult result) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.evaluate(" + request + ", " + result + ")");
}
RangerPerfTracer perf = null;
if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_REQUEST_LOG)) {
perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.evaluate(requestHashCode=" + Integer.toHexString(System.identityHashCode(request)) + "," + perfTag + ")");
}
if (request != null && result != null && CollectionUtils.isNotEmpty(dataMaskEvaluators)) {
if (!result.getIsAccessDetermined() || !result.getIsAuditedDetermined()) {
RangerPolicyResourceMatcher.MatchType matchType = resourceMatcher != null ? resourceMatcher.getMatchType(request.getResource(), request.getContext()) : RangerPolicyResourceMatcher.MatchType.NONE;
final boolean isMatched;
if (request.isAccessTypeAny()) {
isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE;
} else if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) {
isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.DESCENDANT;
} else {
isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.ANCESTOR;
}
if (isMatched) {
if (!result.getIsAuditedDetermined()) {
if (isAuditEnabled()) {
result.setIsAudited(true);
result.setAuditPolicyId(getPolicy().getId());
}
}
if (!result.getIsAccessDetermined()) {
if (hasMatchablePolicyItem(request)) {
evaluatePolicyItems(request, result);
}
}
}
}
}
RangerPerfTracer.log(perf);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.evaluate(" + request + ", " + result + ")");
}
}
@Override
public void evaluate(RangerAccessRequest request, RangerRowFilterResult result) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.evaluate(" + request + ", " + result + ")");
}
RangerPerfTracer perf = null;
if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_REQUEST_LOG)) {
perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.evaluate(requestHashCode=" + Integer.toHexString(System.identityHashCode(request)) + "," + perfTag + ")");
}
if (request != null && result != null && CollectionUtils.isNotEmpty(rowFilterEvaluators)) {
if (!result.getIsAccessDetermined() || !result.getIsAuditedDetermined()) {
RangerPolicyResourceMatcher.MatchType matchType = resourceMatcher != null ? resourceMatcher.getMatchType(request.getResource(), request.getContext()) : RangerPolicyResourceMatcher.MatchType.NONE;
final boolean isMatched;
if (request.isAccessTypeAny()) {
isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE;
} else if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) {
isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.DESCENDANT;
} else {
isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.ANCESTOR;
}
if (isMatched) {
if (!result.getIsAuditedDetermined()) {
if (isAuditEnabled()) {
result.setIsAudited(true);
result.setAuditPolicyId(getPolicy().getId());
}
}
if (!result.getIsAccessDetermined()) {
if (hasMatchablePolicyItem(request)) {
evaluatePolicyItems(request, result);
}
}
}
}
}
RangerPerfTracer.log(perf);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.evaluate(" + request + ", " + result + ")");
}
}
@Override
public boolean isMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resource + ", " + evalContext + ")");
}
boolean ret = false;
RangerPerfTracer perf = null;
if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_REQUEST_LOG)) {
perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.isMatch(resource=" + resource.getAsString() + "," + evalContext + "," + perfTag + ")");
}
if(resourceMatcher != null) {
ret = resourceMatcher.isMatch(resource, evalContext);
}
RangerPerfTracer.log(perf);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resource + ", " + evalContext + "): " + ret);
}
return ret;
}
@Override
public boolean isCompleteMatch(RangerAccessResource resource, Map<String, Object> evalContext) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resource + ", " + evalContext + ")");
}
boolean ret = resourceMatcher != null && resourceMatcher.isCompleteMatch(resource, evalContext);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.isCompleteMatch(" + resource + "): " + ret);
}
return ret;
}
@Override
public boolean isCompleteMatch(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + ", " + evalContext + ")");
}
boolean ret = resourceMatcher != null && resourceMatcher.isCompleteMatch(resources, evalContext);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + ", " + evalContext + "): " + ret);
}
return ret;
}
@Override
public boolean isAccessAllowed(RangerAccessResource resource, String user, Set<String> userGroups, String accessType) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + resource + ", " + user + ", " + userGroups + ", " + accessType + ")");
}
Map<String, Object> evalContext = new HashMap<>();
RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
boolean ret = isAccessAllowed(user, userGroups, accessType) && isMatch(resource, evalContext);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + resource + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret);
}
return ret;
}
@Override
public boolean isAccessAllowed(Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, String accessType) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + ")");
}
Map<String, Object> evalContext = new HashMap<>();
RangerAccessRequestUtil.setCurrentUserInContext(evalContext, user);
boolean ret = isAccessAllowed(user, userGroups, accessType) && isMatch(resources, evalContext);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret);
}
return ret;
}
@Override
public void getResourceAccessInfo(RangerAccessRequest request, RangerResourceAccessInfo result) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.getResourceAccessInfo(" + request + ", " + result + ")");
}
RangerPolicyResourceMatcher.MatchType matchType = resourceMatcher != null ? resourceMatcher.getMatchType(request.getResource(), request.getContext()) : RangerPolicyResourceMatcher.MatchType.NONE;
final boolean isMatched;
if (request.isAccessTypeAny()) {
isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE;
} else if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) {
isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.DESCENDANT;
} else {
isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.ANCESTOR;
}
if (isMatched) {
if (CollectionUtils.isNotEmpty(allowEvaluators)) {
Set<String> users = new HashSet<>();
Set<String> groups = new HashSet<>();
getResourceAccessInfo(request, allowEvaluators, users, groups);
if (CollectionUtils.isNotEmpty(allowExceptionEvaluators)) {
Set<String> exceptionUsers = new HashSet<>();
Set<String> exceptionGroups = new HashSet<>();
getResourceAccessInfo(request, allowExceptionEvaluators, exceptionUsers, exceptionGroups);
users.removeAll(exceptionUsers);
groups.removeAll(exceptionGroups);
}
result.getAllowedUsers().addAll(users);
result.getAllowedGroups().addAll(groups);
}
if (matchType != RangerPolicyResourceMatcher.MatchType.DESCENDANT) {
if (CollectionUtils.isNotEmpty(denyEvaluators)) {
Set<String> users = new HashSet<String>();
Set<String> groups = new HashSet<String>();
getResourceAccessInfo(request, denyEvaluators, users, groups);
if (CollectionUtils.isNotEmpty(denyExceptionEvaluators)) {
Set<String> exceptionUsers = new HashSet<String>();
Set<String> exceptionGroups = new HashSet<String>();
getResourceAccessInfo(request, denyExceptionEvaluators, exceptionUsers, exceptionGroups);
users.removeAll(exceptionUsers);
groups.removeAll(exceptionGroups);
}
result.getDeniedUsers().addAll(users);
result.getDeniedGroups().addAll(groups);
}
}
}
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.getResourceAccessInfo(" + request + ", " + result + ")");
}
}
protected void evaluatePolicyItems(RangerAccessRequest request, RangerAccessResult result, boolean isResourceMatch) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.evaluatePolicyItems(" + request + ", " + result + ", " + isResourceMatch + ")");
}
RangerPolicyItemEvaluator matchedPolicyItem = getMatchingPolicyItem(request, denyEvaluators, denyExceptionEvaluators);
if(matchedPolicyItem == null && !result.getIsAllowed()) { // if not denied, evaluate allowItems only if not already allowed
matchedPolicyItem = getMatchingPolicyItem(request, allowEvaluators, allowExceptionEvaluators);
}
if(matchedPolicyItem != null) {
RangerPolicy policy = getPolicy();
if(matchedPolicyItem.getPolicyItemType() == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY) {
if(isResourceMatch) {
result.setIsAllowed(false);
result.setPolicyId(policy.getId());
result.setReason(matchedPolicyItem.getComments());
}
} else {
if(! result.getIsAllowed()) { // if access is not yet allowed by another policy
result.setIsAllowed(true);
result.setPolicyId(policy.getId());
result.setReason(matchedPolicyItem.getComments());
}
}
}
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.evaluatePolicyItems(" + request + ", " + result + ", " + isResourceMatch + ")");
}
}
protected void evaluatePolicyItems(RangerAccessRequest request, RangerDataMaskResult result) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.evaluatePolicyItems(" + request + ", " + result + ")");
}
RangerDataMaskPolicyItemEvaluator matchedPolicyItem = getMatchingPolicyItem(request, dataMaskEvaluators);
RangerPolicyItemDataMaskInfo dataMaskInfo = matchedPolicyItem != null ? matchedPolicyItem.getDataMaskInfo() : null;
if(dataMaskInfo != null) {
RangerPolicy policy = getPolicy();
result.setIsAllowed(true);
result.setIsAccessDetermined(true);
result.setMaskType(dataMaskInfo.getDataMaskType());
result.setMaskCondition(dataMaskInfo.getConditionExpr());
result.setMaskedValue(dataMaskInfo.getValueExpr());
result.setPolicyId(policy.getId());
}
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.evaluatePolicyItems(" + request + ", " + result + ", " + ")");
}
}
protected void evaluatePolicyItems(RangerAccessRequest request, RangerRowFilterResult result) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.evaluatePolicyItems(" + request + ", " + result + ")");
}
RangerRowFilterPolicyItemEvaluator matchedPolicyItem = getMatchingPolicyItem(request, rowFilterEvaluators);
RangerPolicyItemRowFilterInfo rowFilterInfo = matchedPolicyItem != null ? matchedPolicyItem.getRowFilterInfo() : null;
if(rowFilterInfo != null) {
RangerPolicy policy = getPolicy();
result.setIsAllowed(true);
result.setIsAccessDetermined(true);
result.setFilterExpr(rowFilterInfo.getFilterExpr());
result.setPolicyId(policy.getId());
}
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.evaluatePolicyItems(" + request + ", " + result + ", " + ")");
}
}
protected RangerPolicyItemEvaluator getDeterminingPolicyItem(String user, Set<String> userGroups, String accessType) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.getDeterminingPolicyItem(" + user + ", " + userGroups + ", " + accessType + ")");
}
RangerPolicyItemEvaluator ret = null;
/*
* 1. if a deny matches without hitting any deny-exception, return that
* 2. if an allow matches without hitting any allow-exception, return that
*/
ret = getMatchingPolicyItem(user, userGroups, accessType, denyEvaluators, denyExceptionEvaluators);
if(ret == null) {
ret = getMatchingPolicyItem(user, userGroups, accessType, allowEvaluators, allowExceptionEvaluators);
}
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.getDeterminingPolicyItem(" + user + ", " + userGroups + ", " + accessType + "): " + ret);
}
return ret;
}
private void getResourceAccessInfo(RangerAccessRequest request, List<? extends RangerPolicyItemEvaluator> policyItems, Set<String> users, Set<String> groups) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.getResourceAccessInfo(" + request + ", " + policyItems + ", " + users + ", " + groups + ")");
}
if (CollectionUtils.isNotEmpty(policyItems)) {
for (RangerPolicyItemEvaluator policyItemEvaluator : policyItems) {
if (policyItemEvaluator.matchAccessType(request.getAccessType()) && policyItemEvaluator.matchCustomConditions(request)) {
if (CollectionUtils.isNotEmpty(policyItemEvaluator.getPolicyItem().getUsers())) {
users.addAll(policyItemEvaluator.getPolicyItem().getUsers());
}
if (CollectionUtils.isNotEmpty(policyItemEvaluator.getPolicyItem().getGroups())) {
groups.addAll(policyItemEvaluator.getPolicyItem().getGroups());
}
}
}
}
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.getResourceAccessInfo(" + request + ", " + policyItems + ", " + users + ", " + groups + ")");
}
}
protected boolean isMatch(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resources + ", " + evalContext + ")");
}
boolean ret = resourceMatcher != null && resourceMatcher.isMatch(resources, evalContext);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resources + ", " + evalContext + "): " + ret);
}
return ret;
}
protected boolean isAccessAllowed(String user, Set<String> userGroups, String accessType) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + user + ", " + userGroups + ", " + accessType + ")");
}
boolean ret = false;
RangerPerfTracer perf = null;
if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_REQUEST_LOG)) {
perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.isAccessAllowed(hashCode=" + Integer.toHexString(System.identityHashCode(this)) + "," + perfTag + ")");
}
RangerPolicyItemEvaluator item = this.getDeterminingPolicyItem(user, userGroups, accessType);
if(item != null && item.getPolicyItemType() == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW) {
ret = true;
}
RangerPerfTracer.log(perf);
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + user + ", " + userGroups + ", " + accessType + "): " + ret);
}
return ret;
}
public StringBuilder toString(StringBuilder sb) {
sb.append("RangerDefaultPolicyEvaluator={");
super.toString(sb);
sb.append("resourceMatcher={");
if(resourceMatcher != null) {
resourceMatcher.toString(sb);
}
sb.append("} ");
sb.append("}");
return sb;
}
private void preprocessPolicy(RangerPolicy policy, RangerServiceDef serviceDef) {
if(policy == null || (!hasAllow() && !hasDeny()) || serviceDef == null) {
return;
}
Map<String, Collection<String>> impliedAccessGrants = getImpliedAccessGrants(serviceDef);
if(impliedAccessGrants == null || impliedAccessGrants.isEmpty()) {
return;
}
preprocessPolicyItems(policy.getPolicyItems(), impliedAccessGrants);
preprocessPolicyItems(policy.getDenyPolicyItems(), impliedAccessGrants);
preprocessPolicyItems(policy.getAllowExceptions(), impliedAccessGrants);
preprocessPolicyItems(policy.getDenyExceptions(), impliedAccessGrants);
preprocessPolicyItems(policy.getDataMaskPolicyItems(), impliedAccessGrants);
preprocessPolicyItems(policy.getRowFilterPolicyItems(), impliedAccessGrants);
}
private void preprocessPolicyItems(List<? extends RangerPolicyItem> policyItems, Map<String, Collection<String>> impliedAccessGrants) {
for(RangerPolicyItem policyItem : policyItems) {
if(CollectionUtils.isEmpty(policyItem.getAccesses())) {
continue;
}
// Only one round of 'expansion' is done; multi-level impliedGrants (like shown below) are not handled for now
// multi-level impliedGrants: given admin=>write; write=>read: must imply admin=>read,write
for(Map.Entry<String, Collection<String>> e : impliedAccessGrants.entrySet()) {
String accessType = e.getKey();
Collection<String> impliedGrants = e.getValue();
RangerPolicyItemAccess access = getAccess(policyItem, accessType);
if(access == null) {
continue;
}
for(String impliedGrant : impliedGrants) {
RangerPolicyItemAccess impliedAccess = getAccess(policyItem, impliedGrant);
if(impliedAccess == null) {
impliedAccess = new RangerPolicyItemAccess(impliedGrant, access.getIsAllowed());
policyItem.getAccesses().add(impliedAccess);
} else {
if(! impliedAccess.getIsAllowed()) {
impliedAccess.setIsAllowed(access.getIsAllowed());
}
}
}
}
}
}
private Map<String, Collection<String>> getImpliedAccessGrants(RangerServiceDef serviceDef) {
Map<String, Collection<String>> ret = null;
if(serviceDef != null && !CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
for(RangerAccessTypeDef accessTypeDef : serviceDef.getAccessTypes()) {
if(!CollectionUtils.isEmpty(accessTypeDef.getImpliedGrants())) {
if(ret == null) {
ret = new HashMap<>();
}
Collection<String> impliedAccessGrants = ret.get(accessTypeDef.getName());
if(impliedAccessGrants == null) {
impliedAccessGrants = new HashSet<>();
ret.put(accessTypeDef.getName(), impliedAccessGrants);
}
impliedAccessGrants.addAll(accessTypeDef.getImpliedGrants());
}
}
}
return ret;
}
private RangerPolicyItemAccess getAccess(RangerPolicyItem policyItem, String accessType) {
RangerPolicyItemAccess ret = null;
if(policyItem != null && CollectionUtils.isNotEmpty(policyItem.getAccesses())) {
for(RangerPolicyItemAccess itemAccess : policyItem.getAccesses()) {
if(StringUtils.equalsIgnoreCase(itemAccess.getType(), accessType)) {
ret = itemAccess;
break;
}
}
}
return ret;
}
private List<RangerPolicyItemEvaluator> createPolicyItemEvaluators(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options, int policyItemType) {
List<RangerPolicyItemEvaluator> ret = null;
List<RangerPolicyItem> policyItems = null;
if(isPolicyItemTypeEnabled(serviceDef, policyItemType)) {
if (policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW) {
policyItems = policy.getPolicyItems();
} else if (policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY) {
policyItems = policy.getDenyPolicyItems();
} else if (policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS) {
policyItems = policy.getAllowExceptions();
} else if (policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS) {
policyItems = policy.getDenyExceptions();
}
}
if(CollectionUtils.isNotEmpty(policyItems)) {
ret = new ArrayList<>();
int policyItemCounter = 1;
for(RangerPolicyItem policyItem : policyItems) {
RangerPolicyItemEvaluator itemEvaluator = new RangerDefaultPolicyItemEvaluator(serviceDef, policy, policyItem, policyItemType, policyItemCounter++, options);
itemEvaluator.init();
ret.add(itemEvaluator);
if(CollectionUtils.isNotEmpty(itemEvaluator.getConditionEvaluators())) {
customConditionsCount += itemEvaluator.getConditionEvaluators().size();
}
}
} else {
ret = Collections.<RangerPolicyItemEvaluator>emptyList();
}
return ret;
}
private List<RangerDataMaskPolicyItemEvaluator> createDataMaskPolicyItemEvaluators(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options, List<RangerDataMaskPolicyItem> policyItems) {
List<RangerDataMaskPolicyItemEvaluator> ret = null;
if(CollectionUtils.isNotEmpty(policyItems)) {
ret = new ArrayList<>();
int policyItemCounter = 1;
for(RangerDataMaskPolicyItem policyItem : policyItems) {
RangerDataMaskPolicyItemEvaluator itemEvaluator = new RangerDefaultDataMaskPolicyItemEvaluator(serviceDef, policy, policyItem, policyItemCounter++, options);
itemEvaluator.init();
ret.add(itemEvaluator);
if(CollectionUtils.isNotEmpty(itemEvaluator.getConditionEvaluators())) {
customConditionsCount += itemEvaluator.getConditionEvaluators().size();
}
}
} else {
ret = Collections.<RangerDataMaskPolicyItemEvaluator>emptyList();
}
return ret;
}
private List<RangerRowFilterPolicyItemEvaluator> createRowFilterPolicyItemEvaluators(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options, List<RangerRowFilterPolicyItem> policyItems) {
List<RangerRowFilterPolicyItemEvaluator> ret = null;
if(CollectionUtils.isNotEmpty(policyItems)) {
ret = new ArrayList<>();
int policyItemCounter = 1;
for(RangerRowFilterPolicyItem policyItem : policyItems) {
RangerRowFilterPolicyItemEvaluator itemEvaluator = new RangerDefaultRowFilterPolicyItemEvaluator(serviceDef, policy, policyItem, policyItemCounter++, options);
itemEvaluator.init();
ret.add(itemEvaluator);
if(CollectionUtils.isNotEmpty(itemEvaluator.getConditionEvaluators())) {
customConditionsCount += itemEvaluator.getConditionEvaluators().size();
}
}
} else {
ret = Collections.<RangerRowFilterPolicyItemEvaluator>emptyList();
}
return ret;
}
private boolean isPolicyItemTypeEnabled(RangerServiceDef serviceDef, int policyItemType) {
boolean ret = true;
if(policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY ||
policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS ||
policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS) {
ret = ServiceDefUtil.getOption_enableDenyAndExceptionsInPolicies(serviceDef);
}
return ret;
}
protected <T extends RangerPolicyItemEvaluator> T getMatchingPolicyItem(RangerAccessRequest request, List<T> evaluators) {
T ret = getMatchingPolicyItem(request, evaluators, null);
return ret;
}
private <T extends RangerPolicyItemEvaluator> T getMatchingPolicyItem(RangerAccessRequest request, List<T> evaluators, List<T> exceptionEvaluators) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + request + ")");
}
T ret = null;
if(CollectionUtils.isNotEmpty(evaluators)) {
for (T evaluator : evaluators) {
if(evaluator.isMatch(request)) {
ret = evaluator;
break;
}
}
}
if(ret != null && CollectionUtils.isNotEmpty(exceptionEvaluators)) {
for (T exceptionEvaluator : exceptionEvaluators) {
if(exceptionEvaluator.isMatch(request)) {
if(LOG.isDebugEnabled()) {
LOG.debug("RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + request + "): found exception policyItem(" + exceptionEvaluator.getPolicyItem() + "); ignoring the matchedPolicyItem(" + ret.getPolicyItem() + ")");
}
ret = null;
break;
}
}
}
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + request + "): " + ret);
}
return ret;
}
private <T extends RangerPolicyItemEvaluator> T getMatchingPolicyItem(String user, Set<String> userGroups, String accessType, List<T> evaluators, List<T> exceptionEvaluators) {
if(LOG.isDebugEnabled()) {
LOG.debug("==> RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + user + ", " + userGroups + ", " + accessType + ")");
}
T ret = null;
if(CollectionUtils.isNotEmpty(evaluators)) {
for (T evaluator : evaluators) {
if(evaluator.matchUserGroup(user, userGroups) && evaluator.matchAccessType(accessType)) {
ret = evaluator;
break;
}
}
}
if(ret != null && CollectionUtils.isNotEmpty(exceptionEvaluators)) {
for (T exceptionEvaluator : exceptionEvaluators) {
if(exceptionEvaluator.matchUserGroup(user, userGroups) && exceptionEvaluator.matchAccessType(accessType)) {
if(LOG.isDebugEnabled()) {
LOG.debug("RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + user + ", " + userGroups + ", " + accessType + "): found exception policyItem(" + exceptionEvaluator.getPolicyItem() + "); ignoring the matchedPolicyItem(" + ret.getPolicyItem() + ")");
}
ret = null;
break;
}
}
}
if(LOG.isDebugEnabled()) {
LOG.debug("<== RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + user + ", " + userGroups + ", " + accessType + "): " + ret);
}
return ret;
}
}