summaryrefslogtreecommitdiff
path: root/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java
diff options
context:
space:
mode:
Diffstat (limited to 'eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java')
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java257
1 files changed, 257 insertions, 0 deletions
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..5e6ca34b
--- /dev/null
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java
@@ -0,0 +1,257 @@
+package at.gv.egiz.eaaf.core.impl.credential;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.Nullable;
+import javax.annotation.PostConstruct;
+
+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 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 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";
+ 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";
+
+ @Autowired
+ private IConfiguration basicConfig;
+ @Autowired
+ private ResourceLoader resourceLoader;
+
+ private boolean isHsmFacadeInitialized = false;
+
+ /**
+ * Get a new KeyStore based on a KeyStore configuration-object.
+ *
+ * @param config KeyStore configuration
+ * @return new KeyStore instance
+ * @throws EaafException In case of a KeyStore initialization error
+ */
+ public KeyStore buildNewKeyStore(KeyStoreConfiguration config) throws EaafException {
+ log.trace("Starting KeyStore generation based on configuration object ... ");
+ if (KeyStoreType.PKCS12.equals(config.getKeyStoreType())
+ || KeyStoreType.JKS.equals(config.getKeyStoreType())) {
+ return getKeyStoreFromFileSystem(config);
+
+ } else if (KeyStoreType.HSMFACADE.equals(config.getKeyStoreType())) {
+ if (isHsmFacadeInitialized) {
+ return 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() });
+
+ }
+ }
+
+ /**
+ * Get the initialization state of the HSM Facade module.
+ *
+ * @return true if HSM Facade is available, otherwise false
+ */
+ public boolean isHsmFacadeInitialized() {
+ return isHsmFacadeInitialized;
+
+ }
+
+ @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.parseUnsignedInt(
+ 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,
+ EaafFactoryException {
+ try {
+ final String keyStorePath = checkConfigurationParameter(config.getSoftKeyStoreFilePath(),
+ ERRORCODE_06, config.getFriendlyName(), "Software-KeyStore missing filepath to KeyStore");
+
+ final String keyStorePassword = checkConfigurationParameter(config.getSoftKeyStorePassword(),
+ ERRORCODE_06, config.getFriendlyName(), "Software-KeyStore missing Password for KeyStore");
+
+ 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 });
+
+ }
+
+ final InputStream is = ressource.getInputStream();
+ final KeyStore keyStore = KeyStoreUtils.loadKeyStore(is, keyStorePassword);
+ is.close();
+ if (keyStore == null) {
+ throw new EaafFactoryException(ERRORCODE_06,
+ new Object[] { config.getFriendlyName(), "KeyStore not valid or password wrong" });
+
+ }
+
+ return keyStore;
+
+ } 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 = checkConfigurationParameter(config.getKeyStoreName(),
+ ERRORCODE_06, config.getFriendlyName(), "KeyStoreName missing for HSM Facade");
+
+ try {
+ final KeyStore keyStore = KeyStore.getInstance(HSM_FACADE_KEYSTORE_TYPE, HSM_FACADE_PROVIDER);
+ 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 {
+ return checkConfigurationParameter(
+ basicConfig.getBasicConfiguration(configParamKey), ERRORCODE_04, configParamKey);
+
+ }
+
+ @Nonnull
+ private String checkConfigurationParameter(@Nullable String configParam, @Nonnull String errorCode,
+ @Nonnull String... errorParams)
+ throws EaafConfigurationException {
+ if (StringUtils.isEmpty(configParam)) {
+ throw new EaafConfigurationException(errorCode, new Object[] { errorParams });
+
+ }
+ return configParam;
+
+ }
+
+}