aboutsummaryrefslogtreecommitdiff
path: root/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/service/ProxyEidasAttributeRegistry.java
diff options
context:
space:
mode:
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.java249
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;
+
+ }
+
+
+}