summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lenz <thomas.lenz@egiz.gv.at>2020-02-12 19:01:59 +0100
committerThomas Lenz <thomas.lenz@egiz.gv.at>2020-02-12 19:01:59 +0100
commitcbfadcc7681c9f362c1e7e2c3eab43980c1236ef (patch)
tree6ca517c539a88574bd195c298ca1b47339a8fadf
parente02aa41578ec3e08dd96fde9ef0342b69a051ba6 (diff)
downloadEAAF-Components-cbfadcc7681c9f362c1e7e2c3eab43980c1236ef.tar.gz
EAAF-Components-cbfadcc7681c9f362c1e7e2c3eab43980c1236ef.tar.bz2
EAAF-Components-cbfadcc7681c9f362c1e7e2c3eab43980c1236ef.zip
add first untested version of EaafKeyStoreFactory that supports Software-Keystore and HSM-Facade
-rw-r--r--eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/exceptions/EaafFactoryException.java18
-rw-r--r--eaaf_core_utils/pom.xml5
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java216
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/KeyStoreConfiguration.java59
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/pom.xml6
-rw-r--r--pom.xml7
6 files changed, 305 insertions, 6 deletions
diff --git a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/exceptions/EaafFactoryException.java b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/exceptions/EaafFactoryException.java
new file mode 100644
index 00000000..f556a781
--- /dev/null
+++ b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/exceptions/EaafFactoryException.java
@@ -0,0 +1,18 @@
+package at.gv.egiz.eaaf.core.exceptions;
+
+public class EaafFactoryException extends EaafException {
+
+ private static final long serialVersionUID = 4710605711787308220L;
+
+ /**
+ * In case that a factory can not build an object.
+ *
+ * @param errorId ErrorCode
+ * @param params Message parameters
+ * @param e Exception
+ */
+ public EaafFactoryException(String errorId, Object[] params, Throwable e) {
+ super(errorId, params, e);
+ }
+
+}
diff --git a/eaaf_core_utils/pom.xml b/eaaf_core_utils/pom.xml
index 84ab46f5..6392fb76 100644
--- a/eaaf_core_utils/pom.xml
+++ b/eaaf_core_utils/pom.xml
@@ -42,6 +42,11 @@
</dependency>
<dependency>
+ <groupId>at.asitplus.hsmfacade</groupId>
+ <artifactId>provider</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
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
new file mode 100644
index 00000000..af184050
--- /dev/null
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java
@@ -0,0 +1,216 @@
+package at.gv.egiz.eaaf.core.impl.credential;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+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;
+import at.gv.egiz.eaaf.core.exceptions.EaafFactoryException;
+import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType;
+import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
+import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class EaafKeyStoreFactory {
+
+ public static final String CONFIG_PROP_HSM_FACADE_HOST = "security.hsmfacade.host";
+ public static final String CONFIG_PROP_HSM_FACADE_PORT = "security.hsmfacade.port";
+ public static final String CONFIG_PROP_HSM_FACADE_SSLTRUST = "security.hsmfacade.trustedsslcert";
+ public static final String CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME = "security.hsmfacade.username";
+ public static final String CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD = "security.hsmfacade.password";
+ public static final String CONFIG_PROP_HSM_FACADE_HSM_NAME = "security.hsmfacade.hsmname";
+
+ public static final String ERRORCODE_00 = "internal.keystore.00";
+ public static final String ERRORCODE_01 = "internal.keystore.01";
+ public static final String ERRORCODE_02 = "internal.keystore.02";
+ public static final String ERRORCODE_03 = "internal.keystore.03";
+ 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";
+
+ @Autowired private IConfiguration basicConfig;
+ @Autowired private ResourceLoader resourceLoader;
+
+ private boolean isHsmFacadeInitialized = false;
+
+
+
+ public KeyStore buildNewKeyStore(KeyStoreConfiguration config) throws EaafException {
+ log.trace("Starting KeyStore generation based on configuration object ... ");
+ if (KeyStoreType.SOFTWARE.equals(config.getKeyStoreType())) {
+ return getKeyStoreFromFileSystem(config);
+
+ } else if (KeyStoreType.HSMFACADE.equals(config.getKeyStoreType())) {
+ if (isHsmFacadeInitialized) {
+ getKeyStoreFromHsmFacade(config);
+
+ } else {
+ log.error("HSMFacade can NOT be used for KeyStore: {} because {} is not initialized",
+ config.getFriendlyName());
+ throw new EaafConfigurationException(ERRORCODE_00,
+ new Object[]{config.getFriendlyName()});
+
+ }
+
+ } else if (KeyStoreType.PKCS11.equals(config.getKeyStoreType())) {
+ log.warn("KeyStoreType: {} is NOT supported", config.getKeyStoreType());
+ throw new EaafConfigurationException(ERRORCODE_02,
+ new Object[]{config.getFriendlyName(), config.getKeyStoreType()});
+
+ } else {
+ log.warn("KeyStoreType: {} is unrecognized", config.getKeyStoreType());
+ throw new EaafConfigurationException(ERRORCODE_01,
+ new Object[]{config.getFriendlyName()});
+
+ }
+ return null;
+ }
+
+ @PostConstruct
+ private void initialize() throws EaafException {
+
+ final String hsmFacadeHost = basicConfig.getBasicConfiguration(CONFIG_PROP_HSM_FACADE_HOST);
+ if (StringUtils.isNotEmpty(hsmFacadeHost)) {
+ log.debug("Find host for HSMFacade. Starting crypto provider initialization ... ");
+ try {
+ final int port = Integer.valueOf(
+ getConfigurationParameter(CONFIG_PROP_HSM_FACADE_PORT));
+ final String clientUsername =
+ getConfigurationParameter(CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME);
+ final String clientPassword =
+ getConfigurationParameter(CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD);
+ final String hsmName =
+ getConfigurationParameter(CONFIG_PROP_HSM_FACADE_HSM_NAME);
+
+ final HsmFacadeProvider provider = HsmFacadeProvider.Companion.getInstance();
+ provider.init(getHsmFacadeTrustSslCertificate(), clientUsername, clientPassword, hsmFacadeHost, port, hsmName);
+ Security.addProvider(provider);
+ isHsmFacadeInitialized = true;
+ log.info("HSM Facade is initialized. {} can provide KeyStores based on remote HSM",
+ EaafKeyStoreFactory.class.getSimpleName());
+
+ } catch (final EaafException e) {
+ throw e;
+
+ } catch (final Exception e) {
+ log.error("HSM Facade initialization FAILED with an generic error.", e);
+ throw new EaafConfigurationException(ERRORCODE_03, new Object[] {e.getMessage()}, e);
+ }
+
+ } else {
+ log.info("HSM Facade is not configurated. {} can only provide software keystores",
+ EaafKeyStoreFactory.class.getSimpleName());
+
+ }
+
+ }
+
+ private KeyStore getKeyStoreFromFileSystem(KeyStoreConfiguration config) throws EaafConfigurationException {
+ try {
+ final String keyStorePath = config.getKeyStoreFilePath();
+ final String keyStorePassword = config.getKeyStorePassword();
+
+ //TODO: check config
+
+ final String absKeyStorePath = FileUtils.makeAbsoluteUrl(keyStorePath, basicConfig.getConfigurationRootDirectory());
+ final Resource ressource = resourceLoader.getResource(absKeyStorePath);
+ if (!ressource.exists()) {
+ throw new EaafConfigurationException(ERRORCODE_05,
+ new Object[] {CONFIG_PROP_HSM_FACADE_SSLTRUST,
+ "File not found at: " + absKeyStorePath});
+
+ }
+
+ return KeyStoreUtils.loadKeyStore(ressource.getInputStream(), keyStorePassword);
+
+ } catch (KeyStoreException | IOException e) {
+ log.error("Software KeyStore initialization FAILED with an generic error.", e);
+ throw new EaafConfigurationException(ERRORCODE_03, new Object[] {e.getMessage()}, e);
+
+ }
+ }
+
+ private KeyStore getKeyStoreFromHsmFacade(KeyStoreConfiguration config) throws EaafFactoryException, EaafConfigurationException {
+ final String keyStoreName = config.getKeyStoreName();
+ if (StringUtils.isEmpty(keyStoreName)) {
+ throw new EaafConfigurationException(ERRORCODE_06,
+ new Object[] {config.getFriendlyName(), "No KeyStore name"});
+
+ }
+
+ try {
+ final KeyStore keyStore = KeyStore.getInstance("RemoteKeyStore", "HsmFacade");
+ keyStore.load(new RemoteKeyStoreLoadParameter(keyStoreName));
+ return keyStore;
+
+ } catch (NoSuchAlgorithmException | CertificateException | IOException |
+ KeyStoreException | NoSuchProviderException e) {
+ log.error("Can not initialize KeyStore: {} with reason: {}",
+ config.getFriendlyName(), e.getMessage());
+ throw new EaafFactoryException(ERRORCODE_06,
+ new Object[] {config.getFriendlyName(), e.getMessage()}, e);
+
+ }
+ }
+
+ private X509Certificate getHsmFacadeTrustSslCertificate() throws EaafConfigurationException {
+ try {
+ final String certFilePath = getConfigurationParameter(CONFIG_PROP_HSM_FACADE_SSLTRUST);
+
+ final String absolutCertFilePath = FileUtils.makeAbsoluteUrl(
+ certFilePath, basicConfig.getConfigurationRootDirectory());
+ final Resource certFile = resourceLoader.getResource(absolutCertFilePath);
+
+ if (!certFile.exists()) {
+ throw new EaafConfigurationException(ERRORCODE_05,
+ new Object[] {CONFIG_PROP_HSM_FACADE_SSLTRUST,
+ "File not found at: " + absolutCertFilePath });
+
+ }
+
+ return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certFile.getInputStream());
+
+ } catch (final EaafConfigurationException e) {
+ throw e;
+
+ } catch (CertificateException | IOException e) {
+ log.error("Can not load trusted server-certificate for HSM-Facade. Reason: {}", e.getMessage());
+ throw new EaafConfigurationException(ERRORCODE_05,
+ new Object[] {CONFIG_PROP_HSM_FACADE_SSLTRUST, e.getMessage()}, e);
+
+ }
+ }
+
+ @Nonnull
+ private String getConfigurationParameter(@Nonnull String configParamKey)
+ throws EaafConfigurationException{
+ final String configValue = basicConfig.getBasicConfiguration(configParamKey);
+ if (StringUtils.isEmpty(configValue)) {
+ throw new EaafConfigurationException(ERRORCODE_04, new Object[] {configParamKey});
+
+ }
+
+ return configValue;
+ }
+
+}
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
new file mode 100644
index 00000000..c8489ac0
--- /dev/null
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/KeyStoreConfiguration.java
@@ -0,0 +1,59 @@
+package at.gv.egiz.eaaf.core.impl.credential;
+
+import lombok.Getter;
+
+@Getter
+public class KeyStoreConfiguration {
+
+ private String friendlyName;
+
+ private KeyStoreType keyStoreType;
+
+ private String keyStoreName;
+
+ private String keyStoreFilePath;
+
+ private String keyStorePassword;
+
+
+ public enum KeyStoreType {
+ SOFTWARE("software"), HSMFACADE("hsmfacade"), PKCS11("pkcs11");
+
+ private final String keyStoreType;
+
+ KeyStoreType(final String keyStoreType) {
+ this.keyStoreType = keyStoreType;
+ }
+
+ /**
+ * Get Type of this KeyStore.
+ *
+ * @return
+ */
+ public String getKeyStoreType() {
+ return this.keyStoreType;
+ }
+
+ /**
+ * Get KeyStore type from String representation.
+ *
+ * @param s Config parameter
+ * @return
+ */
+ public static KeyStoreType fromString(final String s) {
+ try {
+ return KeyStoreType.valueOf(s.toUpperCase());
+
+ } catch (IllegalArgumentException | NullPointerException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getKeyStoreType();
+
+ }
+
+ }
+}
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 @@
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <hsm-facade-provider.version>0.1.1-SNAPSHOT</hsm-facade-provider.version>
</properties>
<dependencies>
@@ -24,11 +23,6 @@
<version>${egiz.eaaf.version}</version>
</dependency>
<dependency>
- <groupId>at.asitplus.hsmfacade</groupId>
- <artifactId>provider</artifactId>
- <version>${hsm-facade-provider.version}</version>
- </dependency>
- <dependency>
<groupId>org.opensaml</groupId>
<artifactId>opensaml-core</artifactId>
</dependency>
diff --git a/pom.xml b/pom.xml
index 669d9da2..fe63c752 100644
--- a/pom.xml
+++ b/pom.xml
@@ -43,6 +43,7 @@
<iaik.prod.iaik_xades.version>2.13_moa</iaik.prod.iaik_xades.version>
<iaik.prod.iaik_xsect.version>2.13_moa</iaik.prod.iaik_xsect.version>
+ <hsm-facade-provider.version>0.1.1-SNAPSHOT</hsm-facade-provider.version>
<!-- Other third-party libs -->
<org.springframework.version>5.1.5.RELEASE</org.springframework.version>
@@ -315,6 +316,12 @@
</dependency>
<dependency>
+ <groupId>at.asitplus.hsmfacade</groupId>
+ <artifactId>provider</artifactId>
+ <version>${hsm-facade-provider.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>${javax.annotation-api}</version>