/* * 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 java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ranger.authorization.hadoop.config.RangerConfiguration; import org.apache.ranger.authorization.utils.StringUtil; import org.apache.ranger.db.RangerDaoManager; import org.apache.ranger.entity.*; import org.apache.ranger.plugin.model.*; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; import org.apache.ranger.plugin.util.RangerPerfTracer; public class RangerTagDBRetriever { static final Log LOG = LogFactory.getLog(RangerTagDBRetriever.class); static final Log PERF_LOG = RangerPerfTracer.getPerfLogger("db.RangerTagDBRetriever"); public static final String OPTION_RANGER_FILTER_TAGS_FOR_SERVICE_PLUGIN = "ranger.filter.tags.for.service.plugin"; private final RangerDaoManager daoMgr; private final XXService xService; private final LookupCache lookupCache; private List<RangerServiceResource> serviceResources; private Map<Long, RangerTagDef> tagDefs; private Map<Long, RangerTag> tags; private List<RangerTagResourceMap> tagResourceMaps; private boolean filterForServicePlugin; public RangerTagDBRetriever(final RangerDaoManager daoMgr, final XXService xService) { this.daoMgr = daoMgr; this.xService = xService; this.lookupCache = new LookupCache(); if (this.daoMgr != null && this.xService != null) { RangerPerfTracer perf = null; if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerTagDBReceiver.getTags(serviceName=" + xService.getName()); } filterForServicePlugin = RangerConfiguration.getInstance().getBoolean(OPTION_RANGER_FILTER_TAGS_FOR_SERVICE_PLUGIN, false); TagRetrieverServiceResourceContext serviceResourceContext = new TagRetrieverServiceResourceContext(xService); TagRetrieverTagDefContext tagDefContext = new TagRetrieverTagDefContext(xService); TagRetrieverTagContext tagContext = new TagRetrieverTagContext(xService); serviceResources = serviceResourceContext.getAllServiceResources(); tagDefs = tagDefContext.getAllTagDefs(); tags = tagContext.getAllTags(); tagResourceMaps = getAllTagResourceMaps(); RangerPerfTracer.log(perf); } } public List<RangerTagResourceMap> getTagResourceMaps() { return tagResourceMaps; } public List<RangerServiceResource> getServiceResources() { return serviceResources; } public Map<Long, RangerTagDef> getTagDefs() { return tagDefs; } public Map<Long, RangerTag> getTags() { return tags; } private List<RangerTagResourceMap> getAllTagResourceMaps() { List<XXTagResourceMap> xTagResourceMaps = filterForServicePlugin ? daoMgr.getXXTagResourceMap().findForServicePlugin(xService.getId()) : daoMgr.getXXTagResourceMap().findByServiceId(xService.getId()); ListIterator<XXTagResourceMap> iterTagResourceMap = xTagResourceMaps.listIterator(); List<RangerTagResourceMap> ret = new ArrayList<RangerTagResourceMap>(); while (iterTagResourceMap.hasNext()) { XXTagResourceMap xTagResourceMap = iterTagResourceMap.next(); if (xTagResourceMap != null) { RangerTagResourceMap tagResourceMap = new RangerTagResourceMap(); tagResourceMap.setId(xTagResourceMap.getId()); tagResourceMap.setGuid(xTagResourceMap.getGuid()); tagResourceMap.setCreatedBy(lookupCache.getUserScreenName(xTagResourceMap.getAddedByUserId())); tagResourceMap.setUpdatedBy(lookupCache.getUserScreenName(xTagResourceMap.getUpdatedByUserId())); tagResourceMap.setCreateTime(xTagResourceMap.getCreateTime()); tagResourceMap.setUpdateTime(xTagResourceMap.getUpdateTime()); tagResourceMap.setResourceId(xTagResourceMap.getResourceId()); tagResourceMap.setTagId(xTagResourceMap.getTagId()); ret.add(tagResourceMap); } } return ret; } static <T> List<T> asList(T obj) { List<T> ret = new ArrayList<T>(); if (obj != null) { ret.add(obj); } return ret; } private class LookupCache { final Map<Long, String> userScreenNames = new HashMap<Long, String>(); final Map<Long, String> resourceDefs = new HashMap<Long, String>(); String getUserScreenName(Long userId) { String ret = null; if (userId != null) { ret = userScreenNames.get(userId); if (ret == null) { XXPortalUser user = daoMgr.getXXPortalUser().getById(userId); if (user != null) { ret = user.getPublicScreenName(); if (StringUtil.isEmpty(ret)) { ret = user.getFirstName(); if (StringUtil.isEmpty(ret)) { ret = user.getLoginId(); } else { if (!StringUtil.isEmpty(user.getLastName())) { ret += (" " + user.getLastName()); } } } if (ret != null) { userScreenNames.put(userId, ret); } } } } return ret; } String getResourceName(Long resourceDefId) { String ret = null; if (resourceDefId != null) { ret = resourceDefs.get(resourceDefId); if (ret == null) { XXResourceDef xResourceDef = daoMgr.getXXResourceDef().getById(resourceDefId); if (xResourceDef != null) { ret = xResourceDef.getName(); resourceDefs.put(resourceDefId, ret); } } } return ret; } } private class TagRetrieverServiceResourceContext { final XXService service; final ListIterator<XXServiceResource> iterServiceResource; final ListIterator<XXServiceResourceElement> iterServiceResourceElement; final ListIterator<XXServiceResourceElementValue> iterServiceResourceElementValue; TagRetrieverServiceResourceContext(XXService xService) { Long serviceId = xService == null ? null : xService.getId(); List<XXServiceResource> xServiceResources = filterForServicePlugin ? daoMgr.getXXServiceResource().findForServicePlugin(serviceId) : daoMgr.getXXServiceResource().findTaggedResourcesInServiceId(serviceId); List<XXServiceResourceElement> xServiceResourceElements = filterForServicePlugin ? daoMgr.getXXServiceResourceElement().findForServicePlugin(serviceId) : daoMgr.getXXServiceResourceElement().findTaggedResourcesInServiceId(serviceId); List<XXServiceResourceElementValue> xServiceResourceElementValues = filterForServicePlugin ? daoMgr.getXXServiceResourceElementValue().findForServicePlugin(serviceId) : daoMgr.getXXServiceResourceElementValue().findTaggedResourcesInServiceId(serviceId); this.service = xService; this.iterServiceResource = xServiceResources.listIterator(); this.iterServiceResourceElement = xServiceResourceElements.listIterator(); this.iterServiceResourceElementValue = xServiceResourceElementValues.listIterator(); } TagRetrieverServiceResourceContext(XXServiceResource xServiceResource, XXService xService) { Long resourceId = xServiceResource == null ? null : xServiceResource.getId(); List<XXServiceResource> xServiceResources = asList(xServiceResource); List<XXServiceResourceElement> xServiceResourceElements = daoMgr.getXXServiceResourceElement().findByResourceId(resourceId); List<XXServiceResourceElementValue> xServiceResourceElementValues = daoMgr.getXXServiceResourceElementValue().findByResourceId(resourceId); this.service = xService; this.iterServiceResource = xServiceResources.listIterator(); this.iterServiceResourceElement = xServiceResourceElements.listIterator(); this.iterServiceResourceElementValue = xServiceResourceElementValues.listIterator(); } List<RangerServiceResource> getAllServiceResources() { List<RangerServiceResource> ret = new ArrayList<RangerServiceResource>(); while (iterServiceResource.hasNext()) { RangerServiceResource serviceResource = getNextServiceResource(); if (serviceResource != null) { ret.add(serviceResource); } } if (!hasProcessedAll()) { LOG.warn("getAllServiceResources(): perhaps one or more serviceResources got updated during retrieval. Using fallback ... "); ret = getServiceResourcesBySecondary(); } return ret; } RangerServiceResource getNextServiceResource() { RangerServiceResource ret = null; if (iterServiceResource.hasNext()) { XXServiceResource xServiceResource = iterServiceResource.next(); if (xServiceResource != null) { ret = new RangerServiceResource(); ret.setId(xServiceResource.getId()); ret.setGuid(xServiceResource.getGuid()); ret.setIsEnabled(xServiceResource.getIsEnabled()); ret.setCreatedBy(lookupCache.getUserScreenName(xServiceResource.getAddedByUserId())); ret.setUpdatedBy(lookupCache.getUserScreenName(xServiceResource.getUpdatedByUserId())); ret.setCreateTime(xServiceResource.getCreateTime()); ret.setUpdateTime(xServiceResource.getUpdateTime()); ret.setVersion(xServiceResource.getVersion()); ret.setResourceSignature(xServiceResource.getResourceSignature()); getServiceResourceElements(ret); } } return ret; } void getServiceResourceElements(RangerServiceResource serviceResource) { while (iterServiceResourceElement.hasNext()) { XXServiceResourceElement xServiceResourceElement = iterServiceResourceElement.next(); if (xServiceResourceElement.getResourceId().equals(serviceResource.getId())) { RangerPolicyResource resource = new RangerPolicyResource(); resource.setIsExcludes(xServiceResourceElement.getIsExcludes()); resource.setIsRecursive(xServiceResourceElement.getIsRecursive()); while (iterServiceResourceElementValue.hasNext()) { XXServiceResourceElementValue xServiceResourceElementValue = iterServiceResourceElementValue.next(); if (xServiceResourceElementValue.getResElementId().equals(xServiceResourceElement.getId())) { resource.getValues().add(xServiceResourceElementValue.getValue()); } else { if (iterServiceResourceElementValue.hasPrevious()) { iterServiceResourceElementValue.previous(); } break; } } serviceResource.getResourceElements().put(lookupCache.getResourceName(xServiceResourceElement.getResDefId()), resource); } else if (xServiceResourceElement.getResourceId().compareTo(serviceResource.getId()) > 0) { if (iterServiceResourceElement.hasPrevious()) { iterServiceResourceElement.previous(); } break; } } } boolean hasProcessedAll() { boolean moreToProcess = iterServiceResource.hasNext() || iterServiceResourceElement.hasNext() || iterServiceResourceElementValue.hasNext(); return !moreToProcess; } List<RangerServiceResource> getServiceResourcesBySecondary() { List<RangerServiceResource> ret = null; if (service != null) { List<XXServiceResource> xServiceResources = filterForServicePlugin ? daoMgr.getXXServiceResource().findForServicePlugin(service.getId()) : daoMgr.getXXServiceResource().findTaggedResourcesInServiceId(service.getId()); if (CollectionUtils.isNotEmpty(xServiceResources)) { ret = new ArrayList<RangerServiceResource>(xServiceResources.size()); for (XXServiceResource xServiceResource : xServiceResources) { TagRetrieverServiceResourceContext ctx = new TagRetrieverServiceResourceContext(xServiceResource, service); RangerServiceResource serviceResource = ctx.getNextServiceResource(); if (serviceResource != null) { ret.add(serviceResource); } } } } return ret; } } private class TagRetrieverTagDefContext { final XXService service; final ListIterator<XXTagDef> iterTagDef; final ListIterator<XXTagAttributeDef> iterTagAttributeDef; TagRetrieverTagDefContext(XXService xService) { Long serviceId = xService == null ? null : xService.getId(); List<XXTagDef> xTagDefs = filterForServicePlugin ? daoMgr.getXXTagDef().findForServicePlugin(serviceId) : daoMgr.getXXTagDef().findByServiceId(serviceId); List<XXTagAttributeDef> xTagAttributeDefs = filterForServicePlugin ? daoMgr.getXXTagAttributeDef().findForServicePlugin(serviceId) : daoMgr.getXXTagAttributeDef().findByServiceId(serviceId); this.service = xService; this.iterTagDef = xTagDefs.listIterator(); this.iterTagAttributeDef = xTagAttributeDefs.listIterator(); } TagRetrieverTagDefContext(XXTagDef xTagDef, XXService xService) { Long tagDefId = xTagDef == null ? null : xTagDef.getId(); List<XXTagDef> xTagDefs = asList(xTagDef); List<XXTagAttributeDef> xTagAttributeDefs = daoMgr.getXXTagAttributeDef().findByTagDefId(tagDefId); this.service = xService; this.iterTagDef = xTagDefs.listIterator(); this.iterTagAttributeDef = xTagAttributeDefs.listIterator(); } Map<Long, RangerTagDef> getAllTagDefs() { Map<Long, RangerTagDef> ret = new HashMap<Long, RangerTagDef>(); while (iterTagDef.hasNext()) { RangerTagDef tagDef = getNextTagDef(); if (tagDef != null) { ret.put(tagDef.getId(), tagDef); } } if (!hasProcessedAllTagDefs()) { LOG.warn("getAllTagDefs(): perhaps one or more tag-definitions got updated during retrieval. Using fallback ... "); ret = getTagDefsBySecondary(); } return ret; } RangerTagDef getNextTagDef() { RangerTagDef ret = null; if (iterTagDef.hasNext()) { XXTagDef xTagDef = iterTagDef.next(); if (xTagDef != null) { ret = new RangerTagDef(); ret.setId(xTagDef.getId()); ret.setGuid(xTagDef.getGuid()); ret.setIsEnabled(xTagDef.getIsEnabled()); ret.setCreatedBy(lookupCache.getUserScreenName(xTagDef.getAddedByUserId())); ret.setUpdatedBy(lookupCache.getUserScreenName(xTagDef.getUpdatedByUserId())); ret.setCreateTime(xTagDef.getCreateTime()); ret.setUpdateTime(xTagDef.getUpdateTime()); ret.setVersion(xTagDef.getVersion()); ret.setName(xTagDef.getName()); ret.setSource(xTagDef.getSource()); getTagAttributeDefs(ret); } } return ret; } void getTagAttributeDefs(RangerTagDef tagDef) { while (iterTagAttributeDef.hasNext()) { XXTagAttributeDef xTagAttributeDef = iterTagAttributeDef.next(); if (xTagAttributeDef.getTagDefId().equals(tagDef.getId())) { RangerTagDef.RangerTagAttributeDef tagAttributeDef = new RangerTagDef.RangerTagAttributeDef(); tagAttributeDef.setName(xTagAttributeDef.getName()); tagAttributeDef.setType(xTagAttributeDef.getType()); tagDef.getAttributeDefs().add(tagAttributeDef); } else if (xTagAttributeDef.getTagDefId().compareTo(tagDef.getId()) > 0) { if (iterTagAttributeDef.hasPrevious()) { iterTagAttributeDef.previous(); } break; } } } boolean hasProcessedAllTagDefs() { boolean moreToProcess = iterTagAttributeDef.hasNext(); return !moreToProcess; } Map<Long, RangerTagDef> getTagDefsBySecondary() { Map<Long, RangerTagDef> ret = null; if (service != null) { List<XXTagDef> xTagDefs = daoMgr.getXXTagDef().findByServiceId(service.getId()); if (CollectionUtils.isNotEmpty(xTagDefs)) { ret = new HashMap<Long, RangerTagDef>(xTagDefs.size()); for (XXTagDef xTagDef : xTagDefs) { TagRetrieverTagDefContext ctx = new TagRetrieverTagDefContext(xTagDef, service); RangerTagDef tagDef = ctx.getNextTagDef(); if (tagDef != null) { ret.put(tagDef.getId(), tagDef); } } } } return ret; } } private class TagRetrieverTagContext { final XXService service; final ListIterator<XXTag> iterTag; final ListIterator<XXTagAttribute> iterTagAttribute; TagRetrieverTagContext(XXService xService) { Long serviceId = xService == null ? null : xService.getId(); List<XXTag> xTags = filterForServicePlugin ? daoMgr.getXXTag().findForServicePlugin(serviceId) : daoMgr.getXXTag().findByServiceId(serviceId); List<XXTagAttribute> xTagAttributes = filterForServicePlugin ? daoMgr.getXXTagAttribute().findForServicePlugin(serviceId) : daoMgr.getXXTagAttribute().findByServiceId(serviceId); this.service = xService; this.iterTag = xTags.listIterator(); this.iterTagAttribute = xTagAttributes.listIterator(); } TagRetrieverTagContext(XXTag xTag, XXService xService) { Long tagId = xTag == null ? null : xTag.getId(); List<XXTag> xTags = asList(xTag); List<XXTagAttribute> xTagAttributes = daoMgr.getXXTagAttribute().findByTagId(tagId); this.service = xService; this.iterTag = xTags.listIterator(); this.iterTagAttribute = xTagAttributes.listIterator(); } Map<Long, RangerTag> getAllTags() { Map<Long, RangerTag> ret = new HashMap<Long, RangerTag>(); while (iterTag.hasNext()) { RangerTag tag = getNextTag(); if (tag != null) { ret.put(tag.getId(), tag); } } if (!hasProcessedAllTags()) { LOG.warn("getAllTags(): perhaps one or more tags got updated during retrieval. Using fallback ... "); ret = getTagsBySecondary(); } return ret; } RangerTag getNextTag() { RangerTag ret = null; if (iterTag.hasNext()) { XXTag xTag = iterTag.next(); if (xTag != null) { ret = new RangerTag(); ret.setId(xTag.getId()); ret.setGuid(xTag.getGuid()); ret.setOwner(xTag.getOwner()); ret.setCreatedBy(lookupCache.getUserScreenName(xTag.getAddedByUserId())); ret.setUpdatedBy(lookupCache.getUserScreenName(xTag.getUpdatedByUserId())); ret.setCreateTime(xTag.getCreateTime()); ret.setUpdateTime(xTag.getUpdateTime()); ret.setVersion(xTag.getVersion()); Map<Long, RangerTagDef> tagDefs = getTagDefs(); if (tagDefs != null) { RangerTagDef tagDef = tagDefs.get(xTag.getType()); if (tagDef != null) { ret.setType(tagDef.getName()); } } getTagAttributes(ret); } } return ret; } void getTagAttributes(RangerTag tag) { while (iterTagAttribute.hasNext()) { XXTagAttribute xTagAttribute = iterTagAttribute.next(); if (xTagAttribute.getTagId().equals(tag.getId())) { String attributeName = xTagAttribute.getName(); String attributeValue = xTagAttribute.getValue(); tag.getAttributes().put(attributeName, attributeValue); } else if (xTagAttribute.getTagId().compareTo(tag.getId()) > 0) { if (iterTagAttribute.hasPrevious()) { iterTagAttribute.previous(); } break; } } } boolean hasProcessedAllTags() { boolean moreToProcess = iterTagAttribute.hasNext(); return !moreToProcess; } Map<Long, RangerTag> getTagsBySecondary() { Map<Long, RangerTag> ret = null; if (service != null) { List<XXTag> xTags = daoMgr.getXXTag().findByServiceId(service.getId()); if (CollectionUtils.isNotEmpty(xTags)) { ret = new HashMap<Long, RangerTag>(xTags.size()); for (XXTag xTag : xTags) { TagRetrieverTagContext ctx = new TagRetrieverTagContext(xTag, service); RangerTag tag = ctx.getNextTag(); if (tag != null) { ret.put(tag.getId(), tag); } } } } return ret; } } }