diff options
Diffstat (limited to 'connector/src')
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.jksBinary files differ new file mode 100644 index 00000000..59e6ad13 --- /dev/null +++ b/connector/src/test/resources/config/keys/junit.jks | 
