diff options
Diffstat (limited to 'eaaf_modules')
13 files changed, 314 insertions, 221 deletions
| diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java index f607f8cb..11fd41fb 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java @@ -7,17 +7,37 @@ public class Constants {    public static final String CONFIG_PROP_VDA_AUTHBLOCK_TRANSFORMATION_ID = CONFIG_PROP_PREFIX        + ".vda.authblock.transformation.id"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH = CONFIG_PROP_PREFIX + ".security.keystore.path"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD = CONFIG_PROP_PREFIX -      + ".security.keystore.password"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS = CONFIG_PROP_PREFIX + ".security.sign.alias"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD = CONFIG_PROP_PREFIX -      + ".security.sign.password"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS = CONFIG_PROP_PREFIX -      + ".security.encryption.alias"; -  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD = CONFIG_PROP_PREFIX -      + ".security.encryption.password"; +   +  //KeyStore configuration +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_TYPE =  +      CONFIG_PROP_PREFIX + ".security.keystore.type"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_NAME =  +      CONFIG_PROP_PREFIX + ".security.keystore.name"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH =  +      CONFIG_PROP_PREFIX + ".security.keystore.path"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD =  +      CONFIG_PROP_PREFIX + ".security.keystore.password"; +   +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS =  +      CONFIG_PROP_PREFIX + ".security.sign.alias"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD =  +      CONFIG_PROP_PREFIX + ".security.sign.password"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS =  +      CONFIG_PROP_PREFIX + ".security.encryption.alias"; +  public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD =  +      CONFIG_PROP_PREFIX + ".security.encryption.password"; +  //TrustStore configuration +  public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE =  +      CONFIG_PROP_PREFIX + ".security.truststore.type"; +  public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_NAME =  +      CONFIG_PROP_PREFIX + ".security.truststore.name"; +  public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PATH =  +      CONFIG_PROP_PREFIX + ".security.truststore.path"; +  public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD =  +      CONFIG_PROP_PREFIX + ".security.truststore.password"; +   +      public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT = "default";    public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_VDA_ENDPOINT_QUALeID        + CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT; diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java index 0d2c1815..259c21bf 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java @@ -1,17 +1,12 @@  package at.gv.egiz.eaaf.modules.auth.sl20.utils;  import java.io.IOException; -import java.net.MalformedURLException;  import java.security.Key;  import java.security.KeyStore;  import java.security.KeyStoreException; -import java.security.PrivateKey; -import java.security.cert.Certificate;  import java.security.cert.CertificateEncodingException;  import java.security.cert.X509Certificate; -import java.util.ArrayList;  import java.util.Collections; -import java.util.Enumeration;  import java.util.List;  import javax.annotation.Nonnull; @@ -38,9 +33,13 @@ import com.fasterxml.jackson.core.JsonParseException;  import com.fasterxml.jackson.databind.JsonNode;  import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exception.EaafKeyAccessException;  import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; -import at.gv.egiz.eaaf.core.impl.utils.FileUtils; -import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils; +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.X509Utils;  import at.gv.egiz.eaaf.modules.auth.sl20.Constants;  import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; @@ -53,88 +52,60 @@ import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException;  public class JsonSecurityUtils implements IJoseTools {    private static final Logger log = LoggerFactory.getLogger(JsonSecurityUtils.class); -  @Autowired(required = true) -  IConfiguration authConfig; -  private Key signPrivKey = null; -  private X509Certificate[] signCertChain = null; - -  private Key encPrivKey = null; -  private X509Certificate[] encCertChain = null; - -  private List<X509Certificate> trustedCerts = new ArrayList<>(); - +  private static final String FRIENDLYNAME_KEYSTORE = "SL2.0 KeyStore"; +  private static final String FRIENDLYNAME_TRUSTSTORE = "SL2.0 TrustStore"; +   +  @Autowired(required = true) IConfiguration authConfig; +  @Autowired(required = true) EaafKeyStoreFactory keystoreFactory; +   +  private KeyStore keyStore; +  private KeyStore trustStore; +     private static JsonMapper mapper = new JsonMapper();    @PostConstruct -  protected void initalize() { +  protected void initalize() throws SL20Exception {      log.info("Initialize SL2.0 authentication security constrains ... ");      try { -      if (getKeyStoreFilePath() != null) { -        final KeyStore keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(), getKeyStorePassword()); - -        // load signing key -        signPrivKey = keyStore.getKey(getSigningKeyAlias(), getSigningKeyPassword().toCharArray()); -        final Certificate[] certChainSigning = keyStore.getCertificateChain(getSigningKeyAlias()); -        signCertChain = new X509Certificate[certChainSigning.length]; -        for (int i = 0; i < certChainSigning.length; i++) { -          if (certChainSigning[i] instanceof X509Certificate) { -            signCertChain[i] = (X509Certificate) certChainSigning[i]; -          } else { -            log.warn("NO X509 certificate for signing: " + certChainSigning[i].getType()); -          } - -        } - -        // load encryption key -        try { -          encPrivKey = keyStore.getKey(getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray()); -          if (encPrivKey != null) { -            final Certificate[] certChainEncryption = keyStore.getCertificateChain(getEncryptionKeyAlias()); -            encCertChain = new X509Certificate[certChainEncryption.length]; -            for (int i = 0; i < certChainEncryption.length; i++) { -              if (certChainEncryption[i] instanceof X509Certificate) { -                encCertChain[i] = (X509Certificate) certChainEncryption[i]; -              } else { -                log.warn("NO X509 certificate for encryption: " + certChainEncryption[i].getType()); -              } -            } -          } else { -            log.info("No encryption key for SL2.0 found. End-to-End encryption is not used."); -          } - -        } catch (final Exception e) { -          log.warn("No encryption key for SL2.0 found. End-to-End encryption is not used. Reason: " + e.getMessage(), -              e); - -        } - -        // load trusted certificates -        trustedCerts = readCertsFromKeyStore(keyStore); - -        // some short validation -        if (signPrivKey == null || !(signPrivKey instanceof PrivateKey)) { -          log.info("Can NOT open privateKey for SL2.0 signing. KeyStore=" + getKeyStoreFilePath()); -          throw new SL20Exception("sl20.03", new Object[] { "Can NOT open private key for signing" }); - -        } - -        if (signCertChain == null || signCertChain.length == 0) { -          log.info("NO certificate for SL2.0 signing. KeyStore=" + getKeyStoreFilePath()); -          throw new SL20Exception("sl20.03", new Object[] { "NO certificate for SL2.0 signing" }); - -        } - -        log.info("SL2.0 authentication security constrains initialized."); - +      //load KeyStore +      KeyStoreConfiguration keyStoreConfig = buildKeyStoreConfiguration(); +      keyStore = keystoreFactory.buildNewKeyStore(keyStoreConfig); +       +      //load TrustStore +      KeyStoreConfiguration trustStoreConfig = buildTrustStoreConfiguration(); +      trustStore = keystoreFactory.buildNewKeyStore(trustStoreConfig); +       +      //validate KeyStore entries +      EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore, getSigningKeyAlias(),  +              getSigningKeyPassword(), true, FRIENDLYNAME_KEYSTORE); +      Pair<Key, X509Certificate[]> encCredentials =  +          EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore, getEncryptionKeyAlias(),  +              getEncryptionKeyPassword(), false, FRIENDLYNAME_TRUSTSTORE); +      if (encCredentials == null) { +        log.info("No encryption key for SL2.0 found. End-to-End encryption is not used."); +         +      } +       +      //validate TrustStore +      List<X509Certificate> trustedCerts = EaafKeyStoreUtils.readCertsFromKeyStore(trustStore); +      if (trustedCerts.isEmpty()) { +        log.info("No certificates in TrustStore: {}. Signature validation will FAIL!",  +            FRIENDLYNAME_TRUSTSTORE); +                } else { -        log.info("NO SL2.0 authentication security configuration. Initialization was skipped"); +        log.info("Find #{} certificates in TrustStore: {}",  +            trustedCerts.size(), FRIENDLYNAME_TRUSTSTORE); +            } +       +      log.info("SL2.0 authentication security constrains initialized.");      } catch (final RuntimeException e) {        throw e;      } catch (final Exception e) { -      log.error("SL2.0 security constrains initialization FAILED.", e); +      log.error("SL2.0 security constrains initialization FAILED."); +      throw new SL20Exception("sl20.11", new Object[] {e.getMessage()}, e);      } @@ -153,15 +124,18 @@ public class JsonSecurityUtils implements IJoseTools {        // set signing information        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); -      jws.setKey(signPrivKey); +      Pair<Key, X509Certificate[]> signingCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore,  +          getSigningKeyAlias(), getSigningKeyPassword(), true, FRIENDLYNAME_KEYSTORE); +       +      jws.setKey(signingCred.getFirst());        // TODO: -      jws.setCertificateChainHeaderValue(signCertChain); -      jws.setX509CertSha256ThumbprintHeaderValue(signCertChain[0]); +      jws.setCertificateChainHeaderValue(signingCred.getSecond()); +      jws.setX509CertSha256ThumbprintHeaderValue(signingCred.getSecond()[0]);        return jws.getCompactSerialization(); -    } catch (final JoseException e) { +    } catch (final JoseException | EaafKeyAccessException e) {        log.warn("Can NOT sign SL2.0 command.", e);        throw new SlCommandoBuildException("Can NOT sign SL2.0 command.", e); @@ -172,7 +146,7 @@ public class JsonSecurityUtils implements IJoseTools {    @Override    public VerificationResult validateSignature(final String serializedContent, final KeyStore trustStore,        final AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException { -    final List<X509Certificate> trustedCertificates = readCertsFromKeyStore(trustStore); +    final List<X509Certificate> trustedCertificates = EaafKeyStoreUtils.readCertsFromKeyStore(trustStore);      return validateSignature(serializedContent, trustedCertificates, algconstraints);    } @@ -244,7 +218,8 @@ public class JsonSecurityUtils implements IJoseTools {            SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING                .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()])); -      final VerificationResult result = validateSignature(serializedContent, trustedCerts, algConstraints); +      final VerificationResult result =  +          validateSignature(serializedContent, EaafKeyStoreUtils.readCertsFromKeyStore(trustStore), algConstraints);        if (!result.isValidSigned()) {          log.info("JWS signature invalide. Stopping authentication process ..."); @@ -256,7 +231,7 @@ public class JsonSecurityUtils implements IJoseTools {        log.debug("SL2.0 commando signature validation sucessfull");        return result; -    } catch (JoseException | JsonParseException e) { +    } catch (JoseException | JsonParseException | KeyStoreException e) {        log.warn("SL2.0 commando signature validation FAILED", e);        throw new SL20SecurityException(new Object[] { e.getMessage() }, e); @@ -284,6 +259,9 @@ public class JsonSecurityUtils implements IJoseTools {        // set payload        receiverJwe.setCompactSerialization(compactSerialization); +      Pair<Key, X509Certificate[]> encryptionCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore,  +          getEncryptionKeyAlias(), getEncryptionKeyPassword(), true, FRIENDLYNAME_KEYSTORE); +              // validate key from header against key from config        final List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue();        final String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue(); @@ -292,7 +270,7 @@ public class JsonSecurityUtils implements IJoseTools {          log.trace("Sorting received X509 certificates ... ");          final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); -        if (!sortedX5cCerts.get(0).equals(encCertChain[0])) { +        if (!sortedX5cCerts.get(0).equals(encryptionCred.getSecond()[0])) {            log.info("Certificate from JOSE header does NOT match encryption certificate");            try { @@ -307,7 +285,7 @@ public class JsonSecurityUtils implements IJoseTools {        } else if (StringUtils.isNotEmpty(x5t256)) {          log.debug("Found x5t256 fingerprint in JOSE header .... "); -        final String certFingerPrint = X509Util.x5tS256(encCertChain[0]); +        final String certFingerPrint = X509Util.x5tS256(encryptionCred.getSecond()[0]);          if (!certFingerPrint.equals(x5t256)) {            log.info("X5t256 from JOSE header does NOT match encryption certificate");            log.debug("X5t256 from JOSE header: " + x5t256 + " Encrytption cert: " + certFingerPrint); @@ -324,12 +302,12 @@ public class JsonSecurityUtils implements IJoseTools {        }        // set key -      receiverJwe.setKey(encPrivKey); +      receiverJwe.setKey(encryptionCred.getFirst());        // decrypt payload        return mapper.getMapper().readTree(receiverJwe.getPlaintextString()); -    } catch (final JoseException e) { +    } catch (final JoseException | EaafKeyAccessException e) {        log.warn("SL2.0 result decryption FAILED", e);        throw new SL20SecurityException(new Object[] { e.getMessage() }, e); @@ -340,37 +318,74 @@ public class JsonSecurityUtils implements IJoseTools {      } catch (final IOException e) {        log.warn("Decrypted SL2.0 result can not be parsed.", e);        throw new SlCommandoParserException("Decrypted SL2.0 result can not be parsed", e); +            } -    }    @Override    public X509Certificate getEncryptionCertificate() { -    // TODO: maybe update after SL2.0 update on encryption certificate parts -    if (encCertChain != null && encCertChain.length > 0) { -      return encCertChain[0]; -    } else { -      return null; +    Pair<Key, X509Certificate[]> encryptionCred; +    try { +      encryptionCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore,  +          getEncryptionKeyAlias(), getEncryptionKeyPassword(), false, FRIENDLYNAME_KEYSTORE); +      if (encryptionCred != null && encryptionCred.getSecond().length > 0) { +        return encryptionCred.getSecond()[0]; +         +      } +       +    } catch (EaafKeyAccessException e) { +      log.trace("Exception is skipped because Encryption is not mandatory on this level", e); +            } +     +    return null; +        } -  private String getKeyStoreFilePath() throws EaafConfigurationException, MalformedURLException { -    return FileUtils.makeAbsoluteUrl(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PATH), -        authConfig.getConfigurationRootDirectory()); +  private KeyStoreConfiguration buildKeyStoreConfiguration() throws EaafConfigurationException { +    KeyStoreConfiguration config = new KeyStoreConfiguration(); +    config.setFriendlyName(FRIENDLYNAME_KEYSTORE); +     +    config.setKeyStoreType(authConfig.getBasicConfiguration( +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_TYPE),  +        KeyStoreType.JKS.getKeyStoreType())); +    config.setKeyStoreName( +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_NAME)); +    config.setSoftKeyStoreFilePath( +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PATH)); +    config.setSoftKeyStorePassword( +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD)); +     +    //validate configuration state +    config.validate(); +     +    return config; +        } - -  private String getKeyStorePassword() { -    String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD); -    if (value != null) { -      value = value.trim(); -    } - -    return value; - +   +  private KeyStoreConfiguration buildTrustStoreConfiguration() throws EaafConfigurationException { +    KeyStoreConfiguration config = new KeyStoreConfiguration(); +    config.setFriendlyName(FRIENDLYNAME_TRUSTSTORE); +     +    config.setKeyStoreType(authConfig.getBasicConfiguration( +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE),  +        KeyStoreType.JKS.getKeyStoreType())); +    config.setKeyStoreName( +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_NAME)); +    config.setSoftKeyStoreFilePath( +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_PATH)); +    config.setSoftKeyStorePassword( +        authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD)); +     +    //validate configuration state +    config.validate(); +     +    return config;    } +      private String getSigningKeyAlias() { -    String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS).trim(); +    String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS);      if (value != null) {        value = value.trim();      } @@ -378,18 +393,17 @@ public class JsonSecurityUtils implements IJoseTools {      return value;    } -  private String getSigningKeyPassword() { -    String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD).trim(); +  private char[] getSigningKeyPassword() { +    String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD);      if (value != null) { -      value = value.trim(); +      return value.trim().toCharArray();      } -    return value; +    return null;    }    private String getEncryptionKeyAlias() { -    String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS) -        .trim(); +    String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS);      if (value != null) {        value = value.trim();      } @@ -397,36 +411,13 @@ public class JsonSecurityUtils implements IJoseTools {      return value;    } -  private String getEncryptionKeyPassword() { -    String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD) -        .trim(); +  private char[] getEncryptionKeyPassword() { +    String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD);      if (value != null) { -      value = value.trim(); -    } - -    return value; -  } - -  @Nonnull -  private List<X509Certificate> readCertsFromKeyStore(@Nonnull final KeyStore keyStore) throws KeyStoreException { -    final List<X509Certificate> result = new ArrayList<>(); - -    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) { -          result.add((X509Certificate) cert); -        } else { -          log.info("Can not process entry: {}. Reason: {}", el, cert != null ? cert.getType() : "cert is null"); -        } - -      } +      return value.trim().toCharArray();      } -    return Collections.unmodifiableList(result); +    return null;    }  } diff --git a/eaaf_modules/eaaf_module_pvp2_core/pom.xml b/eaaf_modules/eaaf_module_pvp2_core/pom.xml index c9aac506..a81ad889 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/pom.xml @@ -22,7 +22,6 @@        <artifactId>eaaf-core</artifactId>        <version>${egiz.eaaf.version}</version>      </dependency> -      <dependency>        <groupId>org.opensaml</groupId>        <artifactId>opensaml-core</artifactId> @@ -82,6 +81,12 @@        <artifactId>mockwebserver</artifactId>        <scope>test</scope>      </dependency> +    <dependency> +    <groupId>xml-apis</groupId> +    <artifactId>xml-apis</artifactId> +    <version>1.4.01</version> +    <scope>test</scope> +  </dependency>    </dependencies> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java index 8a33b205..902f84c7 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java @@ -406,6 +406,7 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec    private void addAndRemoveMetadataProvider() throws EaafConfigurationException {      log.info("EAAF chaining metadata resolver starting internal managment task .... "); +      // get all actually loaded metadata providers      final Map<String, MetadataResolver> loadedproviders = getAllActuallyLoadedResolvers(); @@ -428,6 +429,7 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec        try {          if (StringUtils.isNotEmpty(metadataurl)              && loadedproviders.containsKey(metadataurl)) { +          // SAML2 SP is actually loaded, to nothing            loadedproviders.remove(metadataurl);          } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java index 6959b6bd..cd77228c 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java @@ -19,8 +19,6 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.utils; -import java.io.IOException; -import java.io.InputStream;  import java.security.KeyStore;  import java.security.KeyStoreException;  import java.security.cert.Certificate; @@ -33,24 +31,24 @@ import java.util.List;  import javax.annotation.Nonnull;  import javax.annotation.PostConstruct; +import org.apache.commons.lang3.StringUtils; +import org.apache.xml.security.algorithms.JCEMapper; +import org.opensaml.security.credential.UsageType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ResourceLoader; +  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.KeyStoreUtils; +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.modules.pvp2.PvpConstants;  import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;  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.exception.SamlSigningException;  import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafKeyStoreX509CredentialAdapter; - -import org.apache.commons.lang3.StringUtils; -import org.opensaml.security.credential.UsageType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; -  import lombok.extern.slf4j.Slf4j;  @Slf4j @@ -63,6 +61,9 @@ public abstract class AbstractCredentialProvider implements IPvp2CredentialProvi    @Autowired    protected IConfiguration basicConfig; +  @Autowired +  private EaafKeyStoreFactory keyStoreFactory; +    private KeyStore keyStore = null;    /** @@ -71,23 +72,25 @@ public abstract class AbstractCredentialProvider implements IPvp2CredentialProvi     *     * @return keyStore friendlyName     */ -  public abstract String getFriendlyName(); +  public final String getFriendlyName() { +    try { +      return getBasicKeyStoreConfig().getFriendlyName(); +       +    } catch (EaafConfigurationException e) { +      return "No KeyStoreName"; +       +    } -  /** -   * Get KeyStore. -   * -   * @return URL to the keyStore -   * @throws EaafException In case of an invalid filepath -   */ -  @Nonnull -  public abstract String getKeyStoreFilePath() throws EaafException; +  }    /** -   * Get keyStore password. +   * Get the basic KeyStore configuration object for this SAML2 credential.     * -   * @return Password of the keyStore +   * @return KeyStore configuration object +   * @throws EaafConfigurationException  In case of a configuration error     */ -  public abstract String getKeyStorePassword(); +  @Nonnull +  public abstract KeyStoreConfiguration getBasicKeyStoreConfig() throws EaafConfigurationException;    /**     * Get alias of key for metadata signing. @@ -154,8 +157,6 @@ public abstract class AbstractCredentialProvider implements IPvp2CredentialProvi      }    } - -    /**     * Get Credentials to sign SAML2 messages, like AuthnRequest, Response,     * Assertions as some examples. @@ -250,21 +251,36 @@ public abstract class AbstractCredentialProvider implements IPvp2CredentialProvi    } -  @Lazy    @PostConstruct    private void initialize() throws Exception {      try { -      final Resource ressource = resourceLoader.getResource(getKeyStoreFilePath()); -      final InputStream is = ressource.getInputStream(); -      keyStore = KeyStoreUtils.loadKeyStore(is, getKeyStorePassword()); +      final KeyStoreConfiguration keyStoreConfig = getBasicKeyStoreConfig(); +      keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); + +      if (JCEMapper.getProviderId() != null +          && !JCEMapper.getProviderId().equals(keyStore.getProvider().getName())) { +        log.error("OpenSAML3.x can ONLY use a single type of CryptoProvider in an application. " +            + "Can NOT set: {}, because {} was already set", keyStore.getProvider().getName(), +            JCEMapper.getProviderId()); +        throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_06, +            new Object[] { keyStoreConfig.getFriendlyName(), +                "OpenSAML3.x can ONLY use a single type of CryptoProvider" }); + +      } -      if (keyStore == null) { -        throw new EaafConfigurationException("module.00", -            new Object[] { getFriendlyName(), "KeyStore initialization failed. Maybe wrong password" }); +      // Set JCEMapper only in case of HSM based KeyStores because Software KeyStores +      // can use +      // the default SecurityProvider system in OpenSAML3.x signing engine +      if (!KeyStoreType.JKS.equals(keyStoreConfig.getKeyStoreType()) +          && !KeyStoreType.PKCS12.equals(keyStoreConfig.getKeyStoreType()) +          && JCEMapper.getProviderId() == null) { +        log.info("Register CryptoProvider: {} as defaut for OpenSAML3.x", +            keyStore.getProvider().getName()); +        JCEMapper.setProviderId(keyStore.getProvider().getName());        } -    } catch (IOException | KeyStoreException | EaafException e) { +    } catch (final EaafException e) {        log.error("Can not initialize KeyStore for eIDAS authentication client.", e);        throw e; diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java index b6171e97..22ee389f 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java @@ -3,14 +3,8 @@ package at.gv.egiz.eaaf.modules.pvp2.test;  import java.security.cert.X509Certificate;  import java.util.List; -import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; -import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfigMap; -import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; -import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; -import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; -import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; -  import org.apache.commons.lang3.RandomStringUtils; +import org.apache.xml.security.algorithms.JCEMapper;  import org.junit.Assert;  import org.junit.Before;  import org.junit.Test; @@ -23,6 +17,14 @@ import org.springframework.test.context.ContextConfiguration;  import org.springframework.test.context.TestPropertySource;  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafFactoryException; +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfigMap; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; +  @RunWith(SpringJUnit4ClassRunner.class)  @ContextConfiguration({ @@ -34,9 +36,14 @@ public class CredentialProviderTest {    private static final String PATH_JKS_WITH_TRUST_CERTS = "src/test/resources/data/junit.jks";    private static final String PATH_JKS_WITHOUT_TRUST_CERTS = "src/test/resources/data/junit_without_trustcerts.jks"; +  //private static final String HSMF_ALIAS_METADATA = "shibboleth-sign"; +  //private static final String HSMF_ALIAS_SIGN = "shibboleth-sign"; +  //private static final String HSMF_ALIAS_ENC = "shibboleth-sign"; +      private static final String ALIAS_METADATA = "meta";    private static final String ALIAS_SIGN = "sig";    private static final String ALIAS_ENC = "meta"; +      private static final String PASSWORD = "password"; @@ -59,6 +66,8 @@ public class CredentialProviderTest {      config.removeConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS);      config.removeConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD); +     +    JCEMapper.setProviderId(null);    } @@ -86,7 +95,7 @@ public class CredentialProviderTest {        Assert.fail("No KeyStore not detected");      } catch (final BeansException e) { -      org.springframework.util.Assert.isInstanceOf(java.io.FileNotFoundException.class, +      org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class,            e.getCause(), "Wrong exception");      } @@ -101,7 +110,7 @@ public class CredentialProviderTest {        Assert.fail("No KeyStore not detected");      } catch (final BeansException e) { -      org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, +      org.springframework.util.Assert.isInstanceOf(EaafFactoryException.class,            e.getCause(), "Wrong exception");      } @@ -384,6 +393,33 @@ public class CredentialProviderTest {    @Test    @DirtiesContext +  public void otherKeyStoreTypeAlreadyLoaded() throws CredentialsNotAvailableException { +    config.putConfigValue(DummyCredentialProvider.KEYSTORE_PATH, PATH_JKS_WITHOUT_TRUST_CERTS); + +    config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, +        "RSA-SIG_" + RandomStringUtils.randomAlphabetic(10)); +    config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_SIGNING_EC_ALG, +        "EC-SIG_" + RandomStringUtils.randomAlphabetic(10)); +    config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG, +        "RSA_ENC_" + RandomStringUtils.randomAlphabetic(10)); +    config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG, +        "EC-ENC_" + RandomStringUtils.randomAlphabetic(10)); +     +    try { +      JCEMapper.setProviderId(RandomStringUtils.randomAlphabetic(5)); +       +      context.getBean(DummyCredentialProvider.class); + +    } catch (final BeansException e) { +      org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, +          e.getCause(), "Wrong exception"); + +    } + +  } +   +  @Test +  @DirtiesContext    public void notKeyConfiguration() {      final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class); diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java index b9f1326d..0f8eff72 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java @@ -1,15 +1,12 @@  package at.gv.egiz.eaaf.modules.pvp2.test.dummy; -import java.net.MalformedURLException; +import org.springframework.beans.factory.annotation.Autowired;  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; -import org.springframework.beans.factory.annotation.Autowired; -  public class DummyCredentialProvider extends AbstractCredentialProvider {    @Autowired IConfiguration basicConfig; @@ -26,32 +23,26 @@ public class DummyCredentialProvider extends AbstractCredentialProvider {    public static final String KEY_ENCRYPTION_ALIAS = "key.enc.alias";    public static final String KEY_ENCRYPTION_PASSWORD = "key.enc.pass"; +  private static final String KEYSTORENAME = "jUnit test credential provider"; +      @Override -  public String getFriendlyName() { -    return "jUnit test credential provider"; +  public KeyStoreConfiguration getBasicKeyStoreConfig() { +    KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); +    keyStoreConfig.setKeyStoreType(KeyStoreType.JKS); +    keyStoreConfig.setFriendlyName(KEYSTORENAME); +     +    keyStoreConfig.setSoftKeyStoreFilePath(getKeyStoreFilePath()); +    keyStoreConfig.setSoftKeyStorePassword(getKeyStorePassword()); +     +    return keyStoreConfig;    } -  @Override -  public String getKeyStoreFilePath() throws EaafException { +  public String getKeyStoreFilePath() {      final String path = basicConfig.getBasicConfiguration(KEYSTORE_PATH); - -    if (path != null) { -      try { -        return FileUtils.makeAbsoluteUrl( -            path, -            basicConfig.getConfigurationRootDirectory()); - -      } catch (final MalformedURLException e) { -        throw new EaafConfigurationException("internel test error", null, e); - -      } -    } - -    throw new EaafConfigurationException("No keyStore path", null); - +    return path; +       } -  @Override    public String getKeyStorePassword() {      return basicConfig.getBasicConfiguration(KEYSTORE_PASSWORD);    } @@ -86,4 +77,5 @@ public class DummyCredentialProvider extends AbstractCredentialProvider {      return basicConfig.getBasicConfiguration(KEY_ENCRYPTION_PASSWORD);    } +  } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_2.props b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_2.props new file mode 100644 index 00000000..60cecebb --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_2.props @@ -0,0 +1,12 @@ +keystore.path=classpath:/data/junit.jks +keystore.pass=password +key.metadata.alias=shibboleth-sign +key.metadata.pass=password +key.sig.alias=shibboleth-sign +key.sig.pass=password +key.enc.alias= +key.enc.pass= + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml index 3b2d0a28..5e3f0b9b 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml @@ -19,4 +19,7 @@    <bean id="httpClientFactory"          class="at.gv.egiz.eaaf.core.impl.utils.HttpClientFactory" /> +  <bean id="eaafKeyStoreFactory" +        class="at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory" /> +  </beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml index 5c1a6095..5319236b 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml @@ -14,4 +14,7 @@          class="at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig" /> +  <bean id="eaafKeyStoreFactory" +        class="at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory" /> +  </beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props index 6324f190..164b8807 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props @@ -7,8 +7,6 @@ key.sig.pass=password  key.enc.alias=  key.enc.pass= -pvp2.assertion.encryption.active=true -  client.http.connection.timeout.socket=2  client.http.connection.timeout.connection=2  client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props new file mode 100644 index 00000000..60cecebb --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props @@ -0,0 +1,12 @@ +keystore.path=classpath:/data/junit.jks +keystore.pass=password +key.metadata.alias=shibboleth-sign +key.metadata.pass=password +key.sig.alias=shibboleth-sign +key.sig.pass=password +key.enc.alias= +key.enc.pass= + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml index f46b7747..99552053 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml @@ -25,4 +25,7 @@    <bean id="dummyRevisionLogger"          class="at.gv.egiz.eaaf.core.impl.logging.DummyRevisionsLogger" /> +  <bean id="eaafKeyStoreFactory" +        class="at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory" />  +  </beans>
\ No newline at end of file | 
