blob: c6cb22b774448664edd80b1638e3e3411e6a2b59 [file] [log] [blame]
/*
* 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.util;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerServiceDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerDataMaskTypeDef;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
import org.apache.ranger.plugin.policyengine.RangerPluginContext;
import org.apache.ranger.plugin.store.AbstractServiceStore;
import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
public class ServiceDefUtil {
public static boolean getOption_enableDenyAndExceptionsInPolicies(RangerServiceDef serviceDef, RangerPluginContext pluginContext) {
boolean ret = false;
if(serviceDef != null) {
Configuration config = pluginContext != null ? pluginContext.getConfig() : null;
boolean enableDenyAndExceptionsInPoliciesHiddenOption = config != null ? config.getBoolean("ranger.servicedef.enableDenyAndExceptionsInPolicies", true) : true;
boolean defaultValue = enableDenyAndExceptionsInPoliciesHiddenOption || StringUtils.equalsIgnoreCase(serviceDef.getName(), EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_TAG_NAME);
ret = ServiceDefUtil.getBooleanValue(serviceDef.getOptions(), RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES, defaultValue);
}
return ret;
}
public static RangerDataMaskTypeDef getDataMaskType(RangerServiceDef serviceDef, String typeName) {
RangerDataMaskTypeDef ret = null;
if(serviceDef != null && serviceDef.getDataMaskDef() != null) {
List<RangerDataMaskTypeDef> maskTypes = serviceDef.getDataMaskDef().getMaskTypes();
if(CollectionUtils.isNotEmpty(maskTypes)) {
for(RangerDataMaskTypeDef maskType : maskTypes) {
if(StringUtils.equals(maskType.getName(), typeName)) {
ret = maskType;
break;
}
}
}
}
return ret;
}
public static RangerServiceDef normalize(RangerServiceDef serviceDef) {
normalizeDataMaskDef(serviceDef);
normalizeRowFilterDef(serviceDef);
return serviceDef;
}
public static RangerResourceDef getResourceDef(RangerServiceDef serviceDef, String resource) {
RangerResourceDef ret = null;
if(serviceDef != null && resource != null && CollectionUtils.isNotEmpty(serviceDef.getResources())) {
for(RangerResourceDef resourceDef : serviceDef.getResources()) {
if(StringUtils.equalsIgnoreCase(resourceDef.getName(), resource)) {
ret = resourceDef;
break;
}
}
}
return ret;
}
public static Integer getLeafResourceLevel(RangerServiceDef serviceDef, Map<String, RangerPolicy.RangerPolicyResource> policyResource) {
Integer ret = null;
RangerResourceDef resourceDef = getLeafResourceDef(serviceDef, policyResource);
if (resourceDef != null) {
ret = resourceDef.getLevel();
}
return ret;
}
public static RangerResourceDef getLeafResourceDef(RangerServiceDef serviceDef, Map<String, RangerPolicy.RangerPolicyResource> policyResource) {
RangerResourceDef ret = null;
if(serviceDef != null && policyResource != null) {
for(Map.Entry<String, RangerPolicy.RangerPolicyResource> entry : policyResource.entrySet()) {
if (!isEmpty(entry.getValue())) {
String resource = entry.getKey();
RangerResourceDef resourceDef = ServiceDefUtil.getResourceDef(serviceDef, resource);
if (resourceDef != null && resourceDef.getLevel() != null) {
if (ret == null) {
ret = resourceDef;
} else if(ret.getLevel() < resourceDef.getLevel()) {
ret = resourceDef;
}
}
}
}
}
return ret;
}
public static boolean isAncestorOf(RangerServiceDef serviceDef, RangerResourceDef ancestor, RangerResourceDef descendant) {
boolean ret = false;
if (ancestor != null && descendant != null) {
final String ancestorName = ancestor.getName();
for (RangerResourceDef node = descendant; node != null; node = ServiceDefUtil.getResourceDef(serviceDef, node.getParent())) {
if (StringUtils.equalsIgnoreCase(ancestorName, node.getParent())) {
ret = true;
break;
}
}
}
return ret;
}
public static boolean isEmpty(RangerPolicy.RangerPolicyResource policyResource) {
boolean ret = true;
if (policyResource != null) {
List<String> resourceValues = policyResource.getValues();
if (CollectionUtils.isNotEmpty(resourceValues)) {
for (String resourceValue : resourceValues) {
if (StringUtils.isNotBlank(resourceValue)) {
ret = false;
break;
}
}
}
}
return ret;
}
public static String getOption(Map<String, String> options, String name, String defaultValue) {
String ret = options != null && name != null ? options.get(name) : null;
if(ret == null) {
ret = defaultValue;
}
return ret;
}
public static boolean getBooleanOption(Map<String, String> options, String name, boolean defaultValue) {
String val = getOption(options, name, null);
return val == null ? defaultValue : Boolean.parseBoolean(val);
}
public static char getCharOption(Map<String, String> options, String name, char defaultValue) {
String val = getOption(options, name, null);
return StringUtils.isEmpty(val) ? defaultValue : val.charAt(0);
}
public static 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 static void normalizeDataMaskDef(RangerServiceDef serviceDef) {
if(serviceDef != null && serviceDef.getDataMaskDef() != null) {
List<RangerResourceDef> dataMaskResources = serviceDef.getDataMaskDef().getResources();
List<RangerAccessTypeDef> dataMaskAccessTypes = serviceDef.getDataMaskDef().getAccessTypes();
if(CollectionUtils.isNotEmpty(dataMaskResources)) {
List<RangerResourceDef> resources = serviceDef.getResources();
List<RangerResourceDef> processedDefs = new ArrayList<RangerResourceDef>(dataMaskResources.size());
for(RangerResourceDef dataMaskResource : dataMaskResources) {
RangerResourceDef processedDef = dataMaskResource;
for(RangerResourceDef resourceDef : resources) {
if(StringUtils.equals(resourceDef.getName(), dataMaskResource.getName())) {
processedDef = ServiceDefUtil.mergeResourceDef(resourceDef, dataMaskResource);
break;
}
}
processedDefs.add(processedDef);
}
serviceDef.getDataMaskDef().setResources(processedDefs);
}
if(CollectionUtils.isNotEmpty(dataMaskAccessTypes)) {
List<RangerAccessTypeDef> accessTypes = serviceDef.getAccessTypes();
List<RangerAccessTypeDef> processedDefs = new ArrayList<RangerAccessTypeDef>(accessTypes.size());
for(RangerAccessTypeDef dataMaskAccessType : dataMaskAccessTypes) {
RangerAccessTypeDef processedDef = dataMaskAccessType;
for(RangerAccessTypeDef accessType : accessTypes) {
if(StringUtils.equals(accessType.getName(), dataMaskAccessType.getName())) {
processedDef = ServiceDefUtil.mergeAccessTypeDef(accessType, dataMaskAccessType);
break;
}
}
processedDefs.add(processedDef);
}
serviceDef.getDataMaskDef().setAccessTypes(processedDefs);
}
}
}
private static void normalizeRowFilterDef(RangerServiceDef serviceDef) {
if(serviceDef != null && serviceDef.getRowFilterDef() != null) {
List<RangerResourceDef> rowFilterResources = serviceDef.getRowFilterDef().getResources();
List<RangerAccessTypeDef> rowFilterAccessTypes = serviceDef.getRowFilterDef().getAccessTypes();
if(CollectionUtils.isNotEmpty(rowFilterResources)) {
List<RangerResourceDef> resources = serviceDef.getResources();
List<RangerResourceDef> processedDefs = new ArrayList<RangerResourceDef>(rowFilterResources.size());
for(RangerResourceDef rowFilterResource : rowFilterResources) {
RangerResourceDef processedDef = rowFilterResource;
for(RangerResourceDef resourceDef : resources) {
if(StringUtils.equals(resourceDef.getName(), rowFilterResource.getName())) {
processedDef = ServiceDefUtil.mergeResourceDef(resourceDef, rowFilterResource);
break;
}
}
processedDefs.add(processedDef);
}
serviceDef.getRowFilterDef().setResources(processedDefs);
}
if(CollectionUtils.isNotEmpty(rowFilterAccessTypes)) {
List<RangerAccessTypeDef> accessTypes = serviceDef.getAccessTypes();
List<RangerAccessTypeDef> processedDefs = new ArrayList<RangerAccessTypeDef>(accessTypes.size());
for(RangerAccessTypeDef rowFilterAccessType : rowFilterAccessTypes) {
RangerAccessTypeDef processedDef = rowFilterAccessType;
for(RangerAccessTypeDef accessType : accessTypes) {
if(StringUtils.equals(accessType.getName(), rowFilterAccessType.getName())) {
processedDef = ServiceDefUtil.mergeAccessTypeDef(accessType, rowFilterAccessType);
break;
}
}
processedDefs.add(processedDef);
}
serviceDef.getRowFilterDef().setAccessTypes(processedDefs);
}
}
}
private static RangerResourceDef mergeResourceDef(RangerResourceDef base, RangerResourceDef delta) {
RangerResourceDef ret = new RangerResourceDef(base);
// retain base values for: itemId, name, type, level, parent, lookupSupported
if(Boolean.TRUE.equals(delta.getMandatory()))
ret.setMandatory(delta.getMandatory());
if(delta.getRecursiveSupported() != null)
ret.setRecursiveSupported(delta.getRecursiveSupported());
if(delta.getExcludesSupported() != null)
ret.setExcludesSupported(delta.getExcludesSupported());
if(StringUtils.isNotEmpty(delta.getMatcher()))
ret.setMatcher(delta.getMatcher());
if(MapUtils.isNotEmpty(delta.getMatcherOptions())) {
if(ret.getMatcherOptions() == null) {
ret.setMatcherOptions(new HashMap<String, String>());
}
for(Map.Entry<String, String> e : delta.getMatcherOptions().entrySet()) {
ret.getMatcherOptions().put(e.getKey(), e.getValue());
}
}
if(StringUtils.isNotEmpty(delta.getValidationRegEx()))
ret.setValidationRegEx(delta.getValidationRegEx());
if(StringUtils.isNotEmpty(delta.getValidationMessage()))
ret.setValidationMessage(delta.getValidationMessage());
ret.setUiHint(delta.getUiHint());
if(StringUtils.isNotEmpty(delta.getLabel()))
ret.setLabel(delta.getLabel());
if(StringUtils.isNotEmpty(delta.getDescription()))
ret.setDescription(delta.getDescription());
if(StringUtils.isNotEmpty(delta.getRbKeyLabel()))
ret.setRbKeyLabel(delta.getRbKeyLabel());
if(StringUtils.isNotEmpty(delta.getRbKeyDescription()))
ret.setRbKeyDescription(delta.getRbKeyDescription());
if(StringUtils.isNotEmpty(delta.getRbKeyValidationMessage()))
ret.setRbKeyValidationMessage(delta.getRbKeyValidationMessage());
if(CollectionUtils.isNotEmpty(delta.getAccessTypeRestrictions()))
ret.setAccessTypeRestrictions(delta.getAccessTypeRestrictions());
boolean copyLeafValue = false;
if (ret.getIsValidLeaf() != null) {
if (!ret.getIsValidLeaf().equals(delta.getIsValidLeaf())) {
copyLeafValue = true;
}
} else {
if (delta.getIsValidLeaf() != null) {
copyLeafValue = true;
}
}
if (copyLeafValue)
ret.setIsValidLeaf(delta.getIsValidLeaf());
return ret;
}
private static RangerAccessTypeDef mergeAccessTypeDef(RangerAccessTypeDef base, RangerAccessTypeDef delta) {
RangerAccessTypeDef ret = new RangerAccessTypeDef(base);
// retain base values for: itemId, name, impliedGrants
if(StringUtils.isNotEmpty(delta.getLabel()))
ret.setLabel(delta.getLabel());
if(StringUtils.isNotEmpty(delta.getRbKeyLabel()))
ret.setRbKeyLabel(delta.getRbKeyLabel());
return ret;
}
private static boolean getBooleanValue(Map<String, String> map, String elementName, boolean defaultValue) {
boolean ret = defaultValue;
if(MapUtils.isNotEmpty(map) && map.containsKey(elementName)) {
String elementValue = map.get(elementName);
if(StringUtils.isNotEmpty(elementValue)) {
ret = Boolean.valueOf(elementValue.toString());
}
}
return ret;
}
}