001package com.identityworksllc.iiq.common.access; 002 003import com.identityworksllc.iiq.common.ConfigurationMerger; 004import com.identityworksllc.iiq.common.Metered; 005import sailpoint.api.SailPointContext; 006import sailpoint.object.Configuration; 007import sailpoint.tools.GeneralException; 008import sailpoint.tools.Util; 009 010import java.util.HashMap; 011import java.util.Map; 012 013import static com.identityworksllc.iiq.common.access.DelegatedAccessController.getDelegatedAccessConfig; 014 015/** 016 * Assembles the controls (Common Security assertions) that are present on the 017 * given purpose string, or any of its parent substrings. 018 * 019 * Additionally, any controls in the special key 'global' will be added. 020 * 021 * More specific assertions will override less specific ones. 022 */ 023public class DelegatedAccessAssembler { 024 025 private final SailPointContext context; 026 027 public DelegatedAccessAssembler(SailPointContext context) { 028 this.context = context; 029 } 030 031 /** 032 * Assembles the thing controls for the given target and purpose 033 * 034 * @param purpose The input purpose 035 * @return The assembled / merged set of controls for the given purpose 036 * @throws GeneralException if any failures occur assembling controls 037 */ 038 public Map<String, Object> assembleControls(String purpose) throws GeneralException { 039 return Metered.meter("DelegatedAccessAssembler.assembleControls", () -> { 040 Configuration delegatedAccessConfig = getDelegatedAccessConfig(context); 041 042 Map<String, Object> controls = new HashMap<>(); 043 044 if (delegatedAccessConfig.get("global") instanceof Map) { 045 @SuppressWarnings("unchecked") 046 Map<String, Object> globalControls = (Map<String, Object>) delegatedAccessConfig.get("global"); 047 048 controls.putAll(globalControls); 049 } 050 051 if (Util.isNotNullOrEmpty(purpose)) { 052 String[] purposePieces = purpose.split(DelegatedAccessConstants.TOKEN_DIVIDER); 053 String assembledPurpose = ""; 054 // Loop over each substring of the purpose, such as a, a:b, a:b:c, etc. 055 // TODO support wildcards, such as a:*:c 056 for(String purposePiece : purposePieces) { 057 if (!assembledPurpose.isEmpty()) { 058 assembledPurpose += DelegatedAccessConstants.TOKEN_DIVIDER; 059 } 060 assembledPurpose += purposePiece; 061 if (delegatedAccessConfig.get(assembledPurpose) instanceof Map) { 062 @SuppressWarnings("unchecked") 063 Map<String, Object> purposeControls = (Map<String, Object>) delegatedAccessConfig.get(assembledPurpose); 064 065 // TODO handle anyOf / allOf nested values 066 controls = ConfigurationMerger.mergeConfigurations(controls, purposeControls); 067 } 068 } 069 } 070 return controls; 071 }); 072 } 073}