From e02aa41578ec3e08dd96fde9ef0342b69a051ba6 Mon Sep 17 00:00:00 2001 From: Christian Kollmann Date: Mon, 10 Feb 2020 12:39:09 +0100 Subject: Hack: Integrate HsmFacade for signing operations --- eaaf_modules/eaaf_module_pvp2_core/pom.xml | 13 +++++- .../impl/utils/AbstractCredentialProvider.java | 48 ++++++++++++++++++++-- .../modules/pvp2/test/CredentialProviderTest.java | 6 +-- .../src/test/resources/config/config_1.props | 4 +- .../src/test/resources/config/config_1.props | 4 +- 5 files changed, 64 insertions(+), 11 deletions(-) (limited to 'eaaf_modules') diff --git a/eaaf_modules/eaaf_module_pvp2_core/pom.xml b/eaaf_modules/eaaf_module_pvp2_core/pom.xml index ca112162..14bf50d5 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/pom.xml @@ -14,6 +14,7 @@ http://maven.apache.org UTF-8 + 0.1.1-SNAPSHOT @@ -22,7 +23,11 @@ eaaf-core ${egiz.eaaf.version} - + + at.asitplus.hsmfacade + provider + ${hsm-facade-provider.version} + org.opensaml opensaml-core @@ -76,6 +81,12 @@ mockwebserver test + + xml-apis + xml-apis + 1.4.01 + test + 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..bf551c0e 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,11 +19,15 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.utils; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.security.KeyStore; import java.security.KeyStoreException; +import java.security.Security; import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; @@ -33,6 +37,8 @@ import java.util.List; import javax.annotation.Nonnull; import javax.annotation.PostConstruct; +import at.asitplus.hsmfacade.provider.HsmFacadeProvider; +import at.asitplus.hsmfacade.provider.RemoteKeyStoreLoadParameter; 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; @@ -45,6 +51,7 @@ 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.apache.xml.security.algorithms.JCEMapper; import org.opensaml.security.credential.UsageType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; @@ -250,13 +257,48 @@ public abstract class AbstractCredentialProvider implements IPvp2CredentialProvi } + private X509Certificate getRootCertificate() throws CertificateException { + String pem = "-----BEGIN CERTIFICATE-----\n" + + "MIIDFDCCAfygAwIBAgIEXIjqbjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARy\n" + + "b290MB4XDTE5MDMxMzExMzMwMloXDTIwMDMxMjExMzMwMlowDzENMAsGA1UEAwwE\n" + + "cm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKijWXfb7bvQ7CIw\n" + + "FuyuPUz+aN7uBgSSnpYamtzjagacdtGR2V2OVHfjVHhw+cSoNPaEEV2x0O9A+w8F\n" + + "FCatBT30l7/2scuJmrdXYlIhd17NU6HG/HKYvRYROkXrprsbdZobWqdF/zShLIvv\n" + + "0bwconAu7AxwlDgNJQz2pL0e94OkCT5rZyA4HFgzJ34XynXaCMbUbVXxVk6EuNaX\n" + + "hbyco0qhjOjSn7Rwk3iXp21V4vcYRVq44sG3ieU6jHq6LKmYSGJ1y0yv9ADYJwSp\n" + + "jCzRbOEKe/7QVvZIyzzqjhO3SAHONuFNX0V6zPCgMCjUOgHuOIEKLJR9p0YYYocX\n" + + "GBLcVuECAwEAAaN4MHYwDAYDVR0TBAUwAwEB/zA6BgNVHSMEMzAxgBQueuDUlVbB\n" + + "LBjP+iRFr6lUDBh58qETpBEwDzENMAsGA1UEAwwEcm9vdIIEXIjqbjAdBgNVHQ4E\n" + + "FgQULnrg1JVWwSwYz/okRa+pVAwYefIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEB\n" + + "CwUAA4IBAQCEYSVpiKFO7FjCqTlkxNBY7e7891dq43DfX9i/Hb/AIvZDPe/RC46t\n" + + "EXd9LN7QYaXe35U5ZD1q7qmK7NoFJ9zp4D4mxA2iiBHz40GnRt+0abNdQiyw913W\n" + + "s/VIElAOv0tvCw+3SwzvLRU/AVCM1weW6IUbYv/Ty5zmLBsG3do3MmVF3cqXho2m\n" + + "pNaiubuaUsR8Ms1LqIr6R7Yf8MKSrgYWCOw60gj5O64RHnEJli52D+S/8Cue5GvG\n" + + "ECckmgLgGsRcWfFwRqqS7+XWt8Dv8xxD5vurvcs547Hn28kSHtF2i+KYLDVH2QjN\n" + + "dbO0qgEJlMPi7oGrsNjIkndrWseNrPA4\n" + + "-----END CERTIFICATE-----\n"; + return (java.security.cert.X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(pem.getBytes())); + } + @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 HsmFacadeProvider provider = HsmFacadeProvider.Companion.getInstance(); + String clientUsername = "shibboleth-idp"; + String clientPassword = "supersecret123"; + String host = "localhost"; + int port = 9000; + String hsmName = "software"; + String keyStoreName = "shibboleth"; + String keyStoreAlias = "shibboleth-sign"; + + provider.init(getRootCertificate(), clientUsername, clientPassword, host, port, hsmName); + Security.addProvider(provider); + //Security.insertProviderAt(provider, 1); + JCEMapper.setProviderId(provider.getName()); + keyStore = KeyStore.getInstance("RemoteKeyStore", "HsmFacade"); + keyStore.load(new RemoteKeyStoreLoadParameter(keyStoreName)); if (keyStore == null) { throw new EaafConfigurationException("module.00", 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 1183bb49..7d95204b 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 @@ -34,9 +34,9 @@ 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 ALIAS_METADATA = "meta"; - private static final String ALIAS_SIGN = "sig"; - private static final String ALIAS_ENC = "meta"; + private static final String ALIAS_METADATA = "shibboleth-sign"; + private static final String ALIAS_SIGN = "shibboleth-sign"; + private static final String ALIAS_ENC = "shibboleth-sign"; private static final String PASSWORD = "password"; diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props index 164b8807..60cecebb 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props @@ -1,8 +1,8 @@ keystore.path=classpath:/data/junit.jks keystore.pass=password -key.metadata.alias=meta +key.metadata.alias=shibboleth-sign key.metadata.pass=password -key.sig.alias=sig +key.sig.alias=shibboleth-sign key.sig.pass=password key.enc.alias= key.enc.pass= 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..5dea3d51 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 @@ -1,8 +1,8 @@ keystore.path=classpath:/data/junit.jks keystore.pass=password -key.metadata.alias=meta +key.metadata.alias=shibboleth-sign key.metadata.pass=password -key.sig.alias=sig +key.sig.alias=shibboleth-sign key.sig.pass=password key.enc.alias= key.enc.pass= -- cgit v1.2.3 From cbfadcc7681c9f362c1e7e2c3eab43980c1236ef Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 12 Feb 2020 19:01:59 +0100 Subject: add first untested version of EaafKeyStoreFactory that supports Software-Keystore and HSM-Facade --- eaaf_modules/eaaf_module_pvp2_core/pom.xml | 6 ------ 1 file changed, 6 deletions(-) (limited to 'eaaf_modules') diff --git a/eaaf_modules/eaaf_module_pvp2_core/pom.xml b/eaaf_modules/eaaf_module_pvp2_core/pom.xml index 14bf50d5..318fa500 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/pom.xml @@ -14,7 +14,6 @@ http://maven.apache.org UTF-8 - 0.1.1-SNAPSHOT @@ -23,11 +22,6 @@ eaaf-core ${egiz.eaaf.version} - - at.asitplus.hsmfacade - provider - ${hsm-facade-provider.version} - org.opensaml opensaml-core -- cgit v1.2.3 From e23226c47807be597bbbae3891dbb94069d56836 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Fri, 14 Feb 2020 08:46:52 +0100 Subject: Integrate HSM Facade from A-SIT+ The EaafKeyStoreFactory can be used to build KeyStores from differend providers and types --- .../metadata/AbstractChainingMetadataProvider.java | 21 ++-- .../impl/utils/AbstractCredentialProvider.java | 119 ++++++++------------- .../modules/pvp2/test/CredentialProviderTest.java | 60 ++++++++--- .../pvp2/test/dummy/DummyCredentialProvider.java | 44 ++++---- .../src/test/resources/config/config_1.props | 4 +- .../src/test/resources/config/config_2.props | 12 +++ .../test/resources/spring/test_eaaf_core.beans.xml | 3 + .../spring/test_eaaf_core_spring_config.beans.xml | 3 + .../src/test/resources/config/config_1.props | 6 +- .../src/test/resources/config/config_2.props | 12 +++ .../test/resources/spring/test_eaaf_core.beans.xml | 3 + 11 files changed, 152 insertions(+), 135 deletions(-) create mode 100644 eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_2.props create mode 100644 eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props (limited to 'eaaf_modules') 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 1b14c92d..b9d0161f 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 @@ -33,13 +33,6 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.naming.ConfigurationException; -import at.gv.egiz.components.spring.api.IDestroyableObject; -import at.gv.egiz.eaaf.core.api.IGarbageCollectorProcessing; -import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpAddableChainingMetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; - import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.opensaml.core.criterion.EntityIdCriterion; @@ -50,6 +43,12 @@ import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; import org.opensaml.saml.metadata.resolver.impl.AbstractMetadataResolver; import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import at.gv.egiz.components.spring.api.IDestroyableObject; +import at.gv.egiz.eaaf.core.api.IGarbageCollectorProcessing; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpAddableChainingMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; import lombok.extern.slf4j.Slf4j; import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements; import net.shibboleth.utilities.java.support.component.IdentifiedComponent; @@ -408,13 +407,6 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec private void addAndRemoveMetadataProvider() throws EaafConfigurationException { log.info("EAAF chaining metadata resolver starting internal managment task .... "); - /* - * OpenSAML ChainingMetadataProvider can not remove a MetadataProvider - * (UnsupportedOperationException) The ChainingMetadataProvider use internal a - * unmodifiableList to hold all registrated MetadataProviders. - */ - final Map providersinuse = new HashMap<>(); - // get all actually loaded metadata providers final Map loadedproviders = getAllActuallyLoadedResolvers(); @@ -438,7 +430,6 @@ public abstract class AbstractChainingMetadataProvider implements IGarbageCollec if (StringUtils.isNotEmpty(metadataurl) && loadedproviders.containsKey(metadataurl)) { // SAML2 SP is actually loaded, to nothing - providersinuse.put(metadataurl, loadedproviders.get(metadataurl)); 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 bf551c0e..6477d8ff 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,15 +19,9 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.utils; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; import java.security.KeyStore; import java.security.KeyStoreException; -import java.security.Security; import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; @@ -37,27 +31,24 @@ import java.util.List; import javax.annotation.Nonnull; import javax.annotation.PostConstruct; -import at.asitplus.hsmfacade.provider.HsmFacadeProvider; -import at.asitplus.hsmfacade.provider.RemoteKeyStoreLoadParameter; +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.apache.xml.security.algorithms.JCEMapper; -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 @@ -70,6 +61,9 @@ public abstract class AbstractCredentialProvider implements IPvp2CredentialProvi @Autowired protected IConfiguration basicConfig; + @Autowired + private EaafKeyStoreFactory keyStoreFactory; + private KeyStore keyStore = null; /** @@ -78,23 +72,18 @@ public abstract class AbstractCredentialProvider implements IPvp2CredentialProvi * * @return keyStore friendlyName */ - public abstract String getFriendlyName(); + public final String getFriendlyName() { + return getBasicKeyStoreConfig().getFriendlyName(); - /** - * 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 */ - public abstract String getKeyStorePassword(); + @Nonnull + public abstract KeyStoreConfiguration getBasicKeyStoreConfig(); /** * Get alias of key for metadata signing. @@ -161,8 +150,6 @@ public abstract class AbstractCredentialProvider implements IPvp2CredentialProvi } } - - /** * Get Credentials to sign SAML2 messages, like AuthnRequest, Response, * Assertions as some examples. @@ -257,56 +244,36 @@ public abstract class AbstractCredentialProvider implements IPvp2CredentialProvi } - private X509Certificate getRootCertificate() throws CertificateException { - String pem = "-----BEGIN CERTIFICATE-----\n" + - "MIIDFDCCAfygAwIBAgIEXIjqbjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARy\n" + - "b290MB4XDTE5MDMxMzExMzMwMloXDTIwMDMxMjExMzMwMlowDzENMAsGA1UEAwwE\n" + - "cm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKijWXfb7bvQ7CIw\n" + - "FuyuPUz+aN7uBgSSnpYamtzjagacdtGR2V2OVHfjVHhw+cSoNPaEEV2x0O9A+w8F\n" + - "FCatBT30l7/2scuJmrdXYlIhd17NU6HG/HKYvRYROkXrprsbdZobWqdF/zShLIvv\n" + - "0bwconAu7AxwlDgNJQz2pL0e94OkCT5rZyA4HFgzJ34XynXaCMbUbVXxVk6EuNaX\n" + - "hbyco0qhjOjSn7Rwk3iXp21V4vcYRVq44sG3ieU6jHq6LKmYSGJ1y0yv9ADYJwSp\n" + - "jCzRbOEKe/7QVvZIyzzqjhO3SAHONuFNX0V6zPCgMCjUOgHuOIEKLJR9p0YYYocX\n" + - "GBLcVuECAwEAAaN4MHYwDAYDVR0TBAUwAwEB/zA6BgNVHSMEMzAxgBQueuDUlVbB\n" + - "LBjP+iRFr6lUDBh58qETpBEwDzENMAsGA1UEAwwEcm9vdIIEXIjqbjAdBgNVHQ4E\n" + - "FgQULnrg1JVWwSwYz/okRa+pVAwYefIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEB\n" + - "CwUAA4IBAQCEYSVpiKFO7FjCqTlkxNBY7e7891dq43DfX9i/Hb/AIvZDPe/RC46t\n" + - "EXd9LN7QYaXe35U5ZD1q7qmK7NoFJ9zp4D4mxA2iiBHz40GnRt+0abNdQiyw913W\n" + - "s/VIElAOv0tvCw+3SwzvLRU/AVCM1weW6IUbYv/Ty5zmLBsG3do3MmVF3cqXho2m\n" + - "pNaiubuaUsR8Ms1LqIr6R7Yf8MKSrgYWCOw60gj5O64RHnEJli52D+S/8Cue5GvG\n" + - "ECckmgLgGsRcWfFwRqqS7+XWt8Dv8xxD5vurvcs547Hn28kSHtF2i+KYLDVH2QjN\n" + - "dbO0qgEJlMPi7oGrsNjIkndrWseNrPA4\n" + - "-----END CERTIFICATE-----\n"; - return (java.security.cert.X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(pem.getBytes())); - } - - @Lazy @PostConstruct private void initialize() throws Exception { try { - final HsmFacadeProvider provider = HsmFacadeProvider.Companion.getInstance(); - String clientUsername = "shibboleth-idp"; - String clientPassword = "supersecret123"; - String host = "localhost"; - int port = 9000; - String hsmName = "software"; - String keyStoreName = "shibboleth"; - String keyStoreAlias = "shibboleth-sign"; - - provider.init(getRootCertificate(), clientUsername, clientPassword, host, port, hsmName); - Security.addProvider(provider); - //Security.insertProviderAt(provider, 1); - JCEMapper.setProviderId(provider.getName()); - keyStore = KeyStore.getInstance("RemoteKeyStore", "HsmFacade"); - keyStore.load(new RemoteKeyStoreLoadParameter(keyStoreName)); - - if (keyStore == null) { - throw new EaafConfigurationException("module.00", - new Object[] { getFriendlyName(), "KeyStore initialization failed. Maybe wrong password" }); + 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" }); + + } + + // 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 7d95204b..3ba4629e 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 ALIAS_METADATA = "shibboleth-sign"; - private static final String ALIAS_SIGN = "shibboleth-sign"; - private static final String ALIAS_ENC = "shibboleth-sign"; + //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"); } @@ -382,6 +391,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() { 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_1.props b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props index 60cecebb..164b8807 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props @@ -1,8 +1,8 @@ keystore.path=classpath:/data/junit.jks keystore.pass=password -key.metadata.alias=shibboleth-sign +key.metadata.alias=meta key.metadata.pass=password -key.sig.alias=shibboleth-sign +key.sig.alias=sig key.sig.pass=password key.enc.alias= key.enc.pass= 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 @@ + + \ 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 c1660a70..5aef9544 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 @@ -15,4 +15,7 @@ + + \ 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 5dea3d51..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 @@ -1,14 +1,12 @@ keystore.path=classpath:/data/junit.jks keystore.pass=password -key.metadata.alias=shibboleth-sign +key.metadata.alias=meta key.metadata.pass=password -key.sig.alias=shibboleth-sign +key.sig.alias=sig 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 375224bb..8c0b8596 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 @@ -21,5 +21,8 @@ + + \ No newline at end of file -- cgit v1.2.3 From c4e1a45e7958cab402d83f6f4ae208df1bb2ab58 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Fri, 14 Feb 2020 15:22:13 +0100 Subject: add common-code for KeyStore and Credential handling --- .../gv/egiz/eaaf/modules/auth/sl20/Constants.java | 40 ++- .../modules/auth/sl20/utils/JsonSecurityUtils.java | 271 ++++++++++----------- .../impl/utils/AbstractCredentialProvider.java | 11 +- 3 files changed, 170 insertions(+), 152 deletions(-) (limited to 'eaaf_modules') 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 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 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 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 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 trustedCertificates = readCertsFromKeyStore(trustStore); + final List 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 encryptionCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore, + getEncryptionKeyAlias(), getEncryptionKeyPassword(), true, FRIENDLYNAME_KEYSTORE); + // validate key from header against key from config final List 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 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 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 readCertsFromKeyStore(@Nonnull final KeyStore keyStore) throws KeyStoreException { - final List result = new ArrayList<>(); - - final Enumeration 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/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 6477d8ff..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 @@ -73,7 +73,13 @@ public abstract class AbstractCredentialProvider implements IPvp2CredentialProvi * @return keyStore friendlyName */ public final String getFriendlyName() { - return getBasicKeyStoreConfig().getFriendlyName(); + try { + return getBasicKeyStoreConfig().getFriendlyName(); + + } catch (EaafConfigurationException e) { + return "No KeyStoreName"; + + } } @@ -81,9 +87,10 @@ public abstract class AbstractCredentialProvider implements IPvp2CredentialProvi * Get the basic KeyStore configuration object for this SAML2 credential. * * @return KeyStore configuration object + * @throws EaafConfigurationException In case of a configuration error */ @Nonnull - public abstract KeyStoreConfiguration getBasicKeyStoreConfig(); + public abstract KeyStoreConfiguration getBasicKeyStoreConfig() throws EaafConfigurationException; /** * Get alias of key for metadata signing. -- cgit v1.2.3