diff --git a/dev-support/checks/coverage.sh b/dev-support/checks/coverage.sh index eabf0a4a330..58a8a09bd2f 100755 --- a/dev-support/checks/coverage.sh +++ b/dev-support/checks/coverage.sh @@ -49,6 +49,10 @@ find . -type d -name 'target' -prune -exec find {} -type f \( -name 'ranger-*.ja -or -name '*shim*' -prune \ | xargs -n1 unzip -o -q -d target/coverage-classes +# Multi-release JARs (e.g. BouncyCastle) ship the same classes under +# META-INF/versions/* and at the root; JaCoCo fails with duplicate class names. +rm -rf target/coverage-classes/META-INF/versions || true + # get all source file paths src=$(find . -path '*/src/main/java' -o -path './target' -prune | sed 's/^/--sourcefiles /g' | xargs echo) diff --git a/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java b/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java index face436813e..6c8ede470c4 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/PolicyRefUpdater.java @@ -22,13 +22,14 @@ import org.apache.commons.lang3.StringUtils; import org.apache.ranger.common.RESTErrorUtil; import org.apache.ranger.common.RangerCommonEnums; +import org.apache.ranger.common.db.BaseDao; import org.apache.ranger.common.db.RangerTransactionSynchronizationAdapter; import org.apache.ranger.db.RangerDaoManager; -import org.apache.ranger.entity.XXAccessTypeDef; -import org.apache.ranger.entity.XXDataMaskTypeDef; +import org.apache.ranger.db.XXPolicyRefGroupDao; +import org.apache.ranger.db.XXPolicyRefRoleDao; +import org.apache.ranger.db.XXPolicyRefUserDao; import org.apache.ranger.entity.XXGroup; import org.apache.ranger.entity.XXPolicy; -import org.apache.ranger.entity.XXPolicyConditionDef; import org.apache.ranger.entity.XXPolicyRefAccessType; import org.apache.ranger.entity.XXPolicyRefCondition; import org.apache.ranger.entity.XXPolicyRefDataMaskType; @@ -36,7 +37,6 @@ import org.apache.ranger.entity.XXPolicyRefResource; import org.apache.ranger.entity.XXPolicyRefRole; import org.apache.ranger.entity.XXPolicyRefUser; -import org.apache.ranger.entity.XXResourceDef; import org.apache.ranger.entity.XXRole; import org.apache.ranger.entity.XXServiceDef; import org.apache.ranger.entity.XXUser; @@ -62,7 +62,10 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; import static org.apache.ranger.service.RangerBaseModelService.OPERATION_CREATE_CONTEXT; @@ -121,13 +124,11 @@ public static List> getAllPolicyItems(RangerPol return ret; } - public void createNewPolMappingForRefTable(RangerPolicy policy, XXPolicy xPolicy, XXServiceDef xServiceDef, boolean createPrincipalsIfAbsent) throws Exception { + public void createNewPolMappingForRefTable(RangerPolicy policy, XXPolicy xPolicy, XXServiceDef xServiceDef, boolean createPrincipalsIfAbsent, boolean isCleanupRefTablesNeeded) throws Exception { if (policy == null) { return; } - cleanupRefTables(policy); - final Set resourceNames = policy.getResources().keySet(); final Set roleNames = new HashSet<>(); final Set groupNames = new HashSet<>(); @@ -136,6 +137,7 @@ public void createNewPolMappingForRefTable(RangerPolicy policy, XXPolicy xPolicy final Set conditionTypes = new HashSet<>(); final Set dataMaskTypes = new HashSet<>(); boolean oldBulkMode = RangerBizUtil.isBulkMode(); + final Long policyId = policy.getId(); List rangerPolicyConditions = policy.getConditions(); @@ -175,25 +177,32 @@ public void createNewPolMappingForRefTable(RangerPolicy policy, XXPolicy xPolicy } } - List xPolResources = new ArrayList<>(); + if (isCleanupRefTablesNeeded) { + cleanupRefTablesForUpdate(policyId, userNames, roleNames, groupNames); + } - for (String resource : resourceNames) { - XXResourceDef xResDef = daoMgr.getXXResourceDef().findByNameAndPolicyId(resource, policy.getId()); + if (CollectionUtils.isNotEmpty(resourceNames)) { + List xPolResources = new ArrayList<>(); + Map nameToId = daoMgr.getXXResourceDef().findResourceDefIdsByNameAndPolicyId(resourceNames, policy.getId()); - if (xResDef == null) { - throw new Exception(resource + ": is not a valid resource-type. policy='" + policy.getName() + "' service='" + policy.getService() + "'"); - } + for (String resource : resourceNames) { + Long resourceDefId = nameToId.get(resource); - XXPolicyRefResource xPolRes = new XXPolicyRefResource(); + if (resourceDefId == null) { + throw new Exception(resource + ": is not a valid resource-type. policy='" + policy.getName() + "' service='" + policy.getService() + "'"); + } - xPolRes.setPolicyId(policy.getId()); - xPolRes.setResourceDefId(xResDef.getId()); - xPolRes.setResourceName(resource); + XXPolicyRefResource xPolRes = new XXPolicyRefResource(); - xPolResources.add(xPolRes); - } + xPolRes.setPolicyId(policy.getId()); + xPolRes.setResourceDefId(resourceDefId); + xPolRes.setResourceName(resource); + + xPolResources.add(xPolRes); + } - daoMgr.getXXPolicyRefResource().batchCreate(xPolResources); + batchInsert(xPolResources, daoMgr.getXXPolicyRefResource(), oldBulkMode); + } if (createPrincipalsIfAbsent && !rangerBizUtil.checkAdminAccess()) { LOG.warn("policy={}: createPrincipalIfAbsent=true, but current user does not have admin privileges!", policy.getName()); @@ -201,141 +210,186 @@ public void createNewPolMappingForRefTable(RangerPolicy policy, XXPolicy xPolicy createPrincipalsIfAbsent = false; } - List xPolRoles = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(roleNames)) { + LOG.debug("x_policy_ref_role - New role entries to insert for policy ID {}: {}", policyId, roleNames); - for (String role : roleNames) { - if (StringUtils.isBlank(role)) { - continue; - } + Set filteredRoleNames = roleNames.stream() + .filter(StringUtils::isNotBlank) + .collect(Collectors.toSet()); + + List xPolRoles = new ArrayList<>(); + Map nameToId = daoMgr.getXXRole().getIdsByRoleNames(filteredRoleNames); + + for (String roleName : filteredRoleNames) { + Long roleId = nameToId.get(roleName); + PolicyRoleAssociator associator = new PolicyRoleAssociator(roleName, roleId, xPolicy); - PolicyPrincipalAssociator associator = new PolicyPrincipalAssociator(PRINCIPAL_TYPE.ROLE, role, xPolicy); + if (roleId != null) { + XXPolicyRefRole roleRef = associator.getPolicyRef(); - if (!associator.doAssociate(false)) { - if (createPrincipalsIfAbsent) { + if (roleRef != null) { + xPolRoles.add(roleRef); + } + } else if (createPrincipalsIfAbsent) { rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(associator); } else { VXResponse gjResponse = new VXResponse(); gjResponse.setStatusCode(HttpServletResponse.SC_BAD_REQUEST); - gjResponse.setMsgDesc("Operation denied. Role name: " + role + " specified in policy does not exist in ranger admin."); + gjResponse.setMsgDesc("Operation denied. Role name: " + roleName + " specified in policy does not exist in ranger admin."); throw restErrorUtil.generateRESTException(gjResponse); } } + + batchInsert(xPolRoles, daoMgr.getXXPolicyRefRole(), oldBulkMode); } - RangerBizUtil.setBulkMode(oldBulkMode); + if (CollectionUtils.isNotEmpty(groupNames)) { + LOG.debug("x_policy_ref_group - New group entries to insert for policy ID {}: {}", policyId, groupNames); - daoMgr.getXXPolicyRefRole().batchCreate(xPolRoles); + Set filteredGroupNames = groupNames.stream() + .filter(StringUtils::isNotBlank) + .collect(Collectors.toSet()); - for (String group : groupNames) { - if (StringUtils.isBlank(group)) { - continue; - } + List xPolGroups = new ArrayList<>(); + Map nameToId = daoMgr.getXXGroup().getIdsByGroupNames(filteredGroupNames); + + for (String groupName : filteredGroupNames) { + Long groupId = nameToId.get(groupName); + PolicyGroupAssociator associator = new PolicyGroupAssociator(groupName, groupId, xPolicy); - PolicyPrincipalAssociator associator = new PolicyPrincipalAssociator(PRINCIPAL_TYPE.GROUP, group, xPolicy); + if (groupId != null) { + XXPolicyRefGroup groupRef = associator.getPolicyRef(); - if (!associator.doAssociate(false)) { - if (createPrincipalsIfAbsent) { + if (groupRef != null) { + xPolGroups.add(groupRef); + } + } else if (createPrincipalsIfAbsent) { rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(associator); } else { VXResponse gjResponse = new VXResponse(); gjResponse.setStatusCode(HttpServletResponse.SC_BAD_REQUEST); - gjResponse.setMsgDesc("Operation denied. Group name: " + group + " specified in policy does not exist in ranger admin."); + gjResponse.setMsgDesc("Operation denied. Group name: " + groupName + " specified in policy does not exist in ranger admin."); throw restErrorUtil.generateRESTException(gjResponse); } } + + batchInsert(xPolGroups, daoMgr.getXXPolicyRefGroup(), oldBulkMode); } - for (String user : userNames) { - if (StringUtils.isBlank(user)) { - continue; - } + if (CollectionUtils.isNotEmpty(userNames)) { + LOG.debug("x_policy_ref_user - New user entries to insert for policy ID {}: {}", policyId, userNames); + + Set filteredUserNames = userNames.stream() + .filter(StringUtils::isNotBlank) + .collect(Collectors.toSet()); + + List xPolUsers = new ArrayList<>(); + Map nameToId = daoMgr.getXXUser().getIdsByUserNames(filteredUserNames); - PolicyPrincipalAssociator associator = new PolicyPrincipalAssociator(PRINCIPAL_TYPE.USER, user, xPolicy); + for (String userName : filteredUserNames) { + Long userId = nameToId.get(userName); + PolicyUserAssociator associator = new PolicyUserAssociator(userName, userId, xPolicy); - if (!associator.doAssociate(false)) { - if (createPrincipalsIfAbsent) { + if (userId != null) { + XXPolicyRefUser userRef = associator.getPolicyRef(); + + if (userRef != null) { + xPolUsers.add(userRef); + } + } else if (createPrincipalsIfAbsent) { rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(associator); } else { VXResponse gjResponse = new VXResponse(); gjResponse.setStatusCode(HttpServletResponse.SC_BAD_REQUEST); - gjResponse.setMsgDesc("Operation denied. User name: " + user + " specified in policy does not exist in ranger admin."); + gjResponse.setMsgDesc("Operation denied. User name: " + userName + " specified in policy does not exist in ranger admin."); throw restErrorUtil.generateRESTException(gjResponse); } } - } - List xPolAccesses = new ArrayList<>(); + batchInsert(xPolUsers, daoMgr.getXXPolicyRefUser(), oldBulkMode); + } // ignore built-in access-types while creating ref-table entries accessTypes.removeAll(ServiceDefUtil.ACCESS_TYPE_MARKERS); - for (String accessType : accessTypes) { - XXAccessTypeDef xAccTypeDef = daoMgr.getXXAccessTypeDef().findByNameAndServiceId(accessType, xPolicy.getService()); + if (CollectionUtils.isNotEmpty(accessTypes)) { + List xPolAccesses = new ArrayList<>(); + Map nameToId = daoMgr.getXXAccessTypeDef().findAccessTypeDefIdsByNamesAndServiceId(accessTypes, xPolicy.getService()); - if (xAccTypeDef == null) { - throw new Exception(accessType + ": is not a valid access-type. policy='" + policy.getName() + "' service='" + policy.getService() + "'"); - } + for (String accessType : accessTypes) { + Long accessDefId = nameToId.get(accessType); - XXPolicyRefAccessType xPolAccess = new XXPolicyRefAccessType(); + if (accessDefId == null) { + throw new Exception(accessType + ": is not a valid access-type. policy='" + policy.getName() + "' service='" + policy.getService() + "'"); + } - xPolAccess.setPolicyId(policy.getId()); - xPolAccess.setAccessDefId(xAccTypeDef.getId()); - xPolAccess.setAccessTypeName(accessType); + XXPolicyRefAccessType xPolAccess = new XXPolicyRefAccessType(); - xPolAccesses.add(xPolAccess); + xPolAccess.setPolicyId(policy.getId()); + xPolAccess.setAccessDefId(accessDefId); + xPolAccess.setAccessTypeName(accessType); + + xPolAccesses.add(xPolAccess); + } + + batchInsert(xPolAccesses, daoMgr.getXXPolicyRefAccessType(), oldBulkMode); } - daoMgr.getXXPolicyRefAccessType().batchCreate(xPolAccesses); + if (CollectionUtils.isNotEmpty(conditionTypes)) { + List xPolConds = new ArrayList<>(); + Map nameToId = daoMgr.getXXPolicyConditionDef().findConditionDefIdsByServiceDefIdAndNames(xServiceDef.getId(), conditionTypes); - List xPolConds = new ArrayList<>(); + for (String condition : conditionTypes) { + Long conditionDefId = nameToId.get(condition); - for (String condition : conditionTypes) { - XXPolicyConditionDef xPolCondDef = daoMgr.getXXPolicyConditionDef().findByServiceDefIdAndName(xServiceDef.getId(), condition); + if (conditionDefId == null) { + if (StringUtils.equalsIgnoreCase(condition, ServiceDefUtil.IMPLICIT_CONDITION_EXPRESSION_NAME)) { + continue; + } - if (xPolCondDef == null) { - if (StringUtils.equalsIgnoreCase(condition, ServiceDefUtil.IMPLICIT_CONDITION_EXPRESSION_NAME)) { - continue; + throw new Exception(condition + ": is not a valid condition-type. policy='" + xPolicy.getName() + "' service='" + xPolicy.getService() + "'"); } - throw new Exception(condition + ": is not a valid condition-type. policy='" + xPolicy.getName() + "' service='" + xPolicy.getService() + "'"); - } + XXPolicyRefCondition xPolCond = new XXPolicyRefCondition(); - XXPolicyRefCondition xPolCond = new XXPolicyRefCondition(); + xPolCond.setPolicyId(policy.getId()); + xPolCond.setConditionDefId(conditionDefId); + xPolCond.setConditionName(condition); - xPolCond.setPolicyId(policy.getId()); - xPolCond.setConditionDefId(xPolCondDef.getId()); - xPolCond.setConditionName(condition); + xPolConds.add(xPolCond); + } - xPolConds.add(xPolCond); + batchInsert(xPolConds, daoMgr.getXXPolicyRefCondition(), oldBulkMode); } - daoMgr.getXXPolicyRefCondition().batchCreate(xPolConds); + if (CollectionUtils.isNotEmpty(dataMaskTypes)) { + List xxDataMaskInfos = new ArrayList<>(); + Map nameToId = daoMgr.getXXDataMaskTypeDef().findDataMaskTypeDefIdsByNamesAndServiceId(dataMaskTypes, xPolicy.getService()); - List xxDataMaskInfos = new ArrayList<>(); + for (String dataMaskType : dataMaskTypes) { + Long dataMaskDefId = nameToId.get(dataMaskType); - for (String dataMaskType : dataMaskTypes) { - XXDataMaskTypeDef dataMaskDef = daoMgr.getXXDataMaskTypeDef().findByNameAndServiceId(dataMaskType, xPolicy.getService()); + if (dataMaskDefId == null) { + throw new Exception(dataMaskType + ": is not a valid datamask-type. policy='" + policy.getName() + "' service='" + policy.getService() + "'"); + } - if (dataMaskDef == null) { - throw new Exception(dataMaskType + ": is not a valid datamask-type. policy='" + policy.getName() + "' service='" + policy.getService() + "'"); - } + XXPolicyRefDataMaskType xxDataMaskInfo = new XXPolicyRefDataMaskType(); - XXPolicyRefDataMaskType xxDataMaskInfo = new XXPolicyRefDataMaskType(); + xxDataMaskInfo.setPolicyId(policy.getId()); + xxDataMaskInfo.setDataMaskDefId(dataMaskDefId); + xxDataMaskInfo.setDataMaskTypeName(dataMaskType); - xxDataMaskInfo.setPolicyId(policy.getId()); - xxDataMaskInfo.setDataMaskDefId(dataMaskDef.getId()); - xxDataMaskInfo.setDataMaskTypeName(dataMaskType); + xxDataMaskInfos.add(xxDataMaskInfo); + } - xxDataMaskInfos.add(xxDataMaskInfo); + batchInsert(xxDataMaskInfos, daoMgr.getXXPolicyRefDataMaskType(), oldBulkMode); } - - daoMgr.getXXPolicyRefDataMaskType().batchCreate(xxDataMaskInfos); } public Boolean cleanupRefTables(RangerPolicy policy) { @@ -356,201 +410,430 @@ public Boolean cleanupRefTables(RangerPolicy policy) { return true; } + /** + * Cleans up reference tables for a given policy before updating it. + * This includes handling policy reference users, roles, and other + * associated reference entities like resources, groups, access types, + * conditions, and data mask types. + * + * @param policyId ID of the policy being updated. + * @param policyUsers Set of usernames associated with the updated policy. + * @param policyRoles Set of role names associated with the updated policy. + * @param policyGroups Set of group names associated with the updated policy. + * @return true if cleanup was successful. + */ + public Boolean cleanupRefTablesForUpdate(Long policyId, Set policyUsers, Set policyRoles, Set policyGroups) { + cleanupPolicyRefUsers(policyUsers, policyId, daoMgr.getXXPolicyRefUser()); + cleanupPolicyRefRoles(policyRoles, policyId, daoMgr.getXXPolicyRefRole()); + cleanupPolicyRefGroups(policyGroups, policyId, daoMgr.getXXPolicyRefGroup()); + + daoMgr.getXXPolicyRefResource().deleteByPolicyId(policyId); + daoMgr.getXXPolicyRefAccessType().deleteByPolicyId(policyId); + daoMgr.getXXPolicyRefCondition().deleteByPolicyId(policyId); + daoMgr.getXXPolicyRefDataMaskType().deleteByPolicyId(policyId); + + return true; + } + + /** + * Identifies and deletes outdated user references for a given policy, + * and prepares a list of new users that need to be inserted. + * + * @param policyUsers Set of usernames from the new policy. + * @param policyId The ID of the policy. + * @param dao DAO for policy reference users. + */ + public void cleanupPolicyRefUsers(Set policyUsers, Long policyId, XXPolicyRefUserDao dao) { + Map policyUserNameIdMap = dao.findUserNameIdByPolicyId(policyId); + + if (policyUserNameIdMap != null && !policyUserNameIdMap.isEmpty()) { + Set existingPolicyRefUsers = policyUserNameIdMap.keySet(); + Set toDeletePolicyRefUsers = new HashSet<>(existingPolicyRefUsers); + Set commonUsers = new HashSet<>(policyUsers); + + // Identify users present in both new and existing sets + commonUsers.retainAll(toDeletePolicyRefUsers); + + // Identify users to delete (in DB but not in new set) + toDeletePolicyRefUsers.removeAll(commonUsers); + + // Remove already existing users from the new set (they don’t need to be inserted again) + policyUsers.removeAll(commonUsers); + + if (CollectionUtils.isNotEmpty(toDeletePolicyRefUsers)) { + List idsToDelete = toDeletePolicyRefUsers.stream() + .map(policyUserNameIdMap::get) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + LOG.debug("Deleting user IDs from x_policy_ref_user table: {} for policy ID: {}", idsToDelete, policyId); + + dao.deletePolicyRefUserByIds(idsToDelete); + } + } + } + + /** + * Identifies and deletes outdated role references for a given policy, + * and prepares a list of new roles that need to be inserted. + * + * @param policyRoles Set of role names from the new policy. + * @param policyId The ID of the policy. + * @param dao DAO for policy reference roles. + */ + public void cleanupPolicyRefRoles(Set policyRoles, Long policyId, XXPolicyRefRoleDao dao) { + Map policyRoleNameIdMap = dao.findRoleNameIdByPolicyId(policyId); + + if (policyRoleNameIdMap != null && !policyRoleNameIdMap.isEmpty()) { + Set existingPolicyRefRoles = policyRoleNameIdMap.keySet(); + Set toDeletePolicyRefRoles = new HashSet<>(existingPolicyRefRoles); + Set commonRoles = new HashSet<>(policyRoles); + + // Identify roles present in both new and existing sets + commonRoles.retainAll(toDeletePolicyRefRoles); + + // Identify roles to delete (in DB but not in new set) + toDeletePolicyRefRoles.removeAll(commonRoles); + + // Remove already existing roles from the new set (they don’t need to be inserted again) + policyRoles.removeAll(commonRoles); + + if (CollectionUtils.isNotEmpty(toDeletePolicyRefRoles)) { + List idsToDelete = toDeletePolicyRefRoles.stream() + .map(policyRoleNameIdMap::get) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + LOG.debug("Deleting Role IDs from x_policy_ref_role: {} for policy ID: {}", idsToDelete, policyId); + + dao.deletePolicyRefRoleByIds(idsToDelete); + } + } + } + + /** + * Identifies and deletes outdated group references for a given policy, + * and prepares a list of new groups that need to be inserted. + * + * @param policyGroups Set of group names from the new policy. + * @param policyId The ID of the policy. + * @param dao DAO for policy reference groups. + */ + public void cleanupPolicyRefGroups(Set policyGroups, Long policyId, XXPolicyRefGroupDao dao) { + Map policyGroupNameIdMap = dao.findGroupNameByPolicyId(policyId); + + if (policyGroupNameIdMap != null && !policyGroupNameIdMap.isEmpty()) { + Set existingPolicyRefGroups = policyGroupNameIdMap.keySet(); + Set toDeletePolicyRefGroups = new HashSet<>(existingPolicyRefGroups); + Set commonGroups = new HashSet<>(policyGroups); + + // Identify groups present in both new and existing sets + commonGroups.retainAll(toDeletePolicyRefGroups); + + // Identify groups to delete (in DB but not in new set) + toDeletePolicyRefGroups.removeAll(commonGroups); + + // Remove already existing groups from the new set (they don’t need to be inserted again) + policyGroups.removeAll(commonGroups); + + if (CollectionUtils.isNotEmpty(toDeletePolicyRefGroups)) { + List idsToDelete = toDeletePolicyRefGroups.stream() + .map(policyGroupNameIdMap::get) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + LOG.debug("Deleting Group IDs from x_policy_ref_group: {} for policy ID: {}", idsToDelete, policyId); + + dao.deletePolicyRefGroupByIds(idsToDelete); + } + } + } + public enum PRINCIPAL_TYPE { USER, GROUP, ROLE } - private class PolicyPrincipalAssociator implements Runnable { - final PRINCIPAL_TYPE type; - final String name; - final XXPolicy xPolicy; + private boolean doesPolicyExist(XXPolicy policy) { + return daoMgr.getXXPolicy().getById(policy.getId()) != null; + } + + private class PolicyRoleAssociator implements Runnable { + private final String name; + private final Long roleId; + private final XXPolicy xPolicy; - public PolicyPrincipalAssociator(PRINCIPAL_TYPE type, String name, XXPolicy xPolicy) { - this.type = type; + PolicyRoleAssociator(String name, Long roleId, XXPolicy xPolicy) { this.name = name; + this.roleId = roleId; this.xPolicy = xPolicy; } + public XXPolicyRefRole getPolicyRef() { + Long id = resolveRoleId(false); + + if (id != null && doesPolicyExist(xPolicy)) { + XXPolicyRefRole xPolRole = new XXPolicyRefRole(); + + xPolRole.setPolicyId(xPolicy.getId()); + xPolRole.setRoleId(id); + xPolRole.setRoleName(name); + + return xPolRole; + } + + return null; + } + + public void createPolicyRef(Long id) { + if (doesPolicyExist(xPolicy)) { + XXPolicyRefRole xPolRole = new XXPolicyRefRole(); + + xPolRole.setPolicyId(xPolicy.getId()); + xPolRole.setRoleId(id); + xPolRole.setRoleName(name); + + daoMgr.getXXPolicyRefRole().create(xPolRole); + } else { + LOG.info("Policy with id ={} does not exist, skipping policy association!", xPolicy.getId()); + } + } + @Override public void run() { - if (doAssociate(true)) { - LOG.debug("Associated {}:{} with policy id:[{}]", type.name(), name, xPolicy.getId()); + Long id = resolveRoleId(true); + + if (id != null) { + createPolicyRef(id); + + LOG.debug("Associated ROLE:{} with policy id:[{}]", name, xPolicy.getId()); } else { - throw new RuntimeException("Failed to associate " + type.name() + ":" + name + " with policy id:[" + xPolicy.getId() + "]"); + throw new RuntimeException("Failed to associate ROLE:" + name + " with policy id:[" + xPolicy.getId() + "]"); } } - boolean doAssociate(boolean isAdmin) { - LOG.debug("===> PolicyPrincipalAssociator.doAssociate({})", isAdmin); + private Long resolveRoleId(boolean createIfAbsent) { + Long ret = roleId; - final boolean ret; + if (ret == null) { + XXRole xRole = daoMgr.getXXRole().findByRoleName(name); - Long id = createOrGetPrincipal(isAdmin); + if (xRole != null) { + ret = xRole.getId(); + } else if (createIfAbsent) { + RangerBizUtil.setBulkMode(false); + + ret = createRole(); + } + } + + return ret; + } + + private Long createRole() { + LOG.warn("Role specified in policy does not exist in ranger admin, creating new role, name = {}", name); + + try { + RangerRole rRole = new RangerRole(name, null, null, null, null); + RangerRole createdRole = roleStore.createRole(rRole, false); + + return createdRole.getId(); + } catch (Exception e) { + return null; + } + } + } + + private class PolicyGroupAssociator implements Runnable { + private final String name; + private final Long groupId; + private final XXPolicy xPolicy; + + PolicyGroupAssociator(String name, Long groupId, XXPolicy xPolicy) { + this.name = name; + this.groupId = groupId; + this.xPolicy = xPolicy; + } + + public XXPolicyRefGroup getPolicyRef() { + Long id = resolveGroupId(false); + + if (id != null && doesPolicyExist(xPolicy)) { + XXPolicyRefGroup xPolGroup = new XXPolicyRefGroup(); + + xPolGroup.setPolicyId(xPolicy.getId()); + xPolGroup.setGroupId(id); + xPolGroup.setGroupName(name); + + return xPolGroup; + } + + return null; + } + + public void createPolicyRef(Long id) { + if (doesPolicyExist(xPolicy)) { + XXPolicyRefGroup xPolGroup = new XXPolicyRefGroup(); + + xPolGroup.setPolicyId(xPolicy.getId()); + xPolGroup.setGroupId(id); + xPolGroup.setGroupName(name); + + daoMgr.getXXPolicyRefGroup().create(xPolGroup); + } else { + LOG.info("Policy with id ={} does not exist, skipping policy association!", xPolicy.getId()); + } + } + + @Override + public void run() { + Long id = resolveGroupId(true); if (id != null) { - // associate with policy - createPolicyAssociation(id, name); + createPolicyRef(id); - ret = true; + LOG.debug("Associated GROUP:{} with policy id:[{}]", name, xPolicy.getId()); } else { - ret = false; + throw new RuntimeException("Failed to associate GROUP:" + name + " with policy id:[" + xPolicy.getId() + "]"); } + } + + private Long resolveGroupId(boolean createIfAbsent) { + Long ret = groupId; + + if (ret == null) { + XXGroup xGroup = daoMgr.getXXGroup().findByGroupName(name); - LOG.debug("<=== PolicyPrincipalAssociator.doAssociate({}) : {}", isAdmin, ret); + if (xGroup != null) { + ret = xGroup.getId(); + } else if (createIfAbsent) { + ret = createGroup(); + } + } return ret; } - private Long createOrGetPrincipal(final boolean createIfAbsent) { - LOG.debug("===> PolicyPrincipalAssociator.createOrGetPrincipal({})", createIfAbsent); + private Long createGroup() { + LOG.warn("Group specified in policy does not exist in ranger admin, creating new group, name = {}", name); - Long ret = null; + VXGroup vxGroup = new VXGroup(); - switch (type) { - case USER: { - XXUser xUser = daoMgr.getXXUser().findByUserName(name); + vxGroup.setName(name); + vxGroup.setDescription(name); + vxGroup.setGroupSource(RangerCommonEnums.GROUP_EXTERNAL); - if (xUser != null) { - ret = xUser.getId(); - } else { - if (createIfAbsent) { - ret = createPrincipal(name); - } - } - } - break; - case GROUP: { - XXGroup xGroup = daoMgr.getXXGroup().findByGroupName(name); - - if (xGroup != null) { - ret = xGroup.getId(); - } else { - if (createIfAbsent) { - ret = createPrincipal(name); - } - } - } - break; - case ROLE: { - XXRole xRole = daoMgr.getXXRole().findByRoleName(name); - - if (xRole != null) { - ret = xRole.getId(); - } else { - if (createIfAbsent) { - RangerBizUtil.setBulkMode(false); - ret = createPrincipal(name); - } - } - } - break; - default: - break; + VXGroup vXGroup = xGroupService.createXGroupWithOutLogin(vxGroup); + + if (vXGroup != null) { + xGroupService.createTransactionLog(vXGroup, null, OPERATION_CREATE_CONTEXT, xPolicy.getAddedByUserId()); + + return vXGroup.getId(); } - LOG.debug("<=== PolicyPrincipalAssociator.createOrGetPrincipal({}) : {}", createIfAbsent, ret); + return null; + } + } - return ret; + private class PolicyUserAssociator implements Runnable { + private final String name; + private final Long userId; + private final XXPolicy xPolicy; + + PolicyUserAssociator(String name, Long userId, XXPolicy xPolicy) { + this.name = name; + this.userId = userId; + this.xPolicy = xPolicy; } - private Long createPrincipal(String user) { - LOG.warn("User specified in policy does not exist in ranger admin, creating new user, Type: {}, name = {}", type.name(), user); + public XXPolicyRefUser getPolicyRef() { + Long id = resolveUserId(false); - LOG.debug("===> PolicyPrincipalAssociator.createPrincipal(type={}, name={})", type.name(), name); + if (id != null && doesPolicyExist(xPolicy)) { + XXPolicyRefUser xPolUser = new XXPolicyRefUser(); - Long ret = null; + xPolUser.setPolicyId(xPolicy.getId()); + xPolUser.setUserId(id); + xPolUser.setUserName(name); - switch (type) { - case USER: { - // Create External user - VXUser vXUser = xUserMgr.createServiceConfigUser(name); - if (vXUser != null) { - XXUser xUser = daoMgr.getXXUser().findByUserName(name); + return xPolUser; + } - if (xUser == null) { - LOG.error("No User created!! Irrecoverable error! [{}]", name); - } else { - ret = xUser.getId(); - } - } else { - LOG.warn("serviceConfigUser:[{}] creation failed. This may be a transient/spurious condition that may correct itself when transaction is committed", name); - } - } - break; - case GROUP: { - // Create group - VXGroup vxGroup = new VXGroup(); + return null; + } - vxGroup.setName(name); - vxGroup.setDescription(name); - vxGroup.setGroupSource(RangerCommonEnums.GROUP_EXTERNAL); + public void createPolicyRef(Long id) { + if (doesPolicyExist(xPolicy)) { + XXPolicyRefUser xPolUser = new XXPolicyRefUser(); - VXGroup vXGroup = xGroupService.createXGroupWithOutLogin(vxGroup); + xPolUser.setPolicyId(xPolicy.getId()); + xPolUser.setUserId(id); + xPolUser.setUserName(name); - if (vXGroup != null) { - xGroupService.createTransactionLog(vXGroup, null, OPERATION_CREATE_CONTEXT, xPolicy.getAddedByUserId()); + daoMgr.getXXPolicyRefUser().create(xPolUser); + } else { + LOG.info("Policy with id ={} does not exist, skipping policy association!", xPolicy.getId()); + } + } - ret = vXGroup.getId(); - } - } - break; - case ROLE: { - try { - RangerRole rRole = new RangerRole(name, null, null, null, null); - RangerRole createdRole = roleStore.createRole(rRole, false); - - ret = createdRole.getId(); - } catch (Exception e) { - // Ignore - } - } - break; - default: - break; + @Override + public void run() { + Long id = resolveUserId(true); + + if (id != null) { + createPolicyRef(id); + + LOG.debug("Associated USER:{} with policy id:[{}]", name, xPolicy.getId()); + } else { + throw new RuntimeException("Failed to associate USER:" + name + " with policy id:[" + xPolicy.getId() + "]"); } + } + + private Long resolveUserId(boolean createIfAbsent) { + Long ret = userId; - LOG.debug("<=== PolicyPrincipalAssociator.createPrincipal(type={}, name={}) : {}", type.name(), name, ret); + if (ret == null) { + XXUser xUser = daoMgr.getXXUser().findByUserName(name); + + if (xUser != null) { + ret = xUser.getId(); + } else if (createIfAbsent) { + return createUser(); + } + } return ret; } - private void createPolicyAssociation(Long id, String name) { - LOG.debug("===> PolicyPrincipalAssociator.createPolicyAssociation(policyId={}, type={}, name={}, id={})", xPolicy.getId(), type.name(), name, id); + private Long createUser() { + LOG.warn("User specified in policy does not exist in ranger admin, creating new user, name = {}", name); - switch (type) { - case USER: { - XXPolicyRefUser xPolUser = new XXPolicyRefUser(); + VXUser vXUser = xUserMgr.createServiceConfigUser(name); - xPolUser.setPolicyId(xPolicy.getId()); - xPolUser.setUserId(id); - xPolUser.setUserName(name); + if (vXUser != null) { + XXUser xUser = daoMgr.getXXUser().findByUserName(name); - daoMgr.getXXPolicyRefUser().create(xPolUser); + if (xUser == null) { + LOG.error("No User created!! Irrecoverable error! [{}]", name); + } else { + return xUser.getId(); } - break; - case GROUP: { - XXPolicyRefGroup xPolGroup = new XXPolicyRefGroup(); + } else { + LOG.warn("serviceConfigUser:[{}] creation failed. This may be a transient/spurious condition that may correct itself when transaction is committed", name); + } - xPolGroup.setPolicyId(xPolicy.getId()); - xPolGroup.setGroupId(id); - xPolGroup.setGroupName(name); + return null; + } + } - daoMgr.getXXPolicyRefGroup().create(xPolGroup); - } - break; - case ROLE: { - XXPolicyRefRole xPolRole = new XXPolicyRefRole(); + private void batchInsert(List entities, BaseDao dao, boolean oldBulkMode) { + if (CollectionUtils.isNotEmpty(entities)) { + long startTimeMs = System.currentTimeMillis(); - xPolRole.setPolicyId(xPolicy.getId()); - xPolRole.setRoleId(id); - xPolRole.setRoleName(name); + LOG.debug("Batch insert started for create/update {} with {} records.", dao.getClass().getSimpleName(), entities.size()); - daoMgr.getXXPolicyRefRole().create(xPolRole); - } - break; - default: - break; - } + RangerBizUtil.setBulkMode(false); + dao.batchCreate(entities); + RangerBizUtil.setBulkMode(oldBulkMode); - LOG.debug("<=== PolicyPrincipalAssociator.createPolicyAssociation(policyId={}, type={}, name={}, id={})", xPolicy.getId(), type.name(), name, id); + LOG.debug("Batch insert completed for create/update {} with {} records in {} ms.", dao.getClass().getSimpleName(), entities.size(), (System.currentTimeMillis() - startTimeMs)); } } } diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java index cf6c536c94d..ce0b8129365 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java @@ -1472,11 +1472,9 @@ public RangerPolicy updatePolicy(RangerPolicy policy) throws Exception { XXPolicy newUpdPolicy = daoMgr.getXXPolicy().getById(policy.getId()); - policyRefUpdater.cleanupRefTables(policy); - deleteExistingPolicyLabel(policy); - policyRefUpdater.createNewPolMappingForRefTable(policy, newUpdPolicy, xServiceDef, bizUtil.getCreatePrincipalsIfAbsent()); + policyRefUpdater.createNewPolMappingForRefTable(policy, newUpdPolicy, xServiceDef, bizUtil.getCreatePrincipalsIfAbsent(), true); createOrMapLabels(newUpdPolicy, uniquePolicyLabels); @@ -2290,7 +2288,7 @@ public RangerPolicy createPolicy(RangerPolicy policy, boolean createPrincipalsIf XXPolicy xCreatedPolicy = daoMgr.getXXPolicy().getById(policy.getId()); - policyRefUpdater.createNewPolMappingForRefTable(policy, xCreatedPolicy, xServiceDef, createPrincipalsIfAbsent); + policyRefUpdater.createNewPolMappingForRefTable(policy, xCreatedPolicy, xServiceDef, createPrincipalsIfAbsent, false); createOrMapLabels(xCreatedPolicy, uniquePolicyLabels); diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXAccessTypeDefDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXAccessTypeDefDao.java index b5244e889eb..b7c44ee9a7e 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXAccessTypeDefDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXAccessTypeDefDao.java @@ -17,18 +17,27 @@ package org.apache.ranger.db; +import org.apache.commons.collections.CollectionUtils; import org.apache.ranger.common.db.BaseDao; import org.apache.ranger.entity.XXAccessTypeDef; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.persistence.NoResultException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; @Service public class XXAccessTypeDefDao extends BaseDao { + private static final Logger logger = LoggerFactory.getLogger(XXAccessTypeDefDao.class); + public XXAccessTypeDefDao(RangerDaoManagerBase daoManager) { super(daoManager); } @@ -76,4 +85,22 @@ public List getNamesByServiceName(String serviceName) { return ret != null ? ret : Collections.emptyList(); } + + public Map findAccessTypeDefIdsByNamesAndServiceId(Set names, Long serviceId) { + if (serviceId != null && CollectionUtils.isNotEmpty(names)) { + try { + Collection result = getEntityManager() + .createNamedQuery("XXAccessTypeDef.findAccessTypeDefIdsByNamesAndServiceId", Object[].class) + .setParameter("names", names) + .setParameter("serviceId", serviceId) + .getResultList(); + + return result.stream().collect(Collectors.toMap(object -> (String) object[1], object -> (Long) object[0], (a, b) -> a)); + } catch (NoResultException e) { + logger.debug(e.getMessage()); + } + } + + return Collections.emptyMap(); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java index 5deab9cc703..10951113730 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXDataMaskTypeDefDao.java @@ -17,18 +17,27 @@ package org.apache.ranger.db; +import org.apache.commons.collections.CollectionUtils; import org.apache.ranger.common.db.BaseDao; import org.apache.ranger.entity.XXDataMaskTypeDef; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.persistence.NoResultException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; @Service public class XXDataMaskTypeDefDao extends BaseDao { + private static final Logger logger = LoggerFactory.getLogger(XXDataMaskTypeDefDao.class); + public XXDataMaskTypeDefDao(RangerDaoManagerBase daoManager) { super(daoManager); } @@ -76,4 +85,22 @@ public List getNamesByServiceName(String serviceName) { return ret != null ? ret : Collections.emptyList(); } + + public Map findDataMaskTypeDefIdsByNamesAndServiceId(Set names, Long serviceId) { + if (serviceId != null && CollectionUtils.isNotEmpty(names)) { + try { + Collection result = getEntityManager() + .createNamedQuery("XXDataMaskTypeDef.findDataMaskTypeDefIdsByNamesAndServiceId", Object[].class) + .setParameter("names", names) + .setParameter("serviceId", serviceId) + .getResultList(); + + return result.stream().collect(Collectors.toMap(object -> (String) object[1], object -> (Long) object[0], (a, b) -> a)); + } catch (NoResultException e) { + logger.debug(e.getMessage()); + } + } + + return Collections.emptyMap(); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGroupDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGroupDao.java index 68c6ceb45e8..2b765a3307d 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXGroupDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGroupDao.java @@ -19,6 +19,7 @@ package org.apache.ranger.db; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.ranger.authorization.utils.JsonUtils; import org.apache.ranger.common.RangerCommonEnums; @@ -32,9 +33,12 @@ import javax.persistence.NoResultException; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD__IS_INTERNAL; import static org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD__SYNC_SOURCE; @@ -114,6 +118,23 @@ public List getAllGroupsInfo() { return ret; } + public Map getIdsByGroupNames(Collection groupNames) { + if (CollectionUtils.isNotEmpty(groupNames)) { + try { + Collection result = getEntityManager() + .createNamedQuery("XXGroup.getIdsByGroupNames", Object[].class) + .setParameter("names", groupNames) + .getResultList(); + + return result.stream().collect(Collectors.toMap(object -> (String) (object[1]), object -> (Long) (object[0]))); + } catch (NoResultException excp) { + logger.debug(excp.getMessage()); + } + } + + return Collections.emptyMap(); + } + private GroupInfo toGroupInfo(Object[] row) { String name = (String) row[0]; String description = (String) row[1]; diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyConditionDefDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyConditionDefDao.java index ac17b295ac7..eb695380741 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyConditionDefDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyConditionDefDao.java @@ -17,17 +17,27 @@ package org.apache.ranger.db; +import org.apache.commons.collections.CollectionUtils; import org.apache.ranger.common.db.BaseDao; import org.apache.ranger.entity.XXPolicyConditionDef; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.persistence.NoResultException; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; @Service public class XXPolicyConditionDefDao extends BaseDao { + private static final Logger logger = LoggerFactory.getLogger(XXPolicyConditionDefDao.class); + public XXPolicyConditionDefDao(RangerDaoManagerBase daoManager) { super(daoManager); } @@ -60,4 +70,22 @@ public XXPolicyConditionDef findByServiceDefIdAndName(Long serviceDefId, String return null; } } + + public Map findConditionDefIdsByServiceDefIdAndNames(Long serviceDefId, Set names) { + if (serviceDefId != null && CollectionUtils.isNotEmpty(names)) { + try { + Collection result = getEntityManager() + .createNamedQuery("XXPolicyConditionDef.findConditionDefIdsByServiceDefIdAndNames", Object[].class) + .setParameter("serviceDefId", serviceDefId) + .setParameter("names", names) + .getResultList(); + + return result.stream().collect(Collectors.toMap(object -> (String) object[1], object -> (Long) object[0], (a, b) -> a)); + } catch (NoResultException e) { + logger.debug(e.getMessage()); + } + } + + return Collections.emptyMap(); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefGroupDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefGroupDao.java index 21496a81a10..348923f1fe1 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefGroupDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefGroupDao.java @@ -28,8 +28,11 @@ import javax.persistence.NoResultException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Service public class XXPolicyRefGroupDao extends BaseDao { @@ -120,4 +123,30 @@ public void deleteByPolicyId(Long policyId) { batchDeleteByIds("XXPolicyRefGroup.deleteByIds", ids, "ids"); } + + public Map findGroupNameByPolicyId(Long policyId) { + Map ret = Collections.emptyMap(); + if (policyId != null) { + try { + Collection results = getEntityManager() + .createNamedQuery("XXPolicyRefGroup.findGroupNameByPolicyId", Object[].class) + .setParameter("policyId", policyId) + .getResultList(); + ret = results.stream().collect( + Collectors.toMap( + object -> (String) object[0], + object -> (Long) object[1])); + } catch (NoResultException e) { + // ignore + } + } + return ret; + } + + public void deletePolicyRefGroupByIds(List ids) { + if (CollectionUtils.isEmpty(ids)) { + return; + } + batchDeleteByIds("XXPolicyRefGroup.deletePolicyRefGroupByIds", ids, "ids"); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefRoleDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefRoleDao.java index 69b82d67320..dfddf1e666f 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefRoleDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefRoleDao.java @@ -28,8 +28,11 @@ import javax.persistence.NoResultException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Service public class XXPolicyRefRoleDao extends BaseDao { @@ -133,4 +136,30 @@ public void deleteByPolicyId(Long policyId) { batchDeleteByIds("XXPolicyRefRole.deleteByIds", ids, "ids"); } + + public Map findRoleNameIdByPolicyId(Long policyId) { + Map ret = Collections.emptyMap(); + if (policyId != null) { + try { + Collection results = getEntityManager() + .createNamedQuery("XXPolicyRefRole.findRoleNameIdByPolicyId", Object[].class) + .setParameter("policyId", policyId) + .getResultList(); + ret = results.stream().collect( + Collectors.toMap( + object -> (String) object[0], + object -> (Long) object[1])); + } catch (NoResultException e) { + // ignore + } + } + return ret; + } + + public void deletePolicyRefRoleByIds(List ids) { + if (CollectionUtils.isEmpty(ids)) { + return; + } + batchDeleteByIds("XXPolicyRefRole.deletePolicyRefRoleByIds", ids, "ids"); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefUserDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefUserDao.java index d70ebd50e46..38acfaa8d17 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefUserDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyRefUserDao.java @@ -28,8 +28,11 @@ import javax.persistence.NoResultException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Service public class XXPolicyRefUserDao extends BaseDao { @@ -133,4 +136,30 @@ public void deleteByPolicyId(Long policyId) { batchDeleteByIds("XXPolicyRefUser.deleteByIds", ids, "ids"); } + + public Map findUserNameIdByPolicyId(Long policyId) { + Map ret = Collections.emptyMap(); + if (policyId != null) { + try { + Collection results = getEntityManager() + .createNamedQuery("XXPolicyRefUser.findUserNameIdByPolicyId", Object[].class) + .setParameter("policyId", policyId) + .getResultList(); + ret = results.stream().collect( + Collectors.toMap( + object -> (String) object[0], + object -> (Long) object[1])); + } catch (NoResultException e) { + // ignore + } + } + return ret; + } + + public void deletePolicyRefUserByIds(List ids) { + if (CollectionUtils.isEmpty(ids)) { + return; + } + batchDeleteByIds("XXPolicyRefUser.deletePolicyRefUserByIds", ids, "ids"); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXResourceDefDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXResourceDefDao.java index bc0b0643182..62a301f7444 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXResourceDefDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXResourceDefDao.java @@ -17,17 +17,27 @@ package org.apache.ranger.db; +import org.apache.commons.collections.CollectionUtils; import org.apache.ranger.common.db.BaseDao; import org.apache.ranger.entity.XXResourceDef; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.persistence.NoResultException; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; @Service public class XXResourceDefDao extends BaseDao { + private static final Logger logger = LoggerFactory.getLogger(XXResourceDefDao.class); + public XXResourceDefDao(RangerDaoManagerBase daoMgr) { super(daoMgr); } @@ -101,4 +111,22 @@ public List findByParentResId(Long parentId) { return new ArrayList<>(); } } + + public Map findResourceDefIdsByNameAndPolicyId(Set names, Long policyId) { + if (policyId != null && CollectionUtils.isNotEmpty(names)) { + try { + Collection result = getEntityManager() + .createNamedQuery("XXResourceDef.findResourceDefIdsByNameAndPolicyId", Object[].class) + .setParameter("policyId", policyId) + .setParameter("names", names) + .getResultList(); + + return result.stream().collect(Collectors.toMap(object -> (String) object[1], object -> (Long) object[0], (a, b) -> a)); + } catch (NoResultException e) { + logger.debug(e.getMessage()); + } + } + + return Collections.emptyMap(); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java index 7b939e29b77..78372ee2c8a 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java @@ -17,19 +17,27 @@ package org.apache.ranger.db; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.ranger.common.db.BaseDao; import org.apache.ranger.entity.XXRole; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.persistence.NoResultException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Service public class XXRoleDao extends BaseDao { + private static final Logger logger = LoggerFactory.getLogger(XXRoleDao.class); + /** * Default Constructor */ @@ -121,4 +129,21 @@ public List findByGroupId(Long groupId) { } return ret; } + + public Map getIdsByRoleNames(Collection roleNames) { + if (CollectionUtils.isNotEmpty(roleNames)) { + try { + Collection result = getEntityManager() + .createNamedQuery("XXRole.getIdsByRoleNames", Object[].class) + .setParameter("roleNames", roleNames) + .getResultList(); + + return result.stream().collect(Collectors.toMap(object -> (String) (object[1]), object -> (Long) (object[0]))); + } catch (NoResultException e) { + logger.debug(e.getMessage()); + } + } + + return Collections.emptyMap(); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXUserDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXUserDao.java index 520241268f5..6a60b468c28 100755 --- a/security-admin/src/main/java/org/apache/ranger/db/XXUserDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXUserDao.java @@ -19,6 +19,7 @@ package org.apache.ranger.db; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.ranger.authorization.utils.JsonUtils; import org.apache.ranger.common.RangerCommonEnums; @@ -33,12 +34,14 @@ import javax.persistence.NoResultException; 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 java.util.stream.Collectors; import static org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD__EMAIL_ADDRESS; import static org.apache.ranger.plugin.util.RangerCommonConstants.SCRIPT_FIELD__IS_INTERNAL; @@ -185,6 +188,23 @@ public List getAllUsersInfo() { return ret; } + public Map getIdsByUserNames(Collection names) { + if (CollectionUtils.isNotEmpty(names)) { + try { + Collection result = getEntityManager() + .createNamedQuery("XXUser.getIdsByUserNames", Object[].class) + .setParameter("names", names) + .getResultList(); + + return result.stream().collect(Collectors.toMap(object -> (String) (object[1]), object -> (Long) (object[0]))); + } catch (NoResultException e) { + logger.debug(e.getMessage()); + } + } + + return Collections.emptyMap(); + } + private UserInfo toUserInfo(Object[] row) { String name = (String) row[0]; String description = (String) row[1]; diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml index 7ae05973ded..c9b709ed96a 100755 --- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml +++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml @@ -176,6 +176,10 @@ + + SELECT obj.id, obj.name FROM XXGroup obj WHERE obj.name IN :names + + SELECT user.name, group.name FROM XXUser user, XXGroup group, XXGroupUser groupUser @@ -193,6 +197,10 @@ + + SELECT obj.id, obj.name FROM XXUser obj WHERE obj.name IN :names + + SELECT p.principalName, p.principalType FROM VXXPrincipal p WHERE p.principalName LIKE :principalName @@ -583,6 +591,15 @@ and xSvc.id = xPol.service and xPol.id = :policyId and obj.name = :name order by obj.level + + SELECT obj.id, obj.name FROM XXResourceDef obj + WHERE obj.name IN :names AND obj.defId IN + (SELECT xSvcDef.id FROM XXServiceDef xSvcDef, XXService xSvc, XXPolicy xPol + WHERE xSvcDef.id = xSvc.type AND xSvc.id = xPol.service AND xPol.id = :policyId) + ORDER BY obj.level + + + select obj from XXResourceDef obj where obj.parent = :parentId @@ -636,6 +653,11 @@ obj.name = :name and xSvc.id = :serviceId and obj.defId = xSvc.type + + SELECT obj.id, obj.name FROM XXAccessTypeDef obj + WHERE obj.name IN :names AND obj.defId IN (SELECT xSvc.type FROM XXService xSvc WHERE xSvc.id = :serviceId) + + SELECT obj.name FROM XXAccessTypeDef obj, XXService svc WHERE svc.name = :serviceName @@ -652,6 +674,10 @@ select obj from XXPolicyConditionDef obj where obj.defId = :serviceDefId and obj.name = :name order by obj.order + + select obj.id, obj.name from XXPolicyConditionDef obj where obj.defId = :serviceDefId and obj.name IN :names order by obj.order + + select obj from XXContextEnricherDef obj where obj.defId = :serviceDefId order by obj.order @@ -677,6 +703,10 @@ obj.name = :name and xSvc.id = :serviceId and obj.defId = xSvc.type + + select obj.id, obj.name from XXDataMaskTypeDef obj, XXService xSvc where obj.name IN :names and xSvc.id = :serviceId and obj.defId = xSvc.type + + SELECT obj.name FROM XXDataMaskTypeDef obj, XXService svc WHERE svc.name = :serviceName @@ -916,6 +946,14 @@ select obj from XXPolicyRefGroup obj where obj.groupName = :groupName + + select obj.groupName, obj.id from XXPolicyRefGroup obj where obj.policyId = :policyId + + + + DELETE FROM XXPolicyRefGroup obj WHERE obj.id IN :ids + + select obj from XXPolicyRefGroup obj where obj.groupId = :groupId and obj.policyId = :policyId @@ -1122,6 +1160,14 @@ DELETE FROM XXPolicyRefUser obj WHERE obj.id IN :ids + + SELECT obj.userName, obj.id FROM XXPolicyRefUser obj WHERE obj.policyId = :policyId + + + + DELETE FROM XXPolicyRefUser obj WHERE obj.id IN :ids + + @@ -1956,6 +2002,10 @@ select obj.name from XXRole obj + + SELECT obj.id, obj.name FROM XXRole obj WHERE obj.name IN :roleNames + + @@ -2026,6 +2076,14 @@ select obj from XXPolicyRefRole obj where obj.policyId = :policyId + + SELECT obj.roleName, obj.id FROM XXPolicyRefRole obj WHERE obj.policyId = :policyId + + + + DELETE FROM XXPolicyRefRole obj WHERE obj.id IN :ids + + select obj.id from XXPolicyRefRole obj where obj.policyId = :policyId diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestPolicyRefUpdater.java b/security-admin/src/test/java/org/apache/ranger/biz/TestPolicyRefUpdater.java index c3407f69760..d4da4e98283 100644 --- a/security-admin/src/test/java/org/apache/ranger/biz/TestPolicyRefUpdater.java +++ b/security-admin/src/test/java/org/apache/ranger/biz/TestPolicyRefUpdater.java @@ -36,14 +36,10 @@ import org.apache.ranger.db.XXResourceDefDao; import org.apache.ranger.db.XXRoleDao; import org.apache.ranger.db.XXUserDao; -import org.apache.ranger.entity.XXAccessTypeDef; -import org.apache.ranger.entity.XXDataMaskTypeDef; import org.apache.ranger.entity.XXPolicy; -import org.apache.ranger.entity.XXPolicyConditionDef; import org.apache.ranger.entity.XXPolicyRefGroup; import org.apache.ranger.entity.XXPolicyRefRole; import org.apache.ranger.entity.XXPolicyRefUser; -import org.apache.ranger.entity.XXResourceDef; import org.apache.ranger.entity.XXServiceDef; import org.apache.ranger.entity.XXUser; import org.apache.ranger.plugin.model.RangerPolicy; @@ -71,12 +67,18 @@ import java.lang.reflect.Method; import java.util.Arrays; 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 static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -122,7 +124,7 @@ public void testGetAllPolicyItemsAggregates() { @Test public void testCreateNewPolMappingForRefTable_NullPolicyNoop() throws Exception { - updater.createNewPolMappingForRefTable(null, null, null, false); + updater.createNewPolMappingForRefTable(null, null, null, false, false); } @Test @@ -162,9 +164,9 @@ public void testCreateNewPolMappingForRefTable_ValidEverything() throws Exceptio // Stubs for DAO lookups and batch create calls XXResourceDefDao resDefDao = mock(XXResourceDefDao.class); when(daoMgr.getXXResourceDef()).thenReturn(resDefDao); - XXResourceDef xRes = new XXResourceDef(); - xRes.setId(1L); - when(resDefDao.findByNameAndPolicyId("db", 5L)).thenReturn(xRes); + Map xxResourceDefIdMap = new HashMap<>(); + xxResourceDefIdMap.put("db", 1L); + when(resDefDao.findResourceDefIdsByNameAndPolicyId(Mockito.anySet(), Mockito.eq(5L))).thenReturn(xxResourceDefIdMap); Mockito.lenient().when(rangerAuditFields.populateAuditFields(Mockito.any(), Mockito.any())) .thenAnswer(inv -> inv.getArgument(0)); XXPolicyRefResourceDao polResDao = mock(XXPolicyRefResourceDao.class); @@ -177,45 +179,44 @@ public void testCreateNewPolMappingForRefTable_ValidEverything() throws Exceptio when(daoMgr.getXXPolicyRefUser()).thenReturn(polUserDao); XXAccessTypeDefDao accDefDao = mock(XXAccessTypeDefDao.class); when(daoMgr.getXXAccessTypeDef()).thenReturn(accDefDao); - XXAccessTypeDef xAcc = new XXAccessTypeDef(); - xAcc.setId(2L); - when(accDefDao.findByNameAndServiceId("select", 9L)).thenReturn(xAcc); + Map xAccMap = new HashMap<>(); + xAccMap.put("select", 2L); + when(accDefDao.findAccessTypeDefIdsByNamesAndServiceId(Mockito.anySet(), Mockito.eq(9L))).thenReturn(xAccMap); XXPolicyRefAccessTypeDao polAccDao = mock(XXPolicyRefAccessTypeDao.class); when(daoMgr.getXXPolicyRefAccessType()).thenReturn(polAccDao); XXPolicyConditionDefDao condDefDao = mock(XXPolicyConditionDefDao.class); when(daoMgr.getXXPolicyConditionDef()).thenReturn(condDefDao); - XXPolicyConditionDef xCond = new XXPolicyConditionDef(); - xCond.setId(3L); - when(condDefDao.findByServiceDefIdAndName(9L, "time")).thenReturn(xCond); + Map xCondMap = new HashMap<>(); + xCondMap.put("time", 3L); + when(condDefDao.findConditionDefIdsByServiceDefIdAndNames(Mockito.eq(9L), Mockito.anySet())).thenReturn(xCondMap); XXPolicyRefConditionDao polCondDao = mock(XXPolicyRefConditionDao.class); when(daoMgr.getXXPolicyRefCondition()).thenReturn(polCondDao); XXDataMaskTypeDefDao dmDefDao = mock(XXDataMaskTypeDefDao.class); when(daoMgr.getXXDataMaskTypeDef()).thenReturn(dmDefDao); - XXDataMaskTypeDef xDm = new XXDataMaskTypeDef(); - xDm.setId(4L); - when(dmDefDao.findByNameAndServiceId("MASK", 9L)).thenReturn(xDm); + Map xxDataMaskTypeDefIdMap = new HashMap<>(); + xxDataMaskTypeDefIdMap.put("MASK", 4L); + when(dmDefDao.findDataMaskTypeDefIdsByNamesAndServiceId(Mockito.anySet(), Mockito.eq(9L))).thenReturn(xxDataMaskTypeDefIdMap); XXPolicyRefDataMaskTypeDao polDmDao = mock(XXPolicyRefDataMaskTypeDao.class); when(daoMgr.getXXPolicyRefDataMaskType()).thenReturn(polDmDao); when(rangerBizUtil.checkAdminAccess()).thenReturn(true); - // Principal creation path (user, group, role) when not existing and - // createPrincipalsIfAbsent=true + org.apache.ranger.db.XXPolicyDao policyDao = mock(org.apache.ranger.db.XXPolicyDao.class); + when(daoMgr.getXXPolicy()).thenReturn(policyDao); + when(policyDao.getById(xPolicy.getId())).thenReturn(xPolicy); + XXUserDao userDao = mock(XXUserDao.class); when(daoMgr.getXXUser()).thenReturn(userDao); - when(userDao.findByUserName("u1")).thenReturn(null); - when(daoMgr.getXXPolicyRefUser()).thenReturn(polUserDao); + when(userDao.getIdsByUserNames(Mockito.anySet())).thenReturn(Collections.singletonMap("u1", 30L)); XXGroupDao groupDao = mock(XXGroupDao.class); when(daoMgr.getXXGroup()).thenReturn(groupDao); - when(groupDao.findByGroupName("g1")).thenReturn(null); - when(daoMgr.getXXPolicyRefGroup()).thenReturn(polGroupDao); + when(groupDao.getIdsByGroupNames(Mockito.anySet())).thenReturn(Collections.singletonMap("g1", 20L)); XXRoleDao roleDao = mock(XXRoleDao.class); when(daoMgr.getXXRole()).thenReturn(roleDao); - when(roleDao.findByRoleName("r1")).thenReturn(null); - when(daoMgr.getXXPolicyRefRole()).thenReturn(polRoleDao); + when(roleDao.getIdsByRoleNames(Mockito.anySet())).thenReturn(Collections.singletonMap("r1", 10L)); - updater.createNewPolMappingForRefTable(policy, xPolicy, xSvc, true); + updater.createNewPolMappingForRefTable(policy, xPolicy, xSvc, true, false); // no exceptions indicates success across branches } @@ -231,18 +232,72 @@ public void testCreateNewPolMappingForRefTable_InvalidResourceDef() throws Excep xPolicy.setId(6L); XXServiceDef xSvc = new XXServiceDef(); xSvc.setId(9L); - // ensure cleanupRefTables() doesn't NPE before resource lookup - when(daoMgr.getXXPolicyRefResource()).thenReturn(mock(XXPolicyRefResourceDao.class)); - when(daoMgr.getXXPolicyRefRole()).thenReturn(mock(XXPolicyRefRoleDao.class)); - when(daoMgr.getXXPolicyRefGroup()).thenReturn(mock(XXPolicyRefGroupDao.class)); - when(daoMgr.getXXPolicyRefUser()).thenReturn(mock(XXPolicyRefUserDao.class)); - when(daoMgr.getXXPolicyRefAccessType()).thenReturn(mock(XXPolicyRefAccessTypeDao.class)); - when(daoMgr.getXXPolicyRefCondition()).thenReturn(mock(XXPolicyRefConditionDao.class)); - when(daoMgr.getXXPolicyRefDataMaskType()).thenReturn(mock(XXPolicyRefDataMaskTypeDao.class)); XXResourceDefDao resDefDao = mock(XXResourceDefDao.class); when(daoMgr.getXXResourceDef()).thenReturn(resDefDao); - when(resDefDao.findByNameAndPolicyId("invalid", 6L)).thenReturn(null); - assertThrows(Exception.class, () -> updater.createNewPolMappingForRefTable(policy, xPolicy, xSvc, false)); + when(resDefDao.findResourceDefIdsByNameAndPolicyId(Mockito.anySet(), Mockito.eq(6L))).thenReturn(Collections.emptyMap()); + assertThrows(Exception.class, () -> updater.createNewPolMappingForRefTable(policy, xPolicy, xSvc, false, false)); + } + + @Test + public void testCleanupRefTablesForUpdate_SelectivePrincipalCleanup() { + final Long policyId = 100L; + + Set policyUsers = new HashSet<>(Arrays.asList("alice", "bob", "carol")); + Set policyRoles = new HashSet<>(Arrays.asList("roleA", "roleB", "roleNew")); + Set policyGroups = new HashSet<>(Arrays.asList("grp1", "grp2", "grpNew")); + + Map existingUsers = new HashMap<>(); + existingUsers.put("alice", 1L); + existingUsers.put("bob", 2L); + existingUsers.put("dave", 4L); + + Map existingRoles = new HashMap<>(); + existingRoles.put("roleA", 10L); + existingRoles.put("roleOld", 12L); + + Map existingGroups = new HashMap<>(); + existingGroups.put("grp1", 20L); + existingGroups.put("grpOld", 22L); + + XXPolicyRefUserDao userDao = mock(XXPolicyRefUserDao.class); + XXPolicyRefRoleDao roleDao = mock(XXPolicyRefRoleDao.class); + XXPolicyRefGroupDao groupDao = mock(XXPolicyRefGroupDao.class); + XXPolicyRefResourceDao resourceDao = mock(XXPolicyRefResourceDao.class); + XXPolicyRefAccessTypeDao accessDao = mock(XXPolicyRefAccessTypeDao.class); + XXPolicyRefConditionDao conditionDao = mock(XXPolicyRefConditionDao.class); + XXPolicyRefDataMaskTypeDao dataMaskDao = mock(XXPolicyRefDataMaskTypeDao.class); + + when(daoMgr.getXXPolicyRefUser()).thenReturn(userDao); + when(daoMgr.getXXPolicyRefRole()).thenReturn(roleDao); + when(daoMgr.getXXPolicyRefGroup()).thenReturn(groupDao); + when(daoMgr.getXXPolicyRefResource()).thenReturn(resourceDao); + when(daoMgr.getXXPolicyRefAccessType()).thenReturn(accessDao); + when(daoMgr.getXXPolicyRefCondition()).thenReturn(conditionDao); + when(daoMgr.getXXPolicyRefDataMaskType()).thenReturn(dataMaskDao); + + when(userDao.findUserNameIdByPolicyId(policyId)).thenReturn(existingUsers); + when(roleDao.findRoleNameIdByPolicyId(policyId)).thenReturn(existingRoles); + when(groupDao.findGroupNameByPolicyId(policyId)).thenReturn(existingGroups); + + assertTrue(updater.cleanupRefTablesForUpdate(policyId, policyUsers, policyRoles, policyGroups)); + + verify(userDao).deletePolicyRefUserByIds(Collections.singletonList(4L)); + assertEquals(Collections.singleton("carol"), policyUsers); + + verify(roleDao).deletePolicyRefRoleByIds(Collections.singletonList(12L)); + assertEquals(new HashSet<>(Arrays.asList("roleB", "roleNew")), policyRoles); + + verify(groupDao).deletePolicyRefGroupByIds(Collections.singletonList(22L)); + assertEquals(new HashSet<>(Arrays.asList("grp2", "grpNew")), policyGroups); + + verify(resourceDao).deleteByPolicyId(policyId); + verify(accessDao).deleteByPolicyId(policyId); + verify(conditionDao).deleteByPolicyId(policyId); + verify(dataMaskDao).deleteByPolicyId(policyId); + + verify(userDao, never()).deleteByPolicyId(policyId); + verify(roleDao, never()).deleteByPolicyId(policyId); + verify(groupDao, never()).deleteByPolicyId(policyId); } @Test @@ -268,9 +323,14 @@ public void testCreatePrincipal_User_Group_Role_Paths() throws Exception { xPolicy.setId(10L); xPolicy.setService(100L); + // FIX: Mock policy DAO hierarchy to satisfy doesPolicyExist(xPolicy) checks + org.apache.ranger.db.XXPolicyDao policyDao = mock(org.apache.ranger.db.XXPolicyDao.class); + when(daoMgr.getXXPolicy()).thenReturn(policyDao); + when(policyDao.getById(xPolicy.getId())).thenReturn(xPolicy); + // Mock audit population to be identity Mockito.lenient().when(rangerAuditFields.populateAuditFields(Mockito.any(), Mockito.any())) - .thenAnswer(inv -> inv.getArgument(0)); + .thenAnswer(inv -> inv.getArgument(0)); // USER path: user not found, xUserMgr creates, then XXUser lookup returns id XXUserDao userDao = mock(XXUserDao.class); @@ -285,23 +345,22 @@ public void testCreatePrincipal_User_Group_Role_Paths() throws Exception { XXPolicyRefUserDao polUserDao = mock(XXPolicyRefUserDao.class); when(daoMgr.getXXPolicyRefUser()).thenReturn(polUserDao); - // Reflectively construct inner class PolicyPrincipalAssociator for USER - Class inner = null; + // Reflectively construct inner class PolicyUserAssociator for USER + Class userAssociatorClass = null; for (Class c : PolicyRefUpdater.class.getDeclaredClasses()) { - if (c.getSimpleName().equals("PolicyPrincipalAssociator")) { - inner = c; + if (c.getSimpleName().equals("PolicyUserAssociator")) { + userAssociatorClass = c; break; } } - assertNotNull(inner); - Constructor ctor = inner.getDeclaredConstructor(PolicyRefUpdater.class, - PolicyRefUpdater.PRINCIPAL_TYPE.class, String.class, XXPolicy.class); - ctor.setAccessible(true); - Object associatorUser = ctor.newInstance(updater, PolicyRefUpdater.PRINCIPAL_TYPE.USER, "uNew", xPolicy); - Method doAssociate = inner.getDeclaredMethod("doAssociate", boolean.class); - doAssociate.setAccessible(true); - Object resultUser = doAssociate.invoke(associatorUser, true); - assertEquals(Boolean.TRUE, resultUser); + assertNotNull(userAssociatorClass); + Constructor userCtor = userAssociatorClass.getDeclaredConstructor( + PolicyRefUpdater.class, String.class, Long.class, XXPolicy.class); + userCtor.setAccessible(true); + Object associatorUser = userCtor.newInstance(updater, "uNew", null, xPolicy); + Method runUser = userAssociatorClass.getDeclaredMethod("run"); + runUser.setAccessible(true); + runUser.invoke(associatorUser); verify(daoMgr.getXXPolicyRefUser(), Mockito.times(1)) .create(Mockito.any(XXPolicyRefUser.class)); @@ -316,9 +375,21 @@ public void testCreatePrincipal_User_Group_Role_Paths() throws Exception { XXPolicyRefGroupDao polGroupDao = mock(XXPolicyRefGroupDao.class); when(daoMgr.getXXPolicyRefGroup()).thenReturn(polGroupDao); - Object associatorGroup = ctor.newInstance(updater, PolicyRefUpdater.PRINCIPAL_TYPE.GROUP, "gNew", xPolicy); - Object resultGroup = doAssociate.invoke(associatorGroup, true); - assertEquals(Boolean.TRUE, resultGroup); + Class groupAssociatorClass = null; + for (Class c : PolicyRefUpdater.class.getDeclaredClasses()) { + if (c.getSimpleName().equals("PolicyGroupAssociator")) { + groupAssociatorClass = c; + break; + } + } + assertNotNull(groupAssociatorClass); + Constructor groupCtor = groupAssociatorClass.getDeclaredConstructor( + PolicyRefUpdater.class, String.class, Long.class, XXPolicy.class); + groupCtor.setAccessible(true); + Object associatorGroup = groupCtor.newInstance(updater, "gNew", null, xPolicy); + Method runGroup = groupAssociatorClass.getDeclaredMethod("run"); + runGroup.setAccessible(true); + runGroup.invoke(associatorGroup); verify(daoMgr.getXXPolicyRefGroup(), Mockito.times(1)) .create(Mockito.any(XXPolicyRefGroup.class)); @@ -333,9 +404,21 @@ public void testCreatePrincipal_User_Group_Role_Paths() throws Exception { XXPolicyRefRoleDao polRoleDao = mock(XXPolicyRefRoleDao.class); when(daoMgr.getXXPolicyRefRole()).thenReturn(polRoleDao); - Object associatorRole = ctor.newInstance(updater, PolicyRefUpdater.PRINCIPAL_TYPE.ROLE, "rNew", xPolicy); - Object resultRole = doAssociate.invoke(associatorRole, true); - assertEquals(Boolean.TRUE, resultRole); + Class roleAssociatorClass = null; + for (Class c : PolicyRefUpdater.class.getDeclaredClasses()) { + if (c.getSimpleName().equals("PolicyRoleAssociator")) { + roleAssociatorClass = c; + break; + } + } + assertNotNull(roleAssociatorClass); + Constructor roleCtor = roleAssociatorClass.getDeclaredConstructor( + PolicyRefUpdater.class, String.class, Long.class, XXPolicy.class); + roleCtor.setAccessible(true); + Object associatorRole = roleCtor.newInstance(updater, "rNew", null, xPolicy); + Method runRole = roleAssociatorClass.getDeclaredMethod("run"); + runRole.setAccessible(true); + runRole.invoke(associatorRole); verify(daoMgr.getXXPolicyRefRole(), Mockito.times(1)).create(Mockito.any(XXPolicyRefRole.class)); } } diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java b/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java index 07c70810de5..ec287dfb6e4 100644 --- a/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java +++ b/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java @@ -1425,7 +1425,7 @@ public void test26createPolicy() throws Exception { Mockito.when(daoMgr.getXXPolicy()).thenReturn(xPolicyDao); Mockito.when(xPolicyDao.getById(Id)).thenReturn(xPolicy); - Mockito.doNothing().when(policyRefUpdater).createNewPolMappingForRefTable(rangerPolicy, xPolicy, xServiceDef, false); + Mockito.doNothing().when(policyRefUpdater).createNewPolMappingForRefTable(rangerPolicy, xPolicy, xServiceDef, false, false); Mockito.when(policyService.getPopulatedViewObject(xPolicy)).thenReturn(rangerPolicy); Mockito.when(daoMgr.getXXService()).thenReturn(xServiceDao); @@ -1550,7 +1550,9 @@ public void test28updatePolicy() throws Exception { RangerPolicyResourceSignature signature = Mockito.mock(RangerPolicyResourceSignature.class); Mockito.when(factory.createPolicyResourceSignature(rangerPolicy)).thenReturn(signature); Mockito.when(!bizUtil.hasAccess(xService, null)).thenReturn(true); - Mockito.when(policyRefUpdater.cleanupRefTables(rangerPolicy)).thenReturn(true); + Mockito.doNothing().when(policyRefUpdater).createNewPolMappingForRefTable( + Mockito.eq(rangerPolicy), Mockito.eq(xPolicy), Mockito.eq(xServiceDef), + Mockito.anyBoolean(), Mockito.eq(true)); RangerPolicy dbRangerPolicy = serviceDBStore.updatePolicy(rangerPolicy); Assertions.assertNotNull(dbRangerPolicy);