/* * 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.Collections; import java.util.HashSet; import java.util.List; 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.conditionevaluator.RangerAbstractConditionEvaluator; import org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator; import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition; import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef; import org.apache.ranger.plugin.policyengine.RangerAccessRequest; import org.apache.ranger.plugin.policyengine.RangerAccessResource; import org.apache.ranger.plugin.policyengine.RangerPolicyEngine; import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions; import org.apache.ranger.plugin.util.RangerPerfTracer; public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEvaluator { private static final Log LOG = LogFactory.getLog(RangerDefaultPolicyItemEvaluator.class); private static final Log PERF_POLICYITEM_INIT_LOG = RangerPerfTracer.getPerfLogger("policyitem.init"); private static final Log PERF_POLICYITEM_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policyitem.request"); private static final Log PERF_POLICYCONDITION_INIT_LOG = RangerPerfTracer.getPerfLogger("policycondition.init"); private static final Log PERF_POLICYCONDITION_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policycondition.request"); private boolean hasCurrentUser; private boolean hasResourceOwner; private boolean hasAllPerms; public RangerDefaultPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, int policyItemType, int policyItemIndex, RangerPolicyEngineOptions options) { super(serviceDef, policy, policyItem, policyItemType, policyItemIndex, options); } public void init() { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator(policyId=" + policyId + ", policyItem=" + policyItem + ", serviceType=" + getServiceType() + ", conditionsDisabled=" + getConditionsDisabledOption() + ")"); } Set<String> accessPerms = new HashSet<String>(); List<RangerPolicy.RangerPolicyItemAccess> policyItemAccesses = policyItem.getAccesses(); for(RangerPolicy.RangerPolicyItemAccess policyItemAccess : policyItemAccesses) { if (policyItemAccess.getIsAllowed()) { accessPerms.add(policyItemAccess.getType()); } } hasAllPerms = true; List<RangerServiceDef.RangerAccessTypeDef> serviceAccessTypes = serviceDef.getAccessTypes(); for (RangerServiceDef.RangerAccessTypeDef serviceAccessType : serviceAccessTypes) { String serviceAccessTypeName = serviceAccessType.getName(); if (!accessPerms.contains(serviceAccessTypeName)) { hasAllPerms = false; break; } } if (!getConditionsDisabledOption() && CollectionUtils.isNotEmpty(policyItem.getConditions())) { conditionEvaluators = new ArrayList<>(); RangerPerfTracer perf = null; if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYITEM_INIT_LOG)) { perf = RangerPerfTracer.getPerfTracer(PERF_POLICYITEM_INIT_LOG, "RangerPolicyItemEvaluator.init(policyId=" + policyId + ",policyItemIndex=" + getPolicyItemIndex() + ")"); } for (RangerPolicyItemCondition condition : policyItem.getConditions()) { RangerPolicyConditionDef conditionDef = getConditionDef(condition.getType()); if (conditionDef == null) { LOG.error("RangerDefaultPolicyItemEvaluator(policyId=" + policyId + "): conditionDef '" + condition.getType() + "' not found. Ignoring the condition"); continue; } RangerConditionEvaluator conditionEvaluator = newConditionEvaluator(conditionDef.getEvaluator()); if (conditionEvaluator != null) { conditionEvaluator.setServiceDef(serviceDef); conditionEvaluator.setConditionDef(conditionDef); conditionEvaluator.setPolicyItemCondition(condition); RangerPerfTracer perfConditionInit = null; if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYCONDITION_INIT_LOG)) { perfConditionInit = RangerPerfTracer.getPerfTracer(PERF_POLICYCONDITION_INIT_LOG, "RangerConditionEvaluator.init(policyId=" + policyId + ",policyItemIndex=" + getPolicyItemIndex() + ",policyConditionType=" + condition.getType() + ")"); } conditionEvaluator.init(); RangerPerfTracer.log(perfConditionInit); conditionEvaluators.add(conditionEvaluator); } else { LOG.error("RangerDefaultPolicyItemEvaluator(policyId=" + policyId + "): failed to instantiate condition evaluator '" + condition.getType() + "'; evaluatorClassName='" + conditionDef.getEvaluator() + "'"); } } RangerPerfTracer.log(perf); } List<String> users = policyItem.getUsers(); this.hasCurrentUser = CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.USER_CURRENT); this.hasResourceOwner = CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.RESOURCE_OWNER); if(LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator(policyId=" + policyId + ", conditionsCount=" + getConditionEvaluators().size() + ")"); } } @Override public boolean isMatch(RangerAccessRequest request) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.isMatch(" + request + ")"); } boolean ret = false; RangerPerfTracer perf = null; if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYITEM_REQUEST_LOG)) { perf = RangerPerfTracer.getPerfTracer(PERF_POLICYITEM_REQUEST_LOG, "RangerPolicyItemEvaluator.isMatch(resource=" + request.getResource().getAsString() + ")"); } if(policyItem != null) { if(matchUserGroupAndOwner(request)) { if (request.isAccessTypeDelegatedAdmin()) { // used only in grant/revoke scenario if (policyItem.getDelegateAdmin()) { ret = true; } } else if (CollectionUtils.isNotEmpty(policyItem.getAccesses())) { boolean isAccessTypeMatched = false; if (request.isAccessTypeAny()) { if (getPolicyItemType() == POLICY_ITEM_TYPE_DENY || getPolicyItemType() == POLICY_ITEM_TYPE_DENY_EXCEPTIONS) { if (hasAllPerms) { isAccessTypeMatched = true; } } else { for (RangerPolicy.RangerPolicyItemAccess access : policyItem.getAccesses()) { if (access.getIsAllowed()) { isAccessTypeMatched = true; break; } } } } else { for (RangerPolicy.RangerPolicyItemAccess access : policyItem.getAccesses()) { if (access.getIsAllowed() && StringUtils.equalsIgnoreCase(access.getType(), request.getAccessType())) { isAccessTypeMatched = true; break; } } } if(isAccessTypeMatched) { if(matchCustomConditions(request)) { ret = true; } } } } } RangerPerfTracer.log(perf); if(LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.isMatch(" + request + "): " + ret); } return ret; } @Override public boolean matchUserGroup(String user, Set<String> userGroups) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchUserGroup(" + policyItem + ", " + user + ", " + userGroups + ")"); } boolean ret = false; if(policyItem != null) { if(!ret && user != null && policyItem.getUsers() != null) { ret = hasCurrentUser || policyItem.getUsers().contains(user); } if(!ret && userGroups != null && policyItem.getGroups() != null) { ret = policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC) || !Collections.disjoint(policyItem.getGroups(), userGroups); } } if(LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchUserGroup(" + policyItem + ", " + user + ", " + userGroups + "): " + ret); } return ret; } private boolean matchUserGroupAndOwner(RangerAccessRequest request) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchUserGroupAndOwner(" + request + ")"); } boolean ret = false; String user = request.getUser(); Set<String> userGroups = request.getUserGroups(); if (hasResourceOwner) { RangerAccessResource accessedResource = request.getResource(); String resourceOwner = accessedResource != null ? accessedResource.getOwnerUser() : null; if (user != null && resourceOwner != null && user.equals(resourceOwner)) { ret = true; } } if (!ret) { ret = matchUserGroup(user, userGroups); } if(LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchUserGroupAndOwner(" + request + "): " + ret); } return ret; } @Override public boolean matchAccessType(String accessType) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchAccessType(" + accessType + ")"); } boolean ret = false; if(policyItem != null) { boolean isAdminAccess = StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS); if(isAdminAccess) { ret = policyItem.getDelegateAdmin(); } else { if(CollectionUtils.isNotEmpty(policyItem.getAccesses())) { boolean isAnyAccess = StringUtils.equals(accessType, RangerPolicyEngine.ANY_ACCESS); for(RangerPolicyItemAccess itemAccess : policyItem.getAccesses()) { if(! itemAccess.getIsAllowed()) { continue; } if(isAnyAccess) { ret = true; break; } else if(StringUtils.equalsIgnoreCase(itemAccess.getType(), accessType)) { ret = true; break; } } } } } if(LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchAccessType(" + accessType + "): " + ret); } return ret; } @Override public boolean matchCustomConditions(RangerAccessRequest request) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchCustomConditions(" + request + ")"); } boolean ret = true; if (CollectionUtils.isNotEmpty(conditionEvaluators)) { if(LOG.isDebugEnabled()) { LOG.debug("RangerDefaultPolicyItemEvaluator.matchCustomConditions(): conditionCount=" + conditionEvaluators.size()); } for(RangerConditionEvaluator conditionEvaluator : conditionEvaluators) { if(LOG.isDebugEnabled()) { LOG.debug("evaluating condition: " + conditionEvaluator); } RangerPerfTracer perf = null; if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYCONDITION_REQUEST_LOG)) { String conditionType = null; if (conditionEvaluator instanceof RangerAbstractConditionEvaluator) { conditionType = ((RangerAbstractConditionEvaluator)conditionEvaluator).getPolicyItemCondition().getType(); } perf = RangerPerfTracer.getPerfTracer(PERF_POLICYCONDITION_REQUEST_LOG, "RangerConditionEvaluator.matchCondition(policyId=" + policyId + ",policyItemIndex=" + getPolicyItemIndex() + ",policyConditionType=" + conditionType + ")"); } boolean conditionEvalResult = conditionEvaluator.isMatched(request); RangerPerfTracer.log(perf); if (!conditionEvalResult) { if(LOG.isDebugEnabled()) { LOG.debug(conditionEvaluator + " returned false"); } ret = false; break; } } } if(LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchCustomConditions(" + request + "): " + ret); } return ret; } RangerPolicyConditionDef getConditionDef(String conditionName) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.getConditionDef(" + conditionName + ")"); } RangerPolicyConditionDef ret = null; if (serviceDef != null && CollectionUtils.isNotEmpty(serviceDef.getPolicyConditions())) { for(RangerPolicyConditionDef conditionDef : serviceDef.getPolicyConditions()) { if(StringUtils.equals(conditionName, conditionDef.getName())) { ret = conditionDef; break; } } } if(LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.getConditionDef(" + conditionName + "): " + ret); } return ret; } RangerConditionEvaluator newConditionEvaluator(String className) { if(LOG.isDebugEnabled()) { LOG.debug("==> RangerDefaultPolicyItemEvaluator.newConditionEvaluator(" + className + ")"); } RangerConditionEvaluator evaluator = null; try { @SuppressWarnings("unchecked") Class<RangerConditionEvaluator> matcherClass = (Class<RangerConditionEvaluator>)Class.forName(className); evaluator = matcherClass.newInstance(); } catch(Throwable t) { LOG.error("RangerDefaultPolicyItemEvaluator.newConditionEvaluator(" + className + "): error instantiating evaluator", t); } if(LOG.isDebugEnabled()) { LOG.debug("<== RangerDefaultPolicyItemEvaluator.newConditionEvaluator(" + className + "): " + evaluator); } return evaluator; } }