package at.asitplus.eidas.specific.modules.auth.idaustria.utils; 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 javax.annotation.PostConstruct; 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.springframework.beans.factory.annotation.Autowired; import at.asitplus.eidas.specific.modules.auth.idaustria.IdAustriaAuthConstants; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; 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.SchemaValidationFilter; import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SimpleMetadataSignatureVerificationFilter; import lombok.extern.slf4j.Slf4j; /** * SAML2 metadata-provider implementation for ID Austria client. * * @author tlenz * */ @Slf4j public class IdAustriaAuthMetadataProvider extends AbstractChainingMetadataProvider { private static final String FRIENDLYNAME_METADATA_TRUSTSTORE = "'ID Austria client-metadata truststore'"; private static final String PROVIDER_ID_PATTERN = "ID Austria resolver: {0}"; public static final String PROVIDER_ID = "ID Austria_client metadata provider'"; @Autowired private IConfiguration basicConfig; @Autowired private PvpMetadataResolverFactory metadataProviderFactory; @Autowired private IHttpClientFactory httpClientFactory; @Autowired private EaafKeyStoreFactory keyStoreFactory; private Pair metadataSigningTrustStore; @Override protected String getMetadataUrl(String entityId) throws EaafConfigurationException { log.trace("ID Austria uses SAML2 well-known location approach. EntityId is Metadata-URL"); return entityId; } @Override protected MetadataResolver createNewMetadataProvider(String entityId) throws EaafConfigurationException, IOException, CertificateException { final List filterList = new ArrayList<>(); filterList.add(new SchemaValidationFilter(true)); filterList.add(new SimpleMetadataSignatureVerificationFilter( metadataSigningTrustStore.getFirst(), entityId)); 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(IdAustriaAuthConstants.ERRORTYPE_04, new Object[] { entityId, e.getMessage() }, e); } } @Override protected List getAllMetadataUrlsFromConfiguration() throws EaafConfigurationException { return Collections.emptyList(); } @Override protected String getMetadataProviderId() { return PROVIDER_ID; } @Override public void runGarbageCollector() { log.trace("Garbage collection is NOT supported by: {}", getId()); } @Override public void doDestroy() { super.fullyDestroy(); } @PostConstruct private void initialize() throws EaafException { // initialize truststore to validate metadata signing certificates initializeTrustStore(); // load metadata with metadataURL, as backup initializeFileSystemMetadata(); } private void initializeFileSystemMetadata() { try { final String metadataUrl = basicConfig.getBasicConfiguration( IdAustriaAuthConstants.CONFIG_PROPS_IDAUSTRIA_METADATAURL); if (StringUtils.isNotEmpty(metadataUrl)) { log.info("Use not recommended metadata-provider initialization!" + " SAML2 'Well-Known-Location' is the preferred methode."); log.info("Initialize 'ID Austria' metadata-provider with URL: {}", metadataUrl); addMetadataResolverIntoChain(createNewMetadataProvider(metadataUrl)); } } catch (final EaafConfigurationException | CertificateException | IOException e) { log.warn("Can NOT inject static eIDAS Node metadata-soure.", e); log.warn("Communication with ID Austria can be FAIL."); } } private void initializeTrustStore() throws EaafException { // set configuration final KeyStoreConfiguration trustStoreConfig = new KeyStoreConfiguration(); trustStoreConfig.setFriendlyName(FRIENDLYNAME_METADATA_TRUSTSTORE); trustStoreConfig.setKeyStoreType(basicConfig.getBasicConfiguration( IdAustriaAuthConstants.CONFIG_PROPS_TRUSTSTORE_TYPE, KeyStoreType.JKS.getKeyStoreType())); trustStoreConfig.setKeyStoreName(basicConfig.getBasicConfiguration( IdAustriaAuthConstants.CONFIG_PROPS_TRUSTSTORE_NAME)); trustStoreConfig.setSoftKeyStoreFilePath(basicConfig.getBasicConfiguration( IdAustriaAuthConstants.CONFIG_PROPS_TRUSTSTORE_PATH)); trustStoreConfig.setSoftKeyStorePassword(basicConfig.getBasicConfiguration( IdAustriaAuthConstants.CONFIG_PROPS_TRUSTSTORE_PASSWORD)); // validate configuration trustStoreConfig.validate(); // open new TrustStore metadataSigningTrustStore = keyStoreFactory.buildNewKeyStore(trustStoreConfig); } }