/* * Copyright 2018 A-SIT Plus GmbH * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. * * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "License"); * You may not use this work except in compliance with the License. * You may obtain a copy of the License at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. */ package at.asitplus.eidas.specific.modules.auth.eidas.v2.service; import java.io.File; import java.text.MessageFormat; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.PostConstruct; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; import edu.umd.cs.findbugs.annotations.NonNull; import eu.eidas.auth.commons.attribute.AttributeRegistries; import eu.eidas.auth.commons.attribute.AttributeRegistry; @Service("attributeRegistry") public class EidasAttributeRegistry { private static final Logger log = LoggerFactory.getLogger(EidasAttributeRegistry.class); @Autowired private IConfigurationWithSP basicConfig; private AttributeRegistry coreAttributeRegistry; private String eidasAttributesFile; private String additionalAttributesFile; @PostConstruct private void initialize() throws RuntimeException { try { if (eidasAttributesFile.isEmpty()) { log.error("Basic eIDAS addribute definition NOT defined"); throw new EaafConfigurationException("config.30", new Object[] { "eidas-attributes.xml" }); } boolean additionalAttrAvailabe = false; if (!additionalAttributesFile.isEmpty()) { final File file = new File(additionalAttributesFile); if (file.exists()) { additionalAttrAvailabe = true; } } if (!additionalAttrAvailabe) { log.info("Start eIDAS ref. impl. Core without additional eIDAS attribute definitions ... "); coreAttributeRegistry = AttributeRegistries.fromFiles(eidasAttributesFile, null); } else { // load attribute definitions log.info("Start eIDAS ref. impl. Core with additional eIDAS attribute definitions ... "); coreAttributeRegistry = AttributeRegistries.fromFiles(eidasAttributesFile, null, additionalAttributesFile); } } catch (final Throwable e) { log.error("Can NOT initialize eIDAS attribute definition.", e); throw new RuntimeException("Can NOT initialize eIDAS attribute definition.", e); } } public AttributeRegistry getCoreAttributeRegistry() { return coreAttributeRegistry; } /** * Get Map of attributes that are requested by default. * * @return Map of AttributeIdentifier, isRequired flag */ @NonNull public Map getDefaultAttributeSetFromConfiguration() { /* * TODO: select set for representation if mandates should be used. It's an open * task in respect to requested eIDAS attributes and isRequired flag, because * there can be a decision problem in case of natural or legal person * representation! From an Austrian use-case point of view, an Austrian service * provider can support mandates for natural and legal persons at the same time. * However, we CAN NOT request attributes for natural AND legal persons on the * same time, because it's not possible to represent both simultaneously. */ final Map configAttributes = basicConfig.getBasicConfigurationWithPrefix( Constants.CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_DEFAULT_ONLYNATURAL); return processAttributeInfosFromConfig(configAttributes); } /** * Get a Map of attributes that are additionally requested for a specific country. * * @param countryCode Country Code * @return Map of AttributeIdentifier, isRequired flag */ @NonNull public Map getAttributeSetFromConfiguration(String countryCode) { /* * TODO: select set for representation if mandates should be used. It's an open * task in respect to requested eIDAS attributes and isRequired flag, because * there can be a decision problem in case of natural or legal person * representation! From an Austrian use-case point of view, an Austrian service * provider can support mandates for natural and legal persons at the same time. * However, we CAN NOT request attributes for natural AND legal persons on the * same time, because it's not possible to represent both simultaneously. */ final Map configAttributes = basicConfig.getBasicConfigurationWithPrefix( MessageFormat.format( Constants.CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_CC_SPECIFIC_ONLYNATURAL, countryCode.toLowerCase())); return processAttributeInfosFromConfig(configAttributes); } private Map processAttributeInfosFromConfig(Map configAttributes) { final Map result = new HashMap<>(); for (final String el : configAttributes.values()) { if (StringUtils.isNotEmpty(el.trim())) { final List attrDef = KeyValueUtils.getListOfCsvValues(el.trim()); boolean isRequired = false; if (attrDef.size() == 2) { isRequired = Boolean.parseBoolean(attrDef.get(1)); } result.put(attrDef.get(0), isRequired); } } log.trace("Load #" + result.size() + " requested attributes from configuration"); return result; } public void setEidasAttributesFile(String eidasAttributesFile) { this.eidasAttributesFile = eidasAttributesFile; } public void setAdditionalAttributesFile(String additionalAttributesFile) { this.additionalAttributesFile = additionalAttributesFile; } }