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 --- .../impl/logging/EaafUtilsMessageSourceTest.java | 36 ++ .../impl/logging/JUnitTestStatusMessenger.java | 3 +- .../core/impl/utils/test/KeyValueUtilsTest.java | 6 +- .../test/credentials/EaafKeyStoreFactoryTest.java | 555 +++++++++++++++++++++ .../credentials/KeyStoreConfigurationTest.java | 190 +++++++ .../eaaf/core/test/dummy/DummyAuthConfigMap.java | 142 ++++++ .../resources/data/junit_without_trustcerts.jks | Bin 0 -> 2733 bytes .../resources/data/junit_without_trustcerts.p12 | Bin 0 -> 3204 bytes eaaf_core_utils/src/test/resources/data/test.crt | 3 + .../resources/spring/test_eaaf_pvp_lazy.beans.xml | 23 + .../spring/test_eaaf_pvp_not_lazy.beans.xml | 19 + 11 files changed, 974 insertions(+), 3 deletions(-) create mode 100644 eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/logging/EaafUtilsMessageSourceTest.java create mode 100644 eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java create mode 100644 eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/KeyStoreConfigurationTest.java create mode 100644 eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/dummy/DummyAuthConfigMap.java create mode 100644 eaaf_core_utils/src/test/resources/data/junit_without_trustcerts.jks create mode 100644 eaaf_core_utils/src/test/resources/data/junit_without_trustcerts.p12 create mode 100644 eaaf_core_utils/src/test/resources/data/test.crt create mode 100644 eaaf_core_utils/src/test/resources/spring/test_eaaf_pvp_lazy.beans.xml create mode 100644 eaaf_core_utils/src/test/resources/spring/test_eaaf_pvp_not_lazy.beans.xml (limited to 'eaaf_core_utils/src/test') diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/logging/EaafUtilsMessageSourceTest.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/logging/EaafUtilsMessageSourceTest.java new file mode 100644 index 00000000..f6df60ae --- /dev/null +++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/logging/EaafUtilsMessageSourceTest.java @@ -0,0 +1,36 @@ +package at.gv.egiz.eaaf.core.impl.logging; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/spring/test_eaaf_pvp_not_lazy.beans.xml") +public class EaafUtilsMessageSourceTest { + + @Autowired + private ResourceLoader loader; + @Autowired(required = false) + private IMessageSourceLocation messageSource; + + @Test + public void simpleTests() { + Assert.assertNotNull("No messageSource", messageSource); + + Assert.assertNotNull("No sourcePath", messageSource.getMessageSourceLocation()); + + for (final String el : messageSource.getMessageSourceLocation()) { + final Resource messages = loader.getResource(el + ".properties"); + Assert.assertTrue("Source not exist", messages.exists()); + + } + + } +} diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/logging/JUnitTestStatusMessenger.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/logging/JUnitTestStatusMessenger.java index be5d95b1..9c1d0c82 100644 --- a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/logging/JUnitTestStatusMessenger.java +++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/logging/JUnitTestStatusMessenger.java @@ -3,6 +3,7 @@ package at.gv.egiz.eaaf.core.impl.logging; import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; + import at.gv.egiz.eaaf.core.api.IStatusMessenger; public class JUnitTestStatusMessenger implements IStatusMessenger { @@ -48,7 +49,7 @@ public class JUnitTestStatusMessenger implements IStatusMessenger { * Add a message into Message-Store. * * @param msgCode message-code - * @param msg message + * @param msg message */ public void addMsg(final String msgCode, final String msg) { if (!msgStore.containsKey(msgCode)) { diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/utils/test/KeyValueUtilsTest.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/utils/test/KeyValueUtilsTest.java index 258c3210..58788392 100644 --- a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/utils/test/KeyValueUtilsTest.java +++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/utils/test/KeyValueUtilsTest.java @@ -6,14 +6,17 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; + import org.apache.commons.lang3.RandomStringUtils; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.BlockJUnit4ClassRunner; + import com.google.common.collect.Sets; +import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; + @RunWith(BlockJUnit4ClassRunner.class) public class KeyValueUtilsTest { @@ -442,5 +445,4 @@ public class KeyValueUtilsTest { } - } diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java new file mode 100644 index 00000000..805000cb --- /dev/null +++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java @@ -0,0 +1,555 @@ +package at.gv.egiz.eaaf.core.test.credentials; + +import java.security.KeyStore; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.MethodMode; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.google.common.base.Optional; +import com.google.common.base.Predicates; +import com.google.common.base.Throwables; +import com.google.common.collect.FluentIterable; + +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafFactoryException; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; +import at.gv.egiz.eaaf.core.test.dummy.DummyAuthConfigMap; +import io.grpc.StatusRuntimeException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/spring/test_eaaf_pvp_lazy.beans.xml") +@DirtiesContext(methodMode = MethodMode.BEFORE_METHOD) +public class EaafKeyStoreFactoryTest { + + private static final String PATH_TO_SOFTWARE_KEYSTORE_JKS = + "src/test/resources/data/junit_without_trustcerts.jks"; + private static final String PATH_TO_SOFTWARE_KEYSTORE_PKCS12 = + "src/test/resources/data/junit_without_trustcerts.p12"; + private static final String PATH_TO_HSM_FACADE_TRUST_CERT = "src/test/resources/data/test.crt"; + private static final String SOFTWARE_KEYSTORE_PASSWORD = "password"; + + @Autowired + private DummyAuthConfigMap mapConfig; + @Autowired + private ApplicationContext context; + + /** + * jUnit test set-up. + */ + @Before + public void testSetup() { + mapConfig.clearAllConfig(); + + } + + @Test + @DirtiesContext + public void startWithoutConfigHsmFacadeConfig() { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + } + + @Test + @DirtiesContext + public void buildyStoreWithOutConfig() { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + try { + keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.fail("Wrong config not detected"); + + } catch (final EaafException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType"); + Assert.assertEquals("wrong errorCode", "internal.keystore.01", e.getErrorId()); + + } + } + + @Test + @DirtiesContext + public void buildyStoreWithPkcs11() { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.PKCS11); + try { + keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.fail("Wrong config not detected"); + + } catch (final EaafException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType"); + Assert.assertEquals("wrong errorCode", "internal.keystore.02", e.getErrorId()); + + } + } + + @Test + @DirtiesContext + public void softwareKeyStoreWithoutConfig() { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.JKS); + try { + keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.fail("Wrong config not detected"); + + } catch (final EaafException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType"); + Assert.assertEquals("wrong errorCode", "internal.keystore.06", e.getErrorId()); + + } + } + + @Test + @DirtiesContext + public void softwareKeyStoreWithoutConfigSecond() { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.PKCS12); + try { + keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.fail("Wrong config not detected"); + + } catch (final EaafException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType"); + Assert.assertEquals("wrong errorCode", "internal.keystore.06", e.getErrorId()); + + } + } + + @Test + @DirtiesContext + public void softwareKeyStoreWithoutPassword() { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.JKS); + keyStoreConfig.setSoftKeyStoreFilePath(PATH_TO_SOFTWARE_KEYSTORE_JKS); + + try { + keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.fail("Wrong config not detected"); + + } catch (final EaafException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType"); + Assert.assertEquals("wrong errorCode", "internal.keystore.06", e.getErrorId()); + + } + } + + @Test + @DirtiesContext + public void softwareKeyStoreWithoutPath() { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.JKS); + keyStoreConfig.setSoftKeyStorePassword(SOFTWARE_KEYSTORE_PASSWORD); + + + try { + keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.fail("Wrong config not detected"); + + } catch (final EaafException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType"); + Assert.assertEquals("wrong errorCode", "internal.keystore.06", e.getErrorId()); + + } + } + + @Test + @DirtiesContext + public void softwareKeyStoreWithoutType() throws EaafException { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.JKS); + keyStoreConfig.setSoftKeyStoreFilePath(PATH_TO_SOFTWARE_KEYSTORE_JKS); + keyStoreConfig.setSoftKeyStorePassword(SOFTWARE_KEYSTORE_PASSWORD); + + final KeyStore keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.assertNotNull("KeyStore is null", keyStore); + + } + + @Test + @DirtiesContext + public void softwareKeyStoreWithWrongPath() { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.JKS); + keyStoreConfig.setSoftKeyStoreFilePath("src/test/resources/notexist.jks"); + keyStoreConfig.setSoftKeyStorePassword(SOFTWARE_KEYSTORE_PASSWORD); + + + try { + keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.fail("Wrong config not detected"); + + } catch (final EaafException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType"); + Assert.assertEquals("wrong errorCode", "internal.keystore.05", e.getErrorId()); + + } + } + + @Test + @DirtiesContext + public void softwareKeyStoreWithWrongPassword() { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.JKS); + keyStoreConfig.setSoftKeyStoreFilePath(PATH_TO_SOFTWARE_KEYSTORE_JKS); + keyStoreConfig.setSoftKeyStorePassword("wrong password"); + + + try { + keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.fail("Wrong config not detected"); + + } catch (final EaafException e) { + org.springframework.util.Assert.isInstanceOf(EaafFactoryException.class, e, "Wong ExceptionType"); + Assert.assertEquals("wrong errorCode", "internal.keystore.06", e.getErrorId()); + + } + } + + @Test + @DirtiesContext + public void softwareKeyStoreSuccessJks() throws EaafException { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.JKS); + keyStoreConfig.setSoftKeyStoreFilePath(PATH_TO_SOFTWARE_KEYSTORE_JKS); + keyStoreConfig.setSoftKeyStorePassword(SOFTWARE_KEYSTORE_PASSWORD); + + + final KeyStore keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.assertNotNull("KeyStore is null", keyStore); + + } + + @Test + @DirtiesContext + public void softwareKeyStoreSuccessPkcs12() throws EaafException { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.PKCS12); + keyStoreConfig.setSoftKeyStoreFilePath(PATH_TO_SOFTWARE_KEYSTORE_PKCS12); + keyStoreConfig.setSoftKeyStorePassword(SOFTWARE_KEYSTORE_PASSWORD); + + final KeyStore keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.assertNotNull("KeyStore is null", keyStore); + + } + + @Test + public void hsmFacadeOnlyHostConfig() { + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, + RandomStringUtils.randomNumeric(10)); + try { + context.getBean(EaafKeyStoreFactory.class); + Assert.fail("Missing HSM Facade not detected"); + + } catch (final BeansException e) { + checkMissingConfigException(e); + + } + } + + @Test + public void hsmFacadeMissingPort() { + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HSM_NAME, + RandomStringUtils.randomAlphanumeric(10)); + + try { + context.getBean(EaafKeyStoreFactory.class); + Assert.fail("Missing HSM Facade not detected"); + + } catch (final BeansException e) { + checkMissingConfigException(e); + + } + } + + @Test + public void hsmFacadeMissingUsername() { + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, + RandomStringUtils.randomNumeric(4)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HSM_NAME, + RandomStringUtils.randomAlphanumeric(10)); + + try { + context.getBean(EaafKeyStoreFactory.class); + Assert.fail("Missing HSM Facade not detected"); + + } catch (final BeansException e) { + checkMissingConfigException(e); + + } + } + + @Test + public void hsmFacadeMissingPassword() { + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, + RandomStringUtils.randomNumeric(4)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HSM_NAME, + RandomStringUtils.randomAlphanumeric(10)); + + try { + context.getBean(EaafKeyStoreFactory.class); + Assert.fail("Missing HSM Facade not detected"); + + } catch (final BeansException e) { + checkMissingConfigException(e); + + } + } + + @Test + public void hsmFacadeMissingKeyStoreName() { + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, + RandomStringUtils.randomNumeric(4)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, + RandomStringUtils.randomAlphanumeric(10)); + + try { + context.getBean(EaafKeyStoreFactory.class); + Assert.fail("Missing HSM Facade not detected"); + + } catch (final BeansException e) { + checkMissingConfigException(e); + + } + } + + @Test + public void hsmFacadeMissingTrustedCertificate() { + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, + RandomStringUtils.randomNumeric(4)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HSM_NAME, + RandomStringUtils.randomAlphanumeric(10)); + + try { + context.getBean(EaafKeyStoreFactory.class); + Assert.fail("Missing HSM Facade not detected"); + + } catch (final BeansException e) { + checkMissingConfigException(e); + + } + } + + @Test + public void hsmFacadeMissingTrustedCertificateFile() { + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, + RandomStringUtils.randomNumeric(4)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HSM_NAME, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_SSLTRUST, + "src/test/resources/data/notexist.crt"); + + try { + context.getBean(EaafKeyStoreFactory.class); + Assert.fail("Missing HSM Facade not detected"); + + } catch (final BeansException e) { + checkMissingConfigException(e, "internal.keystore.05"); + + } + } + + @Test + public void hsmFacadeMissingWrongTrustedCertificate() { + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, + RandomStringUtils.randomNumeric(4)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HSM_NAME, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_SSLTRUST, + "src/test/resources/spring/test_eaaf_pvp_lazy.beans.xml"); + + try { + context.getBean(EaafKeyStoreFactory.class); + Assert.fail("Missing HSM Facade not detected"); + + } catch (final BeansException e) { + checkMissingConfigException(e, "internal.keystore.05"); + + } + } + + @Test + @DirtiesContext + public void hsmFacadeInitialized() { + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, + RandomStringUtils.randomNumeric(4)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HSM_NAME, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_SSLTRUST, + PATH_TO_HSM_FACADE_TRUST_CERT); + + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertTrue("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + } + + @Test + @DirtiesContext + public void hsmFacadeKeyStoreNoKeyStoreName() { + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, + RandomStringUtils.randomNumeric(4)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HSM_NAME, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_SSLTRUST, + PATH_TO_HSM_FACADE_TRUST_CERT); + + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertTrue("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.HSMFACADE); + + try { + keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.fail("Wrong config not detected"); + + } catch (final EaafException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, e, "Wong ExceptionType"); + Assert.assertEquals("wrong errorCode", "internal.keystore.06", e.getErrorId()); + } + + } + + @Test + @DirtiesContext + public void hsmFacadeKeyStoreSuccess() throws EaafException { + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, + RandomStringUtils.randomNumeric(4)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, + RandomStringUtils.randomNumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HSM_NAME, + RandomStringUtils.randomAlphanumeric(10)); + mapConfig.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_SSLTRUST, + PATH_TO_HSM_FACADE_TRUST_CERT); + + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertTrue("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.HSMFACADE); + keyStoreConfig.setKeyStoreName("testkeyStore"); + + try { + final KeyStore keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.assertNotNull("KeyStore is null", keyStore); + + } catch (final StatusRuntimeException e) { + // because there is no mockup of HSM facade available + // Assert.assertTrue("Wrong exception", e.getMessage().contains("io + // exception")); + + } + + } + + private void checkMissingConfigException(Exception e) { + checkMissingConfigException(e, "internal.keystore.04"); + + } + + private void checkMissingConfigException(Exception e, String errorCode) { + final Optional eaafException = FluentIterable.from( + Throwables.getCausalChain(e)).filter( + Predicates.instanceOf(EaafConfigurationException.class)).first(); + Assert.assertTrue("Wrong exception", eaafException.isPresent()); + Assert.assertEquals("Wrong errorCode", + errorCode, ((EaafException) eaafException.get()).getErrorId()); + + } + +} diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/KeyStoreConfigurationTest.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/KeyStoreConfigurationTest.java new file mode 100644 index 00000000..8cb81107 --- /dev/null +++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/KeyStoreConfigurationTest.java @@ -0,0 +1,190 @@ +package at.gv.egiz.eaaf.core.test.credentials; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; + +@RunWith(BlockJUnit4ClassRunner.class) +public class KeyStoreConfigurationTest { + + private Map config; + + @Before + public void testSetup() { + config = new HashMap<>(); + + } + + @Test + public void emptyConfigMap() { + try { + KeyStoreConfiguration.buildFromConfigurationMap(config, "jUnitTest"); + Assert.fail("Wrong config not detected"); + + } catch (final EaafConfigurationException e) { + Assert.assertEquals("wrong errorCode", "internal.keystore.04", e.getErrorId()); + } + } + + @Test + public void emptyKeyStoreType() { + try { + config.put("keystore.type", ""); + + KeyStoreConfiguration.buildFromConfigurationMap(config, "jUnitTest"); + Assert.fail("Wrong config not detected"); + + } catch (final EaafConfigurationException e) { + Assert.assertEquals("wrong errorCode", "internal.keystore.04", e.getErrorId()); + } + } + + @Test + public void unknownKeyStoreType() { + try { + config.put("keystore.type", "test"); + + KeyStoreConfiguration.buildFromConfigurationMap(config, "jUnitTest"); + Assert.fail("Wrong config not detected"); + + } catch (final EaafConfigurationException e) { + Assert.assertEquals("wrong errorCode", "internal.keystore.01", e.getErrorId()); + } + } + + @Test + public void pkcs11KeyStoreType() throws EaafConfigurationException { + config.put("keystore.type", "pkcs11"); + try { + final KeyStoreConfiguration keyStoreConfig = KeyStoreConfiguration.buildFromConfigurationMap(config, + "jUnitTest"); + Assert.fail("Wrong config not detected"); + + } catch (final EaafConfigurationException e) { + Assert.assertEquals("wrong errorCode", "internal.keystore.02", e.getErrorId()); + } + } + + @Test + public void hsmFacadeKeyStoreTypeMissingName() { + try { + config.put("keystore.type", "hsmfacade"); + + KeyStoreConfiguration.buildFromConfigurationMap(config, "jUnitTest"); + Assert.fail("Wrong config not detected"); + + } catch (final EaafConfigurationException e) { + Assert.assertEquals("wrong errorCode", "internal.keystore.04", e.getErrorId()); + } + } + + @Test + public void hsmFacadeKeyStoreTypeSucces() throws EaafConfigurationException { + final String keyStoreName = RandomStringUtils.randomAlphabetic(5); + config.put("keystore.type", "hsmfacade"); + config.put("keystore.name", keyStoreName); + + final KeyStoreConfiguration keyStoreConfig = KeyStoreConfiguration.buildFromConfigurationMap(config, + "jUnitTest"); + + Assert.assertNotNull("KeyStore config object", keyStoreConfig); + Assert.assertEquals("Wrong Type", KeyStoreType.HSMFACADE, keyStoreConfig.getKeyStoreType()); + Assert.assertEquals("Wrong KeyStoreName", keyStoreName, keyStoreConfig.getKeyStoreName()); + + } + + @Test + public void softwareKeyStoreTypeMissingPath() { + try { + final String keyStorePass = RandomStringUtils.randomAlphabetic(5); + config.put("keystore.type", "software"); + config.put("keystore.password", keyStorePass); + config.put("keystore.type", "jks"); + + KeyStoreConfiguration.buildFromConfigurationMap(config, "jUnitTest"); + Assert.fail("Wrong config not detected"); + + } catch (final EaafConfigurationException e) { + Assert.assertEquals("wrong errorCode", "internal.keystore.04", e.getErrorId()); + } + } + + @Test + public void softwareKeyStoreTypeMissingPassword() { + try { + final String keyStorePath = RandomStringUtils.randomAlphabetic(5); + config.put("keystore.type", "software"); + config.put("keystore.software.path", keyStorePath); + config.put("keystore.type", "jks"); + + KeyStoreConfiguration.buildFromConfigurationMap(config, "jUnitTest"); + Assert.fail("Wrong config not detected"); + + } catch (final EaafConfigurationException e) { + Assert.assertEquals("wrong errorCode", "internal.keystore.04", e.getErrorId()); + } + } + + @Test + public void softwareKeyStoreTypeUnknownType() { + try { + final String keyStorePath = RandomStringUtils.randomAlphabetic(5); + final String keyStorePass = RandomStringUtils.randomAlphabetic(5); + config.put("keystore.path", keyStorePath); + config.put("keystore.password", keyStorePass); + config.put("keystore.type", RandomStringUtils.randomAlphabetic(4)); + + KeyStoreConfiguration.buildFromConfigurationMap(config, "jUnitTest"); + Assert.fail("Wrong config not detected"); + + } catch (final EaafConfigurationException e) { + Assert.assertEquals("wrong errorCode", "internal.keystore.01", e.getErrorId()); + } + } + + @Test + public void softwareKeyStoreTypeSuccesJks() throws EaafConfigurationException { + final String keyStorePath = RandomStringUtils.randomAlphabetic(5); + final String keyStorePass = RandomStringUtils.randomAlphabetic(5); + config.put("keystore.type", "jks"); + config.put("keystore.path", keyStorePath); + config.put("keystore.password", keyStorePass); + + final KeyStoreConfiguration keyStoreConfig = KeyStoreConfiguration.buildFromConfigurationMap(config, + "jUnitTest"); + + Assert.assertNotNull("KeyStore config object", keyStoreConfig); + Assert.assertEquals("Wrong Type", KeyStoreType.JKS, keyStoreConfig.getKeyStoreType()); + Assert.assertEquals("Wrong KeyStoreName", keyStorePath, keyStoreConfig.getSoftKeyStoreFilePath()); + Assert.assertEquals("Wrong KeyStoreName", keyStorePass, keyStoreConfig.getSoftKeyStorePassword()); + + } + + @Test + public void softwareKeyStoreTypeSuccesPkcs12() throws EaafConfigurationException { + final String keyStorePath = RandomStringUtils.randomAlphabetic(5); + final String keyStorePass = RandomStringUtils.randomAlphabetic(5); + config.put("keystore.type", "pkcs12"); + config.put("keystore.path", keyStorePath); + config.put("keystore.password", keyStorePass); + + final KeyStoreConfiguration keyStoreConfig = KeyStoreConfiguration.buildFromConfigurationMap(config, + "jUnitTest"); + + Assert.assertNotNull("KeyStore config object", keyStoreConfig); + Assert.assertEquals("Wrong Type", KeyStoreType.PKCS12, keyStoreConfig.getKeyStoreType()); + Assert.assertEquals("Wrong KeyStoreName", keyStorePath, keyStoreConfig.getSoftKeyStoreFilePath()); + Assert.assertEquals("Wrong KeyStoreName", keyStorePass, keyStoreConfig.getSoftKeyStorePassword()); + + } +} diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/dummy/DummyAuthConfigMap.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/dummy/DummyAuthConfigMap.java new file mode 100644 index 00000000..bf1dfd03 --- /dev/null +++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/dummy/DummyAuthConfigMap.java @@ -0,0 +1,142 @@ +package at.gv.egiz.eaaf.core.test.dummy; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; + +/** + * Dummy Application-configuration implementation for jUnit tests. + * + * @author tlenz + * + */ +public class DummyAuthConfigMap implements IConfigurationWithSP { + + private Map config = new HashMap<>(); + + /** + * Creates an emptry configuration. + * + */ + public DummyAuthConfigMap() { + + } + + /** + * Dummy Application-configuration. + * + * @param configIs Property based configuration + * @throws IOException In case of an configuration read error + */ + public DummyAuthConfigMap(final InputStream configIs) throws IOException { + + final Properties props = new Properties(); + props.load(configIs); + + config = KeyValueUtils.convertPropertiesToMap(props); + + } + + /** + * Dummy Application-configuration. + * + * @param path Path to property based configuration + * @throws IOException In case of an configuration read error + */ + public DummyAuthConfigMap(final String path) throws IOException { + + final Properties props = new Properties(); + props.load(this.getClass().getResourceAsStream(path)); + + config = KeyValueUtils.convertPropertiesToMap(props); + + } + + @Override + public String getBasicConfiguration(final String key) { + return config.get(key); + + } + + @Override + public String getBasicConfiguration(final String key, final String defaultValue) { + final String value = getBasicConfiguration(key); + if (StringUtils.isEmpty(value)) { + return defaultValue; + } else { + return value; + } + + } + + @Override + public boolean getBasicConfigurationBoolean(final String key) { + final String value = getBasicConfiguration(key); + if (StringUtils.isEmpty(value)) { + return false; + } else { + return Boolean.valueOf(value); + } + } + + @Override + public boolean getBasicConfigurationBoolean(final String key, final boolean defaultValue) { + return Boolean.parseBoolean(getBasicConfiguration(key, String.valueOf(defaultValue))); + + } + + @Override + public Map getBasicConfigurationWithPrefix(final String prefix) { + return KeyValueUtils.getSubSetWithPrefix(config, prefix); + + } + + @Override + public ISpConfiguration getServiceProviderConfiguration(final String uniqueID) + throws EaafConfigurationException { + return null; + } + + @Override + public T getServiceProviderConfiguration(final String spIdentifier, final Class decorator) + throws EaafConfigurationException { + return null; + } + + @Override + public URI getConfigurationRootDirectory() { + return new java.io.File(".").toURI(); + + } + + @Override + public String validateIdpUrl(final URL authReqUrl) throws EaafException { + return null; + } + + public void putConfigValue(final String key, final String value) { + config.put(key, value); + } + + public void removeConfigValue(final String key) { + config.remove(key); + + } + + public void clearAllConfig() { + config.clear(); + } + +} diff --git a/eaaf_core_utils/src/test/resources/data/junit_without_trustcerts.jks b/eaaf_core_utils/src/test/resources/data/junit_without_trustcerts.jks new file mode 100644 index 00000000..b5262cb8 Binary files /dev/null and b/eaaf_core_utils/src/test/resources/data/junit_without_trustcerts.jks differ diff --git a/eaaf_core_utils/src/test/resources/data/junit_without_trustcerts.p12 b/eaaf_core_utils/src/test/resources/data/junit_without_trustcerts.p12 new file mode 100644 index 00000000..c3fe2681 Binary files /dev/null and b/eaaf_core_utils/src/test/resources/data/junit_without_trustcerts.p12 differ diff --git a/eaaf_core_utils/src/test/resources/data/test.crt b/eaaf_core_utils/src/test/resources/data/test.crt new file mode 100644 index 00000000..76c18361 --- /dev/null +++ b/eaaf_core_utils/src/test/resources/data/test.crt @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIEXDCCA0SgAwIBAgIEY4Qn3zANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCQVQxSDBGBgNVBAoMP0EtVHJ1c3QgR2VzLiBmLiBTaWNoZXJoZWl0c3N5c3RlbWUgaW0gZWxla3RyLiBEYXRlbnZlcmtlaHIgR21iSDEmMCQGA1UECwwdYS1zaWduLVRlc3QtUHJlbWl1bS1Nb2JpbGUtMDUxJjAkBgNVBAMMHWEtc2lnbi1UZXN0LVByZW1pdW0tTW9iaWxlLTA1MB4XDTE5MTIxMzEzNDg0N1oXDTI0MTIxMzEzNDg0N1owYDELMAkGA1UEBhMCQVQxFzAVBgNVBAMMDk1heCBNdXN0ZXJtYW5uMRMwEQYDVQQEDApNdXN0ZXJtYW5uMQwwCgYDVQQqDANNYXgxFTATBgNVBAUTDDgxNjkyMjY1ODM0ODBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAUAVvbow4O/DMA5ZZoPHQXe0rtf86lvH8GLM/Crz1vvRYyQ5D4ESYRFy+s3zHdLqhE4l8I95i9jz2qTvof46mqjggGfMIIBmzCBggYIKwYBBQUHAQEEdjB0MEkGCCsGAQUFBzAChj1odHRwOi8vd3d3LmEtdHJ1c3QuYXQvY2VydHMvYS1zaWduLXRlc3QtcHJlbWl1bS1tb2JpbGUtMDUuY3J0MCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5hLXRydXN0LmF0L29jc3AwEwYDVR0jBAwwCoAITuhoD/7N29AwEQYDVR0OBAoECEyqhgBwLul2MA4GA1UdDwEB/wQEAwIGwDAJBgNVHRMEAjAAMIGGBgNVHSAEfzB9MHsGBiooABEBBDBxMDgGCCsGAQUFBwICMCwaKkRpZXNlcyBaZXJ0aWZpa2F0IGRpZW50IG51ciB6dSBUZXN0endlY2tlbjA1BggrBgEFBQcCARYpaHR0cDovL3d3dy5hLXRydXN0LmF0L2RvY3MvY3AvYS1zaWduLVRFU1QwSAYDVR0fBEEwPzA9oDugOYY3aHR0cDovL2NybC5hLXRydXN0LmF0L2NybC9hLXNpZ24tdGVzdC1wcmVtaXVtLW1vYmlsZS0wNTANBgkqhkiG9w0BAQsFAAOCAQEATD4ZnrEV+xeT7PFI/idqHdElLZ1BVUO9G9qfQQn4oKNCWWHxMo/ZXSlvsOtTjFezCQFkcFO1eJtXNHCyqfr69jorzhZcicscNRMrDlJoB/sJr0l/Ekjlt/dgRaTuZ7NzWE/oTefI3M3xkkLd0ydAMrhrZx+9f82VE3k63I1fmT90kQ8PfDzAMMRmlwbZDA+2TB8iF7SQkOOL6H1j2L9qrhjlG2ekU4cyx6KMkRjLLbr1JVgS07qOzUkeQPR2KTJcWWR+/NQZWDKdOz97eVOulxeI+Y3y96arraGM7lIbV9ZrpkbUn/IxQ9TQTE5X02EipgnZdR7bZrwJ7hJ27vwnfQ== +-----END CERTIFICATE----- diff --git a/eaaf_core_utils/src/test/resources/spring/test_eaaf_pvp_lazy.beans.xml b/eaaf_core_utils/src/test/resources/spring/test_eaaf_pvp_lazy.beans.xml new file mode 100644 index 00000000..210b88be --- /dev/null +++ b/eaaf_core_utils/src/test/resources/spring/test_eaaf_pvp_lazy.beans.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/eaaf_core_utils/src/test/resources/spring/test_eaaf_pvp_not_lazy.beans.xml b/eaaf_core_utils/src/test/resources/spring/test_eaaf_pvp_not_lazy.beans.xml new file mode 100644 index 00000000..402e07f9 --- /dev/null +++ b/eaaf_core_utils/src/test/resources/spring/test_eaaf_pvp_not_lazy.beans.xml @@ -0,0 +1,19 @@ + + + + + + + + + \ 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 --- .../core/exception/EaafKeyAccessException.java | 22 ++ .../core/impl/credential/EaafKeyStoreFactory.java | 1 + .../core/impl/credential/EaafKeyStoreUtils.java | 147 +++++++++++ .../impl/credential/KeyStoreConfiguration.java | 41 +++- .../messages/eaaf_utils_message.properties | 4 +- .../test/credentials/EaafKeyStoreFactoryTest.java | 81 ++++++ eaaf_core_utils/src/test/resources/data/junit.jks | Bin 0 -> 3980 bytes .../gv/egiz/eaaf/modules/auth/sl20/Constants.java | 40 ++- .../modules/auth/sl20/utils/JsonSecurityUtils.java | 271 ++++++++++----------- .../impl/utils/AbstractCredentialProvider.java | 11 +- 10 files changed, 460 insertions(+), 158 deletions(-) create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/exception/EaafKeyAccessException.java create mode 100644 eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java create mode 100644 eaaf_core_utils/src/test/resources/data/junit.jks (limited to 'eaaf_core_utils/src/test') diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/exception/EaafKeyAccessException.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/exception/EaafKeyAccessException.java new file mode 100644 index 00000000..f9abd6d9 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/exception/EaafKeyAccessException.java @@ -0,0 +1,22 @@ +package at.gv.egiz.eaaf.core.exception; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; + +public class EaafKeyAccessException extends EaafException { + + private static final long serialVersionUID = -2641273589744430903L; + + public static final String ERROR_CODE_08 = "internal.keystore.08"; + public static final String ERROR_CODE_09 = "internal.keystore.09"; + + public EaafKeyAccessException(String errorCode, String... params) { + super(errorCode, new Object[] {params}); + + } + + public EaafKeyAccessException(String errorCode, Throwable e, String... params) { + super(errorCode, new Object[] {params}, e); + + } + +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java index f13013f5..5e6ca34b 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java @@ -48,6 +48,7 @@ public class EaafKeyStoreFactory { public static final String ERRORCODE_04 = "internal.keystore.04"; public static final String ERRORCODE_05 = "internal.keystore.05"; public static final String ERRORCODE_06 = "internal.keystore.06"; + public static final String ERRORCODE_07 = "internal.keystore.07"; private static final String HSM_FACADE_PROVIDER = "HsmFacade"; private static final String HSM_FACADE_KEYSTORE_TYPE = "RemoteKeyStore"; diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java new file mode 100644 index 00000000..b4b44724 --- /dev/null +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreUtils.java @@ -0,0 +1,147 @@ +package at.gv.egiz.eaaf.core.impl.credential; + +import java.security.Key; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +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; +import javax.annotation.Nullable; + +import at.gv.egiz.eaaf.core.exception.EaafKeyAccessException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EaafKeyStoreUtils { + private static final String ERROR_MSG_REASON = "Maybe 'Alias' is not valid"; + private static final String ERROR_MSG_1 = "Can NOT access key: {} in KeyStore: {}. Reason: {}"; + private static final String ERROR_MSG_2 = "Key: {} will be NOT available"; + + /** + * Read all certificates from a {@link KeyStore}. + * + * @param keyStore KeyStore with certificates + * @return {@link List} of {@link X509Certificate}, but never null + * @throws KeyStoreException In case of an error during KeyStore operations + */ + @Nonnull + public static 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 Collections.unmodifiableList(result); + } + + /** + * Get a specific private Key and the corresponding certificate from a {@link KeyStore}. + * + * @param keyStore KeyStore with certificates + * @param keyAlias Alias of the entry + * @param keyPassword Password to access the Key + * @param isRequired if true, the method throw an {@link EaafKeyAccessException} + * if the key is not available or invalid + * @param friendlyName Name of the KeyStore for logging purposes + * @return A {@link Pair} of {@link Key} and {@link X509Certificate} for this alias, + * or maybe null if isRequired was false + * @throws EaafKeyAccessException In case of an error during KeyStore operations + */ + @Nullable + public static Pair getPrivateKeyAndCertificates(@Nonnull KeyStore keyStore, + @Nonnull String keyAlias, @Nullable char[] keyPassword, boolean isRequired, @Nonnull String friendlyName) + throws EaafKeyAccessException { + try { + Key privKey = keyStore.getKey(keyAlias, keyPassword); + if (privKey != null) { + final Certificate[] certChainSigning = keyStore.getCertificateChain(keyAlias); + X509Certificate[] certChain = new X509Certificate[certChainSigning.length]; + + for (int i = 0; i < certChainSigning.length; i++) { + if (certChainSigning[i] instanceof X509Certificate) { + certChain[i] = (X509Certificate) certChainSigning[i]; + } else { + log.warn("NO X509 certificate for signing: " + certChainSigning[i].getType()); + } + + } + + Pair keyResult = Pair.newInstance(privKey, certChain); + validateKeyResult(keyResult, friendlyName, keyAlias); + return keyResult; + + } else { + if (isRequired) { + log.warn(ERROR_MSG_1, + keyAlias, friendlyName, ERROR_MSG_REASON); + throw new EaafKeyAccessException(EaafKeyAccessException.ERROR_CODE_09, + friendlyName, keyAlias, ERROR_MSG_REASON); + + } else { + log.info(ERROR_MSG_1, + keyAlias, friendlyName, ERROR_MSG_REASON); + log.info(ERROR_MSG_2, keyAlias); + + } + } + + } catch (KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException e) { + if (isRequired) { + log.warn(ERROR_MSG_1, + keyAlias, friendlyName, e.getMessage()); + throw new EaafKeyAccessException( + EaafKeyAccessException.ERROR_CODE_09, e, friendlyName, keyAlias, e.getMessage()); + + } else { + log.info(ERROR_MSG_1, + keyAlias, friendlyName, e.getMessage()); + log.info(ERROR_MSG_2, keyAlias); + + } + } + + return null; + + } + + private static void validateKeyResult(Pair keyResult, + String friendlyName, String keyAlias) throws EaafKeyAccessException { + // some short validation + if (!(keyResult.getFirst() instanceof PrivateKey)) { + log.info("PrivateKey: {} in KeyStore: {} is of wrong type", keyAlias, friendlyName); + throw new EaafKeyAccessException( + EaafKeyAccessException.ERROR_CODE_09, + friendlyName, keyAlias, "Wrong PrivateKey type "); + + } + + if (keyResult.getSecond() == null || keyResult.getSecond().length == 0) { + log.info("NO certificate for Key: {} in KeyStore: {}", keyAlias, friendlyName); + throw new EaafKeyAccessException( + EaafKeyAccessException.ERROR_CODE_09, + friendlyName, keyAlias, "NO certificate for PrivateKey"); + + } + } +} diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/KeyStoreConfiguration.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/KeyStoreConfiguration.java index 400b724f..6dbbba3e 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/KeyStoreConfiguration.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/KeyStoreConfiguration.java @@ -137,6 +137,31 @@ public class KeyStoreConfiguration { } + /** + * Validate the internal state of this configuration object. + * + * @throws EaafConfigurationException In case of a configuration error + */ + public void validate() throws EaafConfigurationException { + if (KeyStoreType.HSMFACADE.equals(keyStoreType)) { + log.trace("Validate HSM-Facade KeyStore ... "); + checkConfigurationValue(keyStoreName, EaafKeyStoreFactory.ERRORCODE_07, + friendlyName, "Missing 'KeyName' for HSM-Facade"); + + } else if (KeyStoreType.PKCS12.equals(keyStoreType) + || KeyStoreType.JKS.equals(keyStoreType)) { + log.trace("Validate software KeyStore ... "); + checkConfigurationValue(softKeyStoreFilePath, EaafKeyStoreFactory.ERRORCODE_07, + friendlyName, "Missing 'KeyPath' for software keystore"); + checkConfigurationValue(softKeyStorePassword, EaafKeyStoreFactory.ERRORCODE_07, + friendlyName, "Missing 'KeyPassword' for software keystore"); + + } else { + log.info("Validation of type: {} not supported yet", keyStoreType); + + } + } + public enum KeyStoreType { PKCS12("pkcs12"), JKS("jks"), HSMFACADE("hsmfacade"), PKCS11("pkcs11"); @@ -182,12 +207,18 @@ public class KeyStoreConfiguration { @Nonnull String configParamKey) throws EaafConfigurationException { final String configValue = config.get(configParamKey); - if (StringUtils.isEmpty(configValue)) { - throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_04, new Object[] { configParamKey }); - - } - + checkConfigurationValue(configValue, EaafKeyStoreFactory.ERRORCODE_04, configParamKey); return configValue; + } + private static void checkConfigurationValue(String configValue, String errorCode, String... params) + throws EaafConfigurationException { + if (StringUtils.isEmpty(configValue)) { + throw new EaafConfigurationException(errorCode, + new Object[] { params}); + + } + + } } diff --git a/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties b/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties index 970b8e5a..2d9a863a 100644 --- a/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties +++ b/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties @@ -5,6 +5,8 @@ internal.keystore.03=HSM-Facade initialization failed with a generic error: {0} internal.keystore.04=HSM-Facade has a wrong configuration. Missing property: {0} internal.keystore.05=HSM-Facade has a wrong configuration. Property: {0} Reason:{1} internal.keystore.06=KeyStore: {0} initialization failed. Reason: {1} - +internal.keystore.07=Validation of KeyStore: {0} failed. Reason: {1} +internal.keystore.08=Can not access Key: {1} in KeyStore: {0} +internal.keystore.09=Can not access Key: {1} in KeyStore: {0} Reason: {2} diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java index 805000cb..c47805e8 100644 --- a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java +++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/test/credentials/EaafKeyStoreFactoryTest.java @@ -1,6 +1,10 @@ package at.gv.egiz.eaaf.core.test.credentials; +import java.security.Key; import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.X509Certificate; +import java.util.List; import org.apache.commons.lang3.RandomStringUtils; import org.junit.Assert; @@ -20,12 +24,15 @@ import com.google.common.base.Predicates; import com.google.common.base.Throwables; import com.google.common.collect.FluentIterable; +import at.gv.egiz.eaaf.core.exception.EaafKeyAccessException; import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.EaafFactoryException; 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.test.dummy.DummyAuthConfigMap; import io.grpc.StatusRuntimeException; @@ -34,6 +41,8 @@ import io.grpc.StatusRuntimeException; @DirtiesContext(methodMode = MethodMode.BEFORE_METHOD) public class EaafKeyStoreFactoryTest { + private static final String PATH_TO_SOFTWARE_KEYSTORE_JKS_WITH_TRUSTED_CERTS = + "src/test/resources/data/junit.jks"; private static final String PATH_TO_SOFTWARE_KEYSTORE_JKS = "src/test/resources/data/junit_without_trustcerts.jks"; private static final String PATH_TO_SOFTWARE_KEYSTORE_PKCS12 = @@ -254,10 +263,78 @@ public class EaafKeyStoreFactoryTest { keyStoreConfig.setSoftKeyStoreFilePath(PATH_TO_SOFTWARE_KEYSTORE_JKS); keyStoreConfig.setSoftKeyStorePassword(SOFTWARE_KEYSTORE_PASSWORD); + keyStoreConfig.validate(); final KeyStore keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); Assert.assertNotNull("KeyStore is null", keyStore); + } + + @Test + @DirtiesContext + public void softwareKeyStoreAccessOperations() throws EaafException, KeyStoreException { + final EaafKeyStoreFactory keyStoreFactory = context.getBean(EaafKeyStoreFactory.class); + Assert.assertFalse("HSM Facade state wrong", keyStoreFactory.isHsmFacadeInitialized()); + + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setKeyStoreType(KeyStoreType.JKS); + keyStoreConfig.setSoftKeyStoreFilePath(PATH_TO_SOFTWARE_KEYSTORE_JKS_WITH_TRUSTED_CERTS); + keyStoreConfig.setSoftKeyStorePassword(SOFTWARE_KEYSTORE_PASSWORD); + + keyStoreConfig.validate(); + + final KeyStore keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); + Assert.assertNotNull("KeyStore is null", keyStore); + + //read trusted certs + List trustedCerts = EaafKeyStoreUtils.readCertsFromKeyStore(keyStore); + Assert.assertNotNull("Trusted certs", trustedCerts); + Assert.assertEquals("Trusted certs size", 2, trustedCerts.size()); + + //read priv. key + Pair privCred1 = EaafKeyStoreUtils.getPrivateKeyAndCertificates( + keyStore, "meta", "password".toCharArray(), true, "jUnit test"); + Assert.assertNotNull("Credential 1", privCred1); + Assert.assertNotNull("Credential 1 priv. key", privCred1.getFirst()); + Assert.assertNotNull("Credential 1 certificate", privCred1.getSecond()); + + //read priv. key + Pair privCred2 = EaafKeyStoreUtils.getPrivateKeyAndCertificates( + keyStore, "sig", "password".toCharArray(), true, "jUnit test"); + Assert.assertNotNull("Credential 2", privCred2); + Assert.assertNotNull("Credential 2 priv. key", privCred2.getFirst()); + Assert.assertNotNull("Credential 2 certificate", privCred2.getSecond()); + + + //read priv. key + Pair privCred3 = EaafKeyStoreUtils.getPrivateKeyAndCertificates( + keyStore, "notexist", "password".toCharArray(), false, "jUnit test"); + Assert.assertNull("Credential 3", privCred3); + + //read priv. key + Pair privCred4 = EaafKeyStoreUtils.getPrivateKeyAndCertificates( + keyStore, "meta", "wrong".toCharArray(), false, "jUnit test"); + Assert.assertNull("Credential 3", privCred4); + + try { + EaafKeyStoreUtils.getPrivateKeyAndCertificates( + keyStore, "meta", "wrong".toCharArray(), true, "jUnit test"); + Assert.fail("Wrong password not detected"); + + } catch (EaafKeyAccessException e) { + Assert.assertEquals("wrong errorcode", "internal.keystore.09", e.getErrorId()); + } + + try { + EaafKeyStoreUtils.getPrivateKeyAndCertificates( + keyStore, "wrong", "password".toCharArray(), true, "jUnit test"); + Assert.fail("Wrong alias not detected"); + + } catch (EaafKeyAccessException e) { + Assert.assertEquals("wrong errorcode", "internal.keystore.09", e.getErrorId()); + } + + } @Test @@ -271,6 +348,8 @@ public class EaafKeyStoreFactoryTest { keyStoreConfig.setSoftKeyStoreFilePath(PATH_TO_SOFTWARE_KEYSTORE_PKCS12); keyStoreConfig.setSoftKeyStorePassword(SOFTWARE_KEYSTORE_PASSWORD); + keyStoreConfig.validate(); + final KeyStore keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); Assert.assertNotNull("KeyStore is null", keyStore); @@ -524,6 +603,8 @@ public class EaafKeyStoreFactoryTest { keyStoreConfig.setKeyStoreType(KeyStoreType.HSMFACADE); keyStoreConfig.setKeyStoreName("testkeyStore"); + keyStoreConfig.validate(); + try { final KeyStore keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); Assert.assertNotNull("KeyStore is null", keyStore); diff --git a/eaaf_core_utils/src/test/resources/data/junit.jks b/eaaf_core_utils/src/test/resources/data/junit.jks new file mode 100644 index 00000000..59e6ad13 Binary files /dev/null and b/eaaf_core_utils/src/test/resources/data/junit.jks differ 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