diff options
author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-02-21 16:22:31 +0100 |
---|---|---|
committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-02-21 16:22:31 +0100 |
commit | 7ba8da297b7be40255ba5efb40c69a21fb130b3b (patch) | |
tree | 14294d39790209235180d6a1de48539e163e7ebf /connector | |
parent | d5f104bf22d204732897ef7127ad704d43d7a194 (diff) | |
download | National_eIDAS_Gateway-7ba8da297b7be40255ba5efb40c69a21fb130b3b.tar.gz National_eIDAS_Gateway-7ba8da297b7be40255ba5efb40c69a21fb130b3b.tar.bz2 National_eIDAS_Gateway-7ba8da297b7be40255ba5efb40c69a21fb130b3b.zip |
update to latest EAAF-components that uses OpenSAML3.x
Diffstat (limited to 'connector')
12 files changed, 181 insertions, 324 deletions
diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringInitializer.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringInitializer.java index 76802825..417828a6 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringInitializer.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringInitializer.java @@ -48,7 +48,7 @@ import at.gv.egiz.components.spring.api.SpringLoader; import at.gv.egiz.eaaf.core.api.IStatusMessenger; import at.gv.egiz.eaaf.core.impl.logging.LogMessageProviderFactory; import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafDefaultSaml2Bootstrap; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; /** * Web application initializer. @@ -156,7 +156,7 @@ public class SpringInitializer implements WebApplicationInitializer { LogMessageProviderFactory.setStatusMessager(rootContext.getBean(IStatusMessenger.class)); log.info("Bootstrap openSAML .... "); - EaafDefaultSaml2Bootstrap.bootstrap(); + EaafOpenSaml3xInitializer.eaafInitialize(); log.info("Seed random number generator ... "); Random.seedRandom(); diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/config/PvpEndPointConfiguration.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/config/PvpEndPointConfiguration.java index fb7cb625..82be730c 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/config/PvpEndPointConfiguration.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/config/PvpEndPointConfiguration.java @@ -25,8 +25,8 @@ package at.asitplus.eidas.specific.connector.config; import java.util.List; -import org.opensaml.saml2.metadata.ContactPerson; -import org.opensaml.saml2.metadata.Organization; +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.Organization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -63,7 +63,7 @@ public class PvpEndPointConfiguration implements IPvp2BasicConfiguration { } @Override - public Object getIdpSsoSoapService(String extractAuthUrlFromRequest) throws EaafException { + public String getIdpSsoSoapService(String extractAuthUrlFromRequest) throws EaafException { log.warn("PVP S-Profile End-Point does NOT support SOAP Binding"); return null; @@ -81,6 +81,11 @@ public class PvpEndPointConfiguration implements IPvp2BasicConfiguration { return null; } + @Override + public IConfiguration getBasicConfiguration() { + return basicConfiguration; + } + private String removePostFix(String url) { if (url != null && url.endsWith("/")) { return url.substring(0, url.length() - 1); diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/config/PvpMetadataConfiguration.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/config/PvpMetadataConfiguration.java index f1828f87..0fc061ff 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/config/PvpMetadataConfiguration.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/config/PvpMetadataConfiguration.java @@ -26,12 +26,11 @@ package at.asitplus.eidas.specific.connector.config; import java.util.Arrays; import java.util.List; -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.core.NameIDType; -import org.opensaml.saml2.metadata.ContactPerson; -import org.opensaml.saml2.metadata.Organization; -import org.opensaml.saml2.metadata.RequestedAttribute; -import org.opensaml.xml.security.credential.Credential; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.Organization; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,17 +38,18 @@ import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.modules.pvp2.api.IPvp2BasicConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpAttributeBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; public class PvpMetadataConfiguration implements IPvpMetadataBuilderConfiguration { private static final Logger log = LoggerFactory.getLogger(PvpMetadataConfiguration.class); private final IConfiguration basicConfig; private final String authUrl; - private final AbstractCredentialProvider pvpIdpCredentials; + private final IPvp2CredentialProvider pvpIdpCredentials; private final IPvp2BasicConfiguration pvpBasicConfig; /** @@ -58,12 +58,12 @@ public class PvpMetadataConfiguration implements IPvpMetadataBuilderConfiguratio * @param basicConfig Application configuration * @param authUrl Public-URL Prefix of the application * @param pvpBasicConfig PVP2 configuration object - * @param pvpIdpCredentials PVP2 credentials + * @param pvpIdpCredentials2 PVP2 credentials */ public PvpMetadataConfiguration(IConfiguration basicConfig, String authUrl, - IPvp2BasicConfiguration pvpBasicConfig, AbstractCredentialProvider pvpIdpCredentials) { + IPvp2BasicConfiguration pvpBasicConfig, IPvp2CredentialProvider pvpIdpCredentials2) { this.authUrl = authUrl; - this.pvpIdpCredentials = pvpIdpCredentials; + this.pvpIdpCredentials = pvpIdpCredentials2; this.basicConfig = basicConfig; this.pvpBasicConfig = pvpBasicConfig; @@ -145,19 +145,19 @@ public class PvpMetadataConfiguration implements IPvpMetadataBuilderConfiguratio } @Override - public Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException { - return pvpIdpCredentials.getIdpMetaDataSigningCredential(); + public EaafX509Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException { + return pvpIdpCredentials.getMetaDataSigningCredential(); } @Override - public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException { - return pvpIdpCredentials.getIdpAssertionSigningCredential(); + public EaafX509Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException { + return pvpIdpCredentials.getMessageSigningCredential(); } @Override - public Credential getEncryptionCredentials() throws CredentialsNotAvailableException { + public EaafX509Credential getEncryptionCredentials() throws CredentialsNotAvailableException { return null; } diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java index 2776ec53..633559de 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java @@ -29,12 +29,12 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.transform.TransformerFactoryConfigurationError; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringEscapeUtils; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.CloseableHttpClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -49,6 +49,7 @@ import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; import at.gv.egiz.eaaf.core.impl.utils.Random; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; @@ -73,6 +74,8 @@ public class MonitoringController { @Autowired private IConfigurationWithSP config; + @Autowired private IHttpClientFactory httpClientFactory; + @Autowired private PvpMetadataBuilder metadatabuilder; @Autowired @@ -248,17 +251,11 @@ public class MonitoringController { // create HTTP client // TODO: update if we switch to openSAML3 - final HttpClient httpClient = new HttpClient(); + CloseableHttpClient httpClient = httpClientFactory.getHttpClient(); + HttpUriRequest request = new HttpGet(urlString); - // set parameters - final HttpClientParams params = new HttpClientParams(); - params.setSoTimeout(5 * 1000); - httpClient.setParams(params); - - // request URL - final HttpMethod method = new GetMethod(urlString); - final int respCode = httpClient.executeMethod(method); - if (respCode != 200) { + final CloseableHttpResponse respCode = httpClient.execute(request); + if (respCode.getStatusLine().getStatusCode() != 200) { log.warn("Monitoring: Has an error in '" + TEST_EIDASNODEMETADATA + "': " + " HTTP responsecode: " + respCode); throw new Exception(TEST_EIDASNODEMETADATA + MESSAGE_ERROR); @@ -266,7 +263,7 @@ public class MonitoringController { } // parse metadata - DomUtils.parseXmlNonValidating(method.getResponseBodyAsStream()); + DomUtils.parseXmlNonValidating(respCode.getEntity().getContent()); return TEST_EIDASNODEMETADATA + MESSAGE_OK; diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpEndPointCredentialProvider.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpEndPointCredentialProvider.java index 92373328..0ae5f76d 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpEndPointCredentialProvider.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpEndPointCredentialProvider.java @@ -23,9 +23,6 @@ package at.asitplus.eidas.specific.connector.provider; -import java.net.MalformedURLException; - -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -33,8 +30,8 @@ import org.springframework.beans.factory.annotation.Autowired; import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; 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.utils.FileUtils; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; public class PvpEndPointCredentialProvider extends AbstractCredentialProvider { @@ -44,41 +41,25 @@ public class PvpEndPointCredentialProvider extends AbstractCredentialProvider { IConfiguration basicConfiguration; @Override - public String getFriendlyName() { - return "PVP2 S-Profile EndPoint"; - } - - @Override - public String getKeyStoreFilePath() throws EaafException { - try { - final String path = basicConfiguration.getBasicConfiguration( - MsEidasNodeConstants.PROP_CONFIG_PVP2_KEYSTORE_PATH); - if (StringUtils.isEmpty(path)) { - log.error(getFriendlyName() + " | Path to keyStore is NULL or EMPTY"); - throw new EaafConfigurationException("config.27", - new Object[] { getFriendlyName() + " | Path to keyStore is NULL or EMPTY" }); - - } - - return FileUtils.makeAbsoluteUrl( - path, - basicConfiguration.getConfigurationRootDirectory()); - - } catch (final MalformedURLException e) { - log.error(getFriendlyName() + " | Path to keyStore NOT valid.", e); - throw new EaafConfigurationException("config.27", - new Object[] { getFriendlyName() + " | Path to keyStore NOT valid." }, e); - - } - - } - - @Override - public String getKeyStorePassword() { - return basicConfiguration.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_PVP2_KEYSTORE_PASSWORD); - + public KeyStoreConfiguration getBasicKeyStoreConfig() throws EaafConfigurationException { + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setFriendlyName("PVP2 S-Profile EndPoint"); + keyStoreConfig.setKeyStoreType( + basicConfiguration.getBasicConfiguration(MsEidasNodeConstants.CONFIG_PROPS_KEYSTORE_TYPE, + KeyStoreType.PKCS12.getKeyStoreType())); + keyStoreConfig.setKeyStoreName( + basicConfiguration.getBasicConfiguration(MsEidasNodeConstants.CONFIG_PROPS_KEYSTORE_NAME)); + keyStoreConfig.setSoftKeyStoreFilePath(basicConfiguration.getBasicConfiguration( + MsEidasNodeConstants.PROP_CONFIG_PVP2_KEYSTORE_PATH)); + keyStoreConfig.setSoftKeyStorePassword( + basicConfiguration.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_PVP2_KEYSTORE_PASSWORD)); + + keyStoreConfig.validate(); + + return keyStoreConfig; } - + + @Override public String getMetadataKeyAlias() { return basicConfiguration.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_PVP2_KEY_METADATA_ALIAS); diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataConfigurationFactory.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataConfigurationFactory.java index 8b0419d0..e8bc4eb8 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataConfigurationFactory.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataConfigurationFactory.java @@ -31,7 +31,7 @@ import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.modules.pvp2.api.IPvp2BasicConfiguration; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; @Service("PVPMetadataConfigurationFactory") public class PvpMetadataConfigurationFactory implements IPvpMetadataConfigurationFactory { @@ -43,9 +43,9 @@ public class PvpMetadataConfigurationFactory implements IPvpMetadataConfiguratio @Override public IPvpMetadataBuilderConfiguration generateMetadataBuilderConfiguration(String authUrl, - AbstractCredentialProvider pvpIdpCredentials) { + IPvp2CredentialProvider pvpIdpCredentials) { return new PvpMetadataConfiguration(basicConfig, authUrl, pvpBasicConfig, pvpIdpCredentials); - + } } diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataProvider.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataProvider.java index 6a223fd0..7738b0be 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataProvider.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataProvider.java @@ -24,38 +24,60 @@ package at.asitplus.eidas.specific.connector.provider; import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.Provider; import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.text.MessageFormat; +import java.util.ArrayList; import java.util.List; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.commons.lang3.StringUtils; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.xml.parse.BasicParserPool; +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.opensaml.security.x509.BasicX509Credential; 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.asitplus.eidas.specific.connector.verification.MetadataSignatureVerificationFilter; 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.impl.utils.FileUtils; +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.EaafKeyStoreUtils; +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.utils.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.MetadataFilterChain; +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); @@ -80,7 +102,7 @@ public class PvpMetadataProvider extends AbstractChainingMetadataProvider { } @Override - protected MetadataProvider createNewMetadataProvider(String entityId) + protected MetadataResolver createNewMetadataProvider(String entityId) throws EaafConfigurationException, IOException, CertificateException { final ISpConfiguration spConfig = basicConfig.getServiceProviderConfiguration(entityId); if (spConfig != null) { @@ -92,20 +114,44 @@ public class PvpMetadataProvider extends AbstractChainingMetadataProvider { metadataUrl = entityId; } - final String trustStoreUrl = FileUtils.makeAbsoluteUrl( - spConfig.getConfigurationValue(MsEidasNodeConstants.PROP_CONFIG_SP_PVP2_METADATA_TRUSTSTORE), - authConfig.getConfigurationRootDirectory()); - final String trustStorePassword = spConfig.getConfigurationValue( - MsEidasNodeConstants.PROP_CONFIG_SP_PVP2_METADATA_TRUSTSTORE_PASSWORD); - - return createNewSimpleMetadataProvider(metadataUrl, - buildMetadataFilterChain(metadataUrl, trustStoreUrl, trustStorePassword), - spConfig.getConfigurationValue(MsEidasNodeConstants.PROP_CONFIG_SP_UNIQUEIDENTIFIER), - getTimer(), - new BasicParserPool(), - createHttpClient()); - - } catch (final Pvp2MetadataException e) { + + 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, Provider> keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + filterList.add(new SimpleMetadataSignatureVerificationFilter( + getTrustedCertificates(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 @@ -122,34 +168,37 @@ public class PvpMetadataProvider extends AbstractChainingMetadataProvider { @Override protected List<String> getAllMetadataUrlsFromConfiguration() throws EaafConfigurationException { - // TODO Auto-generated method stub return null; } - private HttpClient createHttpClient() { - final HttpClient httpClient = new HttpClient(); - final HttpClientParams httpClientParams = new HttpClientParams(); - httpClientParams.setSoTimeout(MsEidasNodeConstants.METADATA_SOCKED_TIMEOUT); - httpClient.setParams(httpClientParams); - return httpClient; - + @Override + protected String getMetadataProviderId() { + return "Service-provider chainging metadata provider"; + } + + private List<BasicX509Credential> getTrustedCertificates(KeyStore trustStore) throws EaafConfigurationException { + try { + final List<X509Certificate> certs = + EaafKeyStoreUtils.readCertsFromKeyStore(trustStore); + if (certs.isEmpty()) { + log.warn("No trusted metadata-signing certificates in configuration"); + throw new EaafConfigurationException("module.eidasauth.02", + new Object[] { "No trusted metadata-signing certificates" }); - private MetadataFilterChain buildMetadataFilterChain(String metadataUrl, - String trustStoreUrl, String trustStorePassword) throws CertificateException, Pvp2MetadataException { - final MetadataFilterChain filterChain = new MetadataFilterChain(); - filterChain.getFilters().add(new SchemaValidationFilter( - basicConfig.getBasicConfigurationBoolean(MsEidasNodeConstants.PROP_CONFIG_PVP_SCHEME_VALIDATION, - true))); + } - filterChain.getFilters().add( - new MetadataSignatureVerificationFilter( - trustStoreUrl, trustStorePassword, metadataUrl)); + final List<BasicX509Credential> result = new ArrayList<>(); + for (final X509Certificate cert : certs) { + result.add(new BasicX509Credential(cert)); - filterChain.getFilters().add(new PvpEntityCategoryFilter( - basicConfig.getBasicConfigurationBoolean(MsEidasNodeConstants.PROP_CONFIG_PVP_ENABLE_ENTITYCATEGORIES, - true))); + } + return result; + + } catch (final KeyStoreException e) { + throw new EaafConfigurationException("module.eidasauth.01", + new Object[] { "Trusted metadata-signing certificates", e.getMessage() }, e); - return filterChain; + } } } diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java index 482e6761..26176c49 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java @@ -29,15 +29,15 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.NameIDPolicy; -import org.opensaml.saml2.core.NameIDType; -import org.opensaml.saml2.core.RequestedAuthnContext; -import org.opensaml.saml2.core.Scoping; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.xml.XMLObject; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.saml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.NameIDPolicy; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml.saml2.core.Scoping; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/MetadataSignatureVerificationFilter.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/MetadataSignatureVerificationFilter.java deleted file mode 100644 index b6dd249a..00000000 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/MetadataSignatureVerificationFilter.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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.verification; - -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.cert.Certificate; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; - -import org.opensaml.common.SignableSAMLObject; -import org.opensaml.saml2.metadata.EntitiesDescriptor; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.security.SAMLSignatureProfileValidator; -import org.opensaml.xml.security.x509.BasicX509Credential; -import org.opensaml.xml.signature.SignatureValidator; -import org.opensaml.xml.validation.ValidationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.gv.egiz.eaaf.core.exceptions.EaafException; -import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils; -import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; -import at.gv.egiz.eaaf.modules.pvp2.idp.exception.SamlRequestNotSignedException; -import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.AbstractMetadataSignatureFilter; - -public class MetadataSignatureVerificationFilter extends AbstractMetadataSignatureFilter { - private static final Logger log = LoggerFactory.getLogger(MetadataSignatureVerificationFilter.class); - - private final String metadataUrl; - private final List<BasicX509Credential> trustedCredential = new ArrayList<>(); - - /** - * SAML2 Metadata signature verifier that checks signer certificates based on local TrustStores. - * - * @param trustStorePath Path to truststore - * @param trustStorePassword TrustStore password - * @param metadataUrl URL to PVP2 metadata - * @throws Pvp2MetadataException In case of a verification error - */ - public MetadataSignatureVerificationFilter(String trustStorePath, String trustStorePassword, - String metadataUrl) - throws Pvp2MetadataException { - this.metadataUrl = metadataUrl; - - log.trace("Initialize metadata signature-verification filter with truststore: " + trustStorePath - + " ... "); - try { - final KeyStore keyStore = KeyStoreUtils.loadKeyStore(trustStorePath, trustStorePassword); - if (keyStore != null) { - // load trusted certificates - final Enumeration<String> aliases = keyStore.aliases(); - while (aliases.hasMoreElements()) { - final String el = aliases.nextElement(); - log.trace("Process TrustStoreEntry: " + el); - if (keyStore.isCertificateEntry(el)) { - final Certificate cert = keyStore.getCertificate(el); - if (cert != null && cert instanceof X509Certificate) { - final BasicX509Credential trustedCert = new BasicX509Credential(); - trustedCert.setEntityCertificate((X509Certificate) cert); - this.trustedCredential.add(trustedCert); - log.debug("Add cert: " + ((X509Certificate) cert).getSubjectDN() + " as trusted for metadata: " - + metadataUrl); - - } else { - log.info("Can not process entry: " + el + ". Reason: is null"); - } - - } - } - - } else { - throw new Pvp2MetadataException("pvp2.26", - new Object[] { "Can not open trustStore: " + trustStorePath + " for metadata: " + metadataUrl }); - } - - } catch (KeyStoreException | IOException e) { - log.warn("Can not open trustStore: " + trustStorePath + " for metadata: " + metadataUrl + " Reason: " - + e.getMessage(), e); - throw new Pvp2MetadataException("pvp2.26", - new Object[] { "Can not open trustStore: " + trustStorePath + " for metadata" }, e); - - } - - } - - @Override - protected void verify(EntityDescriptor desc) throws Pvp2MetadataException { - try { - internalVerify(desc); - - } catch (final EaafException e) { - log.info("Metadata verification FAILED for: " + metadataUrl + " Reason: " + e.getMessage()); - throw new Pvp2MetadataException("pvp2.26", - new Object[] { "Metadata verification FAILED for: " + metadataUrl + " Reason: " + e.getMessage() }, - e); - - } - } - - @Override - protected void verify(EntitiesDescriptor desc) throws Pvp2MetadataException { - throw new Pvp2MetadataException("pvp2.26", - new Object[] { "EntitiesDescritors are NOT supported" }); - - } - - @Override - protected void verify(EntityDescriptor entity, EntitiesDescriptor desc) throws Pvp2MetadataException { - throw new Pvp2MetadataException("pvp2.26", - new Object[] { "EntitiesDescritors are NOT supported" }); - - } - - private void internalVerify(SignableSAMLObject signedElement) - throws EaafException { - if (signedElement.getSignature() == null) { - throw new SamlRequestNotSignedException(); - } - - try { - final SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator(); - sigValidator.validate(signedElement.getSignature()); - } catch (final ValidationException e) { - log.error("Failed to validate Signature", e); - throw new SamlRequestNotSignedException(e); - } - - boolean isTrusted = false; - for (final BasicX509Credential cred : trustedCredential) { - final SignatureValidator sigValidator = new SignatureValidator(cred); - try { - sigValidator.validate(signedElement.getSignature()); - isTrusted = true; - - } catch (final ValidationException e) { - log.info("Failed to verfiy Signature with cert: " + cred.getEntityCertificate().getSubjectDN() - + " Reason: " + e.getMessage()); - - } - } - - if (!isTrusted) { - log.warn("PVP2 metadata: " + metadataUrl + " are NOT trusted!"); - throw new SamlRequestNotSignedException(); - - } - - } - -} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthnRequestValidatorTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthnRequestValidatorTest.java index db863815..e34c8036 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthnRequestValidatorTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthnRequestValidatorTest.java @@ -12,11 +12,11 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.xml.ConfigurationException; -import org.opensaml.xml.io.Unmarshaller; -import org.opensaml.xml.io.UnmarshallerFactory; -import org.opensaml.xml.io.UnmarshallingException; +import org.opensaml.core.config.InitializationException; +import org.opensaml.core.xml.io.Unmarshaller; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.saml2.core.AuthnRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -38,7 +38,8 @@ import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; import at.gv.egiz.eaaf.core.impl.utils.DomUtils; import at.gv.egiz.eaaf.modules.pvp2.api.validation.IAuthnRequestPostProcessor; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafDefaultSaml2Bootstrap; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ @@ -61,15 +62,16 @@ public class AuthnRequestValidatorTest { /** * jUnit class initializer. - * @throws ConfigurationException In case of an error + * @throws ComponentInitializationException In case of an error + * @throws InitializationException In case of an error * */ @BeforeClass - public static void classInitializer() throws ConfigurationException { + public static void classInitializer() throws InitializationException, ComponentInitializationException { final String current = new java.io.File(".").toURI().toString(); System.setProperty("eidas.ms.configuration", current + "src/test/resources/config/junit_config_1.properties"); - EaafDefaultSaml2Bootstrap.bootstrap(); + EaafOpenSaml3xInitializer.eaafInitialize(); } /** @@ -286,9 +288,7 @@ public class AuthnRequestValidatorTest { final Element authBlockDom = DomUtils.parseXmlValidating(AuthnRequestValidatorTest.class.getResourceAsStream(resource)); - final UnmarshallerFactory unmarshallerFactory = - org.opensaml.xml.Configuration.getUnmarshallerFactory(); - final Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(authBlockDom); + final Unmarshaller unmarshaller = XMLObjectSupport.getUnmarshaller(authBlockDom); return (AuthnRequest) unmarshaller.unmarshall(authBlockDom); } diff --git a/connector/src/test/resources/config/junit_config_1.properties b/connector/src/test/resources/config/junit_config_1.properties index 3f290948..982d3e24 100644 --- a/connector/src/test/resources/config/junit_config_1.properties +++ b/connector/src/test/resources/config/junit_config_1.properties @@ -39,8 +39,8 @@ eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/sub eidas.ms.auth.eIDAS.szrclient.useTestService=true eidas.ms.auth.eIDAS.szrclient.endpoint.prod= eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr -eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/..... -eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password= +eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/junit.jks +eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=password eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path= eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password= eidas.ms.auth.eIDAS.szrclient.timeout.connection=15 @@ -80,8 +80,8 @@ eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true ## PVP2 S-Profile end-point configuration -eidas.ms.pvp2.keystore.path=keys/..... -eidas.ms.pvp2.keystore.password= +eidas.ms.pvp2.keystore.path=keys/junit.jks +eidas.ms.pvp2.keystore.password=password eidas.ms.pvp2.key.metadata.alias= eidas.ms.pvp2.key.metadata.password= eidas.ms.pvp2.key.signing.alias= @@ -90,8 +90,8 @@ eidas.ms.pvp2.metadata.validity=24 ## Service Provider configuration eidas.ms.sp.0.uniqueID= -eidas.ms.sp.0.pvp2.metadata.truststore= -eidas.ms.sp.0.pvp2.metadata.truststore.password= +eidas.ms.sp.0.pvp2.metadata.truststore=keys/junit.jks +eidas.ms.sp.0.pvp2.metadata.truststore.password=password #eidas.ms.sp.0.friendlyName= #eidas.ms.sp.0.pvp2.metadata.url= diff --git a/connector/src/test/resources/config/keys/junit.jks b/connector/src/test/resources/config/keys/junit.jks Binary files differnew file mode 100644 index 00000000..59e6ad13 --- /dev/null +++ b/connector/src/test/resources/config/keys/junit.jks |