/* * 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.connector.provider; import java.io.IOException; import java.security.KeyStore; import java.security.Provider; import java.security.cert.CertificateException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.opensaml.saml.metadata.resolver.MetadataResolver; import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; 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.connector.MsEidasNodeConstants; import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory; import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.AbstractChainingMetadataProvider; import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.PvpEntityCategoryFilter; import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SchemaValidationFilter; import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SimpleMetadataSignatureVerificationFilter; @Service("PVPMetadataProvider") public class PvpMetadataProvider extends AbstractChainingMetadataProvider { private static final Logger log = LoggerFactory.getLogger(PvpMetadataProvider.class); private static final String PROVIDER_ID_PATTERN = "eIDAS resolver: {0}"; @Autowired(required = true) IConfigurationWithSP basicConfig; @Autowired private PvpMetadataResolverFactory metadataProviderFactory; @Autowired private IHttpClientFactory httpClientFactory; @Autowired private EaafKeyStoreFactory keyStoreFactory; @Override protected String getMetadataUrl(String entityId) throws EaafConfigurationException { final ISpConfiguration spConfig = basicConfig.getServiceProviderConfiguration(entityId); if (spConfig != null) { String metadataUrl = entityId; final String metadataUrlFromConfig = spConfig.getConfigurationValue( MsEidasNodeConstants.PROP_CONFIG_SP_PVP2_METADATA_URL); if (StringUtils.isNotEmpty(metadataUrlFromConfig)) { log.debug("Use metdataURL from configuration for EntityId: " + entityId); metadataUrl = metadataUrlFromConfig; } return metadataUrl; } else { log.info("No ServiceProvider with entityId: " + entityId + " in configuration."); } return null; } @Override protected MetadataResolver createNewMetadataProvider(String entityId) throws EaafConfigurationException, IOException, CertificateException { final ISpConfiguration spConfig = basicConfig.getServiceProviderConfiguration(entityId); if (spConfig != null) { try { String metadataUrl = spConfig.getConfigurationValue( MsEidasNodeConstants.PROP_CONFIG_SP_PVP2_METADATA_URL); if (StringUtils.isEmpty(metadataUrl)) { log.debug("Use EntityId: " + entityId + " instead of explicite metadataURL ... "); metadataUrl = entityId; } KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); keyStoreConfig.setFriendlyName(MessageFormat.format(PROVIDER_ID_PATTERN, entityId)); keyStoreConfig.setKeyStoreType(KeyStoreType.JKS); keyStoreConfig.setSoftKeyStoreFilePath( spConfig.getConfigurationValue(MsEidasNodeConstants.PROP_CONFIG_SP_PVP2_METADATA_TRUSTSTORE)); keyStoreConfig.setSoftKeyStorePassword(spConfig.getConfigurationValue( MsEidasNodeConstants.PROP_CONFIG_SP_PVP2_METADATA_TRUSTSTORE_PASSWORD)); keyStoreConfig.validate(); Pair keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); final List filterList = new ArrayList<>(); filterList.add(new SchemaValidationFilter(true)); filterList.add(new SimpleMetadataSignatureVerificationFilter( keyStore.getFirst(), entityId)); filterList.add(new PvpEntityCategoryFilter( basicConfig.getBasicConfigurationBoolean(MsEidasNodeConstants.PROP_CONFIG_PVP_ENABLE_ENTITYCATEGORIES, true))); final MetadataFilterChain filter = new MetadataFilterChain(); filter.setFilters(filterList); try { return metadataProviderFactory.createMetadataProvider(getMetadataUrl(entityId), filter, MessageFormat.format(PROVIDER_ID_PATTERN, entityId), httpClientFactory.getHttpClient()); } catch (final Pvp2MetadataException e) { log.info("Can NOT build metadata provider for entityId: {}", entityId); throw new EaafConfigurationException("module.eidasauth.04", new Object[] { entityId, e.getMessage() }, e); } } catch (final EaafException e) { log.info("Can NOT initialize Metadata signature-verification filter. Reason: " + e.getMessage()); throw new EaafConfigurationException("config.27", new Object[] { "Can NOT initialize Metadata signature-verification filter. Reason: " + e .getMessage() }, e); } } else { log.info("No ServiceProvider with entityId: " + entityId + " in configuration."); } return null; } @Override protected List getAllMetadataUrlsFromConfiguration() throws EaafConfigurationException { return Collections.emptyList(); } @Override protected String getMetadataProviderId() { return "Service-provider chainging metadata provider"; } @Override public void doDestroy() { this.fullyDestroy(); } }