/* * 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.patch; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.ranger.biz.RangerBizUtil; import org.apache.ranger.biz.ServiceDBStore; import org.apache.ranger.common.AppConstants; import org.apache.ranger.common.JSONUtil; import org.apache.ranger.common.RangerCommonEnums; import org.apache.ranger.common.SearchCriteria; import org.apache.ranger.common.ServiceUtil; import org.apache.ranger.common.StringUtil; import org.apache.ranger.db.RangerDaoManager; import org.apache.ranger.entity.XXAsset; import org.apache.ranger.entity.XXAuditMap; import org.apache.ranger.entity.XXGroup; import org.apache.ranger.entity.XXPolicy; import org.apache.ranger.entity.XXPolicyConditionDef; import org.apache.ranger.entity.XXPortalUser; import org.apache.ranger.entity.XXResource; import org.apache.ranger.entity.XXServiceConfigDef; import org.apache.ranger.entity.XXServiceDef; import org.apache.ranger.entity.XXUser; import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.model.RangerService; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess; import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource; import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; import org.apache.ranger.service.RangerPolicyService; import org.apache.ranger.service.XPermMapService; import org.apache.ranger.service.XPolicyService; import org.apache.ranger.util.CLIUtil; import org.apache.ranger.view.VXPermMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class PatchMigration_J10002 extends BaseLoader { private static final Logger logger = Logger.getLogger(PatchMigration_J10002.class); @Autowired RangerDaoManager daoMgr; @Autowired ServiceDBStore svcDBStore; @Autowired JSONUtil jsonUtil; @Autowired RangerPolicyService policyService; @Autowired StringUtil stringUtil; @Autowired XPolicyService xPolService; @Autowired XPermMapService xPermMapService; @Autowired RangerBizUtil bizUtil; private static int policyCounter = 0; private static int serviceCounter = 0; static Set<String> unsupportedLegacyPermTypes = new HashSet<String>(); static { unsupportedLegacyPermTypes.add("Unknown"); unsupportedLegacyPermTypes.add("Reset"); unsupportedLegacyPermTypes.add("Obfuscate"); unsupportedLegacyPermTypes.add("Mask"); } public static void main(String[] args) { logger.info("main()"); try { PatchMigration_J10002 loader = (PatchMigration_J10002) CLIUtil.getBean(PatchMigration_J10002.class); loader.init(); while (loader.isMoreToProcess()) { loader.load(); } logger.info("Load complete. Exiting!!!"); System.exit(0); } catch (Exception e) { logger.error("Error loading", e); System.exit(1); } } @Override public void init() throws Exception { // Do Nothing } @Override public void execLoad() { logger.info("==> MigrationPatch.execLoad()"); try { migrateServicesToNewSchema(); migratePoliciesToNewSchema(); updateSequences(); } catch (Exception e) { logger.error("Error whille migrating data.", e); } logger.info("<== MigrationPatch.execLoad()"); } @Override public void printStats() { logger.info("Total Number of migrated repositories/services: " + serviceCounter); logger.info("Total Number of migrated resources/policies: " + policyCounter); } public void migrateServicesToNewSchema() throws Exception { logger.info("==> MigrationPatch.migrateServicesToNewSchema()"); try { List<XXAsset> repoList = daoMgr.getXXAsset().getAll(); if (repoList.isEmpty()) { return; } if (!repoList.isEmpty()) { EmbeddedServiceDefsUtil.instance().init(svcDBStore); } svcDBStore.setPopulateExistingBaseFields(true); for (XXAsset xAsset : repoList) { if (xAsset.getActiveStatus() == AppConstants.STATUS_DELETED) { continue; } RangerService existing = svcDBStore.getServiceByName(xAsset.getName()); if (existing != null) { logger.info("Repository/Service already exists. Ignoring migration of repo: " + xAsset.getName()); continue; } RangerService service = new RangerService(); service = mapXAssetToService(service, xAsset); service = svcDBStore.createService(service); serviceCounter++; logger.info("New Service created. ServiceName: " + service.getName()); } svcDBStore.setPopulateExistingBaseFields(false); } catch (Exception e) { throw new Exception("Error while migrating data to new Plugin Schema.", e); } logger.info("<== MigrationPatch.migrateServicesToNewSchema()"); } public void migratePoliciesToNewSchema() throws Exception { logger.info("==> MigrationPatch.migratePoliciesToNewSchema()"); try { List<XXResource> resList = daoMgr.getXXResource().getAll(); if (resList.isEmpty()) { return; } svcDBStore.setPopulateExistingBaseFields(true); for (XXResource xRes : resList) { if (xRes.getResourceStatus() == AppConstants.STATUS_DELETED) { continue; } XXAsset xAsset = daoMgr.getXXAsset().getById(xRes.getAssetId()); if (xAsset == null) { logger.error("No Repository found for policyName: " + xRes.getPolicyName()); continue; } RangerService service = svcDBStore.getServiceByName(xAsset.getName()); if (service == null) { logger.error("No Service found for policy. Ignoring migration of such policy, policyName: " + xRes.getPolicyName()); continue; } XXPolicy existing = daoMgr.getXXPolicy().findByNameAndServiceId(xRes.getPolicyName(), service.getId()); if (existing != null) { logger.info("Policy already exists. Ignoring migration of policy: " + existing.getName()); continue; } RangerPolicy policy = new RangerPolicy(); policy = mapXResourceToPolicy(policy, xRes, service); if(policy != null) { policy = svcDBStore.createPolicy(policy); policyCounter++; logger.info("New policy created. policyName: " + policy.getName()); } } svcDBStore.setPopulateExistingBaseFields(false); } catch (Exception e) { throw new Exception("Error while migrating data to new Plugin Schema.", e); } logger.info("<== MigrationPatch.migratePoliciesToNewSchema()"); } private RangerService mapXAssetToService(RangerService service, XXAsset xAsset) throws Exception { String type = ""; String name = xAsset.getName(); String description = xAsset.getDescription(); Map<String, String> configs = null; int typeInt = xAsset.getAssetType(); XXServiceDef serviceDef = daoMgr.getXXServiceDef().findByName(AppConstants.getLabelFor_AssetType(typeInt).toLowerCase()); if (serviceDef == null) { throw new Exception("No ServiceDefinition found for repository: " + name); } type = serviceDef.getName(); configs = jsonUtil.jsonToMap(xAsset.getConfig()); List<XXServiceConfigDef> mandatoryConfigs = daoMgr.getXXServiceConfigDef().findByServiceDefName(type); for (XXServiceConfigDef serviceConf : mandatoryConfigs) { if (serviceConf.getIsMandatory()) { if (!stringUtil.isEmpty(configs.get(serviceConf.getName()))) { continue; } String dataType = serviceConf.getType(); String defaultValue = serviceConf.getDefaultvalue(); if (stringUtil.isEmpty(defaultValue)) { defaultValue = getDefaultValueForDataType(dataType); } configs.put(serviceConf.getName(), defaultValue); } } service.setType(type); service.setName(name); service.setDescription(description); service.setConfigs(configs); service.setCreateTime(xAsset.getCreateTime()); service.setUpdateTime(xAsset.getUpdateTime()); XXPortalUser createdByUser = daoMgr.getXXPortalUser().getById(xAsset.getAddedByUserId()); XXPortalUser updByUser = daoMgr.getXXPortalUser().getById(xAsset.getUpdatedByUserId()); if (createdByUser != null) { service.setCreatedBy(createdByUser.getLoginId()); } if (updByUser != null) { service.setUpdatedBy(updByUser.getLoginId()); } service.setId(xAsset.getId()); return service; } private String getDefaultValueForDataType(String dataType) { String defaultValue = ""; switch (dataType) { case "int": defaultValue = "0"; break; case "string": defaultValue = "unknown"; break; case "bool": defaultValue = "false"; break; case "enum": defaultValue = "0"; break; case "password": defaultValue = "password"; break; default: break; } return defaultValue; } private RangerPolicy mapXResourceToPolicy(RangerPolicy policy, XXResource xRes, RangerService service) { String serviceName = service.getName(); String serviceType = service.getType(); String name = xRes.getPolicyName(); String description = xRes.getDescription(); Boolean isAuditEnabled = true; Boolean isEnabled = true; Map<String, RangerPolicyResource> resources = new HashMap<String, RangerPolicyResource>(); List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicyItem>(); XXServiceDef svcDef = daoMgr.getXXServiceDef().findByName(serviceType); if(svcDef == null) { logger.error(serviceType + ": service-def not found. Skipping policy '" + name + "'"); return null; } List<XXAuditMap> auditMapList = daoMgr.getXXAuditMap().findByResourceId(xRes.getId()); if (stringUtil.isEmpty(auditMapList)) { isAuditEnabled = false; } if (xRes.getResourceStatus() == AppConstants.STATUS_DISABLED) { isEnabled = false; } Boolean isPathRecursive = xRes.getIsRecursive() == RangerCommonEnums.BOOL_TRUE; Boolean isTableExcludes = xRes.getTableType() == RangerCommonEnums.POLICY_EXCLUSION; Boolean isColumnExcludes = xRes.getColumnType() == RangerCommonEnums.POLICY_EXCLUSION; if (StringUtils.equalsIgnoreCase(serviceType, "hdfs")) { toRangerResourceList(xRes.getName(), "path", Boolean.FALSE, isPathRecursive, resources); } else if (StringUtils.equalsIgnoreCase(serviceType, "hbase")) { toRangerResourceList(xRes.getTables(), "table", isTableExcludes, Boolean.FALSE, resources); toRangerResourceList(xRes.getColumnFamilies(), "column-family", Boolean.FALSE, Boolean.FALSE, resources); toRangerResourceList(xRes.getColumns(), "column", isColumnExcludes, Boolean.FALSE, resources); } else if (StringUtils.equalsIgnoreCase(serviceType, "hive")) { toRangerResourceList(xRes.getDatabases(), "database", Boolean.FALSE, Boolean.FALSE, resources); toRangerResourceList(xRes.getTables(), "table", isTableExcludes, Boolean.FALSE, resources); toRangerResourceList(xRes.getColumns(), "column", isColumnExcludes, Boolean.FALSE, resources); toRangerResourceList(xRes.getUdfs(), "udf", Boolean.FALSE, Boolean.FALSE, resources); } else if (StringUtils.equalsIgnoreCase(serviceType, "knox")) { toRangerResourceList(xRes.getTopologies(), "topology", Boolean.FALSE, Boolean.FALSE, resources); toRangerResourceList(xRes.getServices(), "service", Boolean.FALSE, Boolean.FALSE, resources); } else if (StringUtils.equalsIgnoreCase(serviceType, "storm")) { toRangerResourceList(xRes.getTopologies(), "topology", Boolean.FALSE, Boolean.FALSE, resources); } policyItems = getPolicyItemListForRes(xRes, svcDef); policy.setService(serviceName); policy.setName(name); policy.setDescription(description); policy.setIsAuditEnabled(isAuditEnabled); policy.setIsEnabled(isEnabled); policy.setResources(resources); policy.setPolicyItems(policyItems); policy.setCreateTime(xRes.getCreateTime()); policy.setUpdateTime(xRes.getUpdateTime()); XXPortalUser createdByUser = daoMgr.getXXPortalUser().getById(xRes.getAddedByUserId()); XXPortalUser updByUser = daoMgr.getXXPortalUser().getById(xRes.getUpdatedByUserId()); if (createdByUser != null) { policy.setCreatedBy(createdByUser.getLoginId()); } if (updByUser != null) { policy.setUpdatedBy(updByUser.getLoginId()); } policy.setId(xRes.getId()); return policy; } private Map<String, RangerPolicy.RangerPolicyResource> toRangerResourceList(String resourceString, String resourceType, Boolean isExcludes, Boolean isRecursive, Map<String, RangerPolicy.RangerPolicyResource> resources) { Map<String, RangerPolicy.RangerPolicyResource> ret = resources == null ? new HashMap<String, RangerPolicy.RangerPolicyResource>() : resources; if(StringUtils.isNotBlank(resourceString)) { RangerPolicy.RangerPolicyResource resource = ret.get(resourceType); if(resource == null) { resource = new RangerPolicy.RangerPolicyResource(); resource.setIsExcludes(isExcludes); resource.setIsRecursive(isRecursive); ret.put(resourceType, resource); } Collections.addAll(resource.getValues(), resourceString.split(",")); } return ret; } private List<RangerPolicyItem> getPolicyItemListForRes(XXResource xRes, XXServiceDef svcDef) { List<RangerPolicyItem> policyItems = new ArrayList<RangerPolicyItem>(); SearchCriteria sc = new SearchCriteria(); sc.addParam("resourceId", xRes.getId()); List<VXPermMap> permMapList = xPermMapService.searchXPermMaps(sc).getVXPermMaps(); HashMap<String, List<VXPermMap>> sortedPermMap = new HashMap<String, List<VXPermMap>>(); // re-group the list with permGroup as the key if (permMapList != null) { for(VXPermMap permMap : permMapList) { String permGrp = permMap.getPermGroup(); List<VXPermMap> sortedList = sortedPermMap.get(permGrp); if(sortedList == null) { sortedList = new ArrayList<VXPermMap>(); sortedPermMap.put(permGrp, sortedList); } sortedList.add(permMap); } } for (Entry<String, List<VXPermMap>> entry : sortedPermMap.entrySet()) { List<String> userList = new ArrayList<String>(); List<String> groupList = new ArrayList<String>(); List<RangerPolicyItemAccess> accessList = new ArrayList<RangerPolicyItemAccess>(); String ipAddress = null; RangerPolicy.RangerPolicyItem policyItem = new RangerPolicy.RangerPolicyItem(); for(VXPermMap permMap : entry.getValue()) { if(permMap.getPermFor() == AppConstants.XA_PERM_FOR_USER) { String userName = getUserName(permMap); if (! userList.contains(userName)) { userList.add(userName); } } else if(permMap.getPermFor() == AppConstants.XA_PERM_FOR_GROUP) { String groupName = getGroupName(permMap); if (! groupList.contains(groupName)) { groupList.add(groupName); } } String accessType = ServiceUtil.toAccessType(permMap.getPermType()); if(StringUtils.isBlank(accessType) || unsupportedLegacyPermTypes.contains(accessType)) { logger.info(accessType + ": is not a valid access-type, ignoring accesstype for policy: " + xRes.getPolicyName()); continue; } if(StringUtils.equalsIgnoreCase(accessType, "Admin")) { policyItem.setDelegateAdmin(Boolean.TRUE); if ( svcDef.getId() == EmbeddedServiceDefsUtil.instance().getHBaseServiceDefId()) { addAccessType(accessType, accessList); } } else { addAccessType(accessType, accessList); } ipAddress = permMap.getIpAddress(); } if(CollectionUtils.isEmpty(accessList)) { logger.info("no access specified. ignoring policyItem for policy: " + xRes.getPolicyName()); continue; } if(CollectionUtils.isEmpty(userList) && CollectionUtils.isEmpty(groupList)) { logger.info("no user or group specified. ignoring policyItem for policy: " + xRes.getPolicyName()); continue; } policyItem.setUsers(userList); policyItem.setGroups(groupList); policyItem.setAccesses(accessList); if(ipAddress != null && !ipAddress.isEmpty()) { XXPolicyConditionDef policyCond = daoMgr.getXXPolicyConditionDef().findByServiceDefIdAndName(svcDef.getId(), "ip-range"); if(policyCond != null) { RangerPolicy.RangerPolicyItemCondition ipCondition = new RangerPolicy.RangerPolicyItemCondition("ip-range", Collections.singletonList(ipAddress)); policyItem.getConditions().add(ipCondition); } } policyItems.add(policyItem); } return policyItems; } private void addAccessType(String accessType, List<RangerPolicyItemAccess> accessList) { boolean alreadyExists = false; for(RangerPolicyItemAccess access : accessList) { if(StringUtils.equalsIgnoreCase(accessType, access.getType())) { alreadyExists = true; break; } } if(!alreadyExists) { accessList.add(new RangerPolicyItemAccess(accessType)); } } private void updateSequences() { daoMgr.getXXServiceDef().updateSequence(); daoMgr.getXXService().updateSequence(); daoMgr.getXXPolicy().updateSequence(); } private String getUserName(VXPermMap permMap) { String userName = permMap.getUserName(); if(userName == null || userName.isEmpty()) { Long userId = permMap.getUserId(); if(userId != null) { XXUser xxUser = daoMgr.getXXUser().getById(userId); if(xxUser != null) { userName = xxUser.getName(); } } } return userName; } private String getGroupName(VXPermMap permMap) { String groupName = permMap.getGroupName(); if(groupName == null || groupName.isEmpty()) { Long groupId = permMap.getGroupId(); if(groupId != null) { XXGroup xxGroup = daoMgr.getXXGroup().getById(groupId); if(xxGroup != null) { groupName = xxGroup.getName(); } } } return groupName; } }