diff options
Diffstat (limited to 'modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/service/ProxyEidasAttributeRegistry.java')
-rw-r--r-- | modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/service/ProxyEidasAttributeRegistry.java | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/service/ProxyEidasAttributeRegistry.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/service/ProxyEidasAttributeRegistry.java new file mode 100644 index 00000000..edb21722 --- /dev/null +++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/service/ProxyEidasAttributeRegistry.java @@ -0,0 +1,249 @@ +package at.asitplus.eidas.specific.modules.msproxyservice.service; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.annotation.PostConstruct; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.CollectionType; +import com.google.common.collect.Sets; + +import at.asitplus.eidas.specific.modules.core.eidas.service.EidasAttributeRegistry; +import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceConstants; +import at.asitplus.eidas.specific.modules.msproxyservice.dto.attributes.AttrMappingElement; +import at.asitplus.eidas.specific.modules.msproxyservice.handler.IEidasAttributeHandler; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; +import lombok.Getter; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ProxyEidasAttributeRegistry { + + private static final String ATTR_CONFIG_ALL = "*"; + + private static ObjectMapper mapper = new ObjectMapper(); + + @Autowired ApplicationContext context; + @Autowired IConfiguration basicConfig; + @Autowired ResourceLoader resourceLoader; + + + @Getter + private EidasAttributeRegistry coreRegistry; + + private Set<AttrMappingElement> attributeConfiguration; + + + /** + * Attribute Registry for eIDAS Proxy-Service implementation. + * @param registry Core attribute registry + */ + public ProxyEidasAttributeRegistry(@Autowired EidasAttributeRegistry registry) { + this.coreRegistry = registry; + + } + + + /** + * Get all attributes that requested from IDA by default. + * + * @param withMandates <code>true</code> if mandates are supported, otherwise <code>false</code> + * @return {@link Stream} of IDA specific attribute names + */ + @NonNull + public Stream<String> getAlwaysRequestedAttributes(boolean withMandates) { + return attributeConfiguration.stream() + .filter(el -> ATTR_CONFIG_ALL.equals(el.getEidasAttributeName())) + .map(el -> getReleadedIdaAttribute(el, withMandates)) + .flatMap(Collection::stream) + .filter(Objects::nonNull); + + } + + /** + * Get all eIDAS attributes that are added by default in case of mandates. + * + * @return {@link Stream} of eIDAS attributes + */ + @NonNull + public Stream<String> getRepresentativeAttributesToAddByDefault() { + return attributeConfiguration.stream() + .filter(el -> el.getType() != null && el.getType().getAutoIncludeWithMandates()) + .map(el -> el.getEidasAttributeName()); + + } + + /** + * Get IDA attributes for a specific eIDAS attribute. + * + * @param eidasAttributeName Name of the eIDAS attribute. + * @param withMandates <code>true</code> if mandates are supported, otherwise <code>false</code> + * @return {@link Set} of IDA specific attribute names + */ + @NonNull + public Set<String> getIdaAttributesForEidasAttribute(String eidasAttributeName, boolean withMandates) { + return attributeConfiguration.stream() + .filter(el -> el.getEidasAttributeName().equals(eidasAttributeName)) + .findFirst() + .map(el -> getReleadedIdaAttribute(el, withMandates)) + .orElse(Collections.emptySet()) + .stream() + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + } + + /** + * Get eIDAS related IDA attribute for a specific mode-operation. + * + * @param eidasAttributeName Name of the eIDAS attribute. + * @param withMandates <code>true</code> if mandates are supported, otherwise <code>false</code> + * @return Name of the related IDA attribute if available + */ + public Optional<String> mapEidasAttributeToSpecificIdaAttribute( + String eidasAttributeName, boolean withMandates) { + return attributeConfiguration.stream() + .filter(el -> el.getEidasAttributeName().equals(eidasAttributeName)) + .filter(el -> el.getIdaAttribute() != null) + .findFirst() + .map(el -> withMandates ? el.getIdaAttribute().getWithMandates() : el.getIdaAttribute().getBasic()) + .filter(el -> StringUtils.isNotEmpty(el)); + + } + + /** + * Get eIDAS related custom attribute-handler. + * + * @param eidasAttributeName Name of the eIDAS attribute. + * @return full classname of the handler implementation if available + */ + public Optional<String> mapEidasAttributeToAttributeHandler(String eidasAttributeName) { + return attributeConfiguration.stream() + .filter(el -> el.getEidasAttributeName().equals(eidasAttributeName)) + .filter(el -> StringUtils.isNotEmpty(el.getSpecificAttributeHandlerClass())) + .findFirst() + .map(el -> el.getSpecificAttributeHandlerClass()); + + } + + + @PostConstruct + private void initialize() throws EaafConfigurationException { + final String attrConfPath = basicConfig.getBasicConfiguration( + MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_ATTIBUTE_CONFIGURATION); + + log.debug("Initializing eIDAS <--> IDA attribute mapping from: {} ... ", attrConfPath); + + if (StringUtils.isEmpty(attrConfPath)) { + log.error("Error: Path to attribute-mapping config is unknown"); + throw new EaafConfigurationException("internal.configuration.00", + new Object[]{MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_ATTIBUTE_CONFIGURATION}); + + } + + try { + // reading attribute-configuration file + final CollectionType javaType = + mapper.getTypeFactory().constructCollectionType(List.class, AttrMappingElement.class); + List<AttrMappingElement> internalAttributeConfiguration = + mapper.readValue(readFromFile(attrConfPath), javaType); + log.debug("Found #{} eIDAS <--> IDA attribute-mappings . Starting import process ... ", + internalAttributeConfiguration.size()); + + // post-validation of attribute configuration + attributeConfiguration = internalAttributeConfiguration.stream() + .filter(el -> checkEidasAttributeName(el)) + .collect(Collectors.toSet()); + log.info("Load {} eIDAS <--> IDA attribute-mappings into attribute-registry", attributeConfiguration.size()); + + } catch (Exception e) { + log.error("Error reading eIDAS <--> IDA attribute-mapping configuration file", e); + throw new EaafConfigurationException("internal.configuration.01", + new Object[]{MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_ATTIBUTE_CONFIGURATION, + "Error reading Configurations file"}, e); + + } + } + + private Set<String> getReleadedIdaAttribute(AttrMappingElement el, boolean withMandates) { + if (el.getIdaAttribute() != null) { + Set<String> directMapping = withMandates + ? Sets.newHashSet(el.getIdaAttribute().getBasic(), el.getIdaAttribute().getWithMandates()) + : Sets.newHashSet(el.getIdaAttribute().getBasic()); + + if (el.getAddionalRequiredAttributes() != null) { + el.getAddionalRequiredAttributes().forEach( + attr -> directMapping.add(attr)); + + } + return directMapping; + + } else { + return Collections.emptySet(); + + } + } + + private boolean checkEidasAttributeName(AttrMappingElement el) { + if (StringUtils.isNotEmpty(el.getEidasAttributeName())) { + if (ATTR_CONFIG_ALL.equals(el.getEidasAttributeName()) + || coreRegistry.getCoreAttributeRegistry().getByName(el.getEidasAttributeName()) != null) { + + // check if custom attribute-handler implementation is available + if (StringUtils.isNotEmpty(el.getSpecificAttributeHandlerClass())) { + try { + context.getBean(el.getSpecificAttributeHandlerClass(), IEidasAttributeHandler.class); + + } catch (Exception e) { + log.error("No custom attribute-handler implementation for: {}", el.getSpecificAttributeHandlerClass(), e); + return false; + } + } + + return true; + + } else { + log.warn("eIDAS attribute: {} is UNKNOWN by eIDAS node. Ignore it!", el.getEidasAttributeName()); + + } + + } else { + log.warn("Find attribute-mapping element WITHOUT eIDAS attribute-name. Ignore it!"); + + } + + return false; + } + + private byte[] readFromFile(final String filePath) throws URISyntaxException, IOException { + final String fullFilePath = FileUtils.makeAbsoluteUrl(filePath, basicConfig.getConfigurationRootDirectory()); + final Resource ressource = resourceLoader.getResource(fullFilePath); + final InputStream is = ressource.getInputStream(); + final byte[] result = IOUtils.toByteArray(is); + is.close(); + return result; + + } + + +} |