diff options
author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-02-14 08:46:52 +0100 |
---|---|---|
committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-02-14 08:46:52 +0100 |
commit | e23226c47807be597bbbae3891dbb94069d56836 (patch) | |
tree | 13419e53996ce9cfe82583cbe5a00c3be2698400 /eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential | |
parent | cbfadcc7681c9f362c1e7e2c3eab43980c1236ef (diff) | |
download | EAAF-Components-e23226c47807be597bbbae3891dbb94069d56836.tar.gz EAAF-Components-e23226c47807be597bbbae3891dbb94069d56836.tar.bz2 EAAF-Components-e23226c47807be597bbbae3891dbb94069d56836.zip |
Integrate HSM Facade from A-SIT+
The EaafKeyStoreFactory can be used to build KeyStores from differend providers and types
Diffstat (limited to 'eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential')
2 files changed, 237 insertions, 63 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 index af184050..f13013f5 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 @@ -1,6 +1,7 @@ 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; @@ -11,8 +12,14 @@ 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; @@ -22,12 +29,6 @@ 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 @@ -48,42 +49,62 @@ public class EaafKeyStoreFactory { 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; + 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.SOFTWARE.equals(config.getKeyStoreType())) { + if (KeyStoreType.PKCS12.equals(config.getKeyStoreType()) + || KeyStoreType.JKS.equals(config.getKeyStoreType())) { return getKeyStoreFromFileSystem(config); } else if (KeyStoreType.HSMFACADE.equals(config.getKeyStoreType())) { if (isHsmFacadeInitialized) { - getKeyStoreFromHsmFacade(config); + 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()}); + 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()}); + new Object[] { config.getFriendlyName(), config.getKeyStoreType() }); } else { log.warn("KeyStoreType: {} is unrecognized", config.getKeyStoreType()); throw new EaafConfigurationException(ERRORCODE_01, - new Object[]{config.getFriendlyName()}); + new Object[] { config.getFriendlyName() }); } - return null; + } + + /** + * Get the initialization state of the HSM Facade module. + * + * @return true if HSM Facade is available, otherwise false + */ + public boolean isHsmFacadeInitialized() { + return isHsmFacadeInitialized; + } @PostConstruct @@ -93,7 +114,7 @@ public class EaafKeyStoreFactory { if (StringUtils.isNotEmpty(hsmFacadeHost)) { log.debug("Find host for HSMFacade. Starting crypto provider initialization ... "); try { - final int port = Integer.valueOf( + final int port = Integer.parseUnsignedInt( getConfigurationParameter(CONFIG_PROP_HSM_FACADE_PORT)); final String clientUsername = getConfigurationParameter(CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME); @@ -103,7 +124,8 @@ public class EaafKeyStoreFactory { getConfigurationParameter(CONFIG_PROP_HSM_FACADE_HSM_NAME); final HsmFacadeProvider provider = HsmFacadeProvider.Companion.getInstance(); - provider.init(getHsmFacadeTrustSslCertificate(), clientUsername, clientPassword, hsmFacadeHost, port, hsmName); + 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", @@ -114,81 +136,91 @@ public class EaafKeyStoreFactory { } 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); + 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()); + log.info("HSM Facade is not configurated. {} can only provide software keystores", + EaafKeyStoreFactory.class.getSimpleName()); } } - private KeyStore getKeyStoreFromFileSystem(KeyStoreConfiguration config) throws EaafConfigurationException { + private KeyStore getKeyStoreFromFileSystem(KeyStoreConfiguration config) throws EaafConfigurationException, + EaafFactoryException { try { - final String keyStorePath = config.getKeyStoreFilePath(); - final String keyStorePassword = config.getKeyStorePassword(); + final String keyStorePath = checkConfigurationParameter(config.getSoftKeyStoreFilePath(), + ERRORCODE_06, config.getFriendlyName(), "Software-KeyStore missing filepath to KeyStore"); - //TODO: check config + 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 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}); + new Object[] { CONFIG_PROP_HSM_FACADE_SSLTRUST, + "File not found at: " + absKeyStorePath }); } - return KeyStoreUtils.loadKeyStore(ressource.getInputStream(), keyStorePassword); + 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); + 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"}); - - } + 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("RemoteKeyStore", "HsmFacade"); + 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); + } 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); + 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 }); + 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()); + return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certFile + .getInputStream()); } catch (final EaafConfigurationException e) { throw e; @@ -196,21 +228,29 @@ public class EaafKeyStoreFactory { } 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); + 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}); + 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; - 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 index c8489ac0..400b724f 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 @@ -1,23 +1,144 @@ package at.gv.egiz.eaaf.core.impl.credential; +import java.util.Map; + +import javax.annotation.Nonnull; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Getter +@Setter public class KeyStoreConfiguration { + public static final String PROP_CONFIG_KEYSTORE_TYPE = + "keystore.type"; + + public static final String PROP_CONFIG_HSMFACADE_NAME = + "keystore.name"; + + public static final String PROP_CONFIG_SOFTWARE_KEYSTORE_PATH = + "keystore.path"; + public static final String PROP_CONFIG_SOFTWARE_KEYSTORE_PASSORD = + "keystore.password"; + + /** + * FriendlyName for this KeyStore. Mainly used for logging. + */ private String friendlyName; + /** + * General type of the KeyStore that should be generated. + */ private KeyStoreType keyStoreType; + /** + * Name of the KeyStore in HSM Facade. + */ private String keyStoreName; - private String keyStoreFilePath; + /** + * Path to software KeyStore in case of a PKCS12 or JKS KeyStore. + */ + private String softKeyStoreFilePath; + + /** + * Password of a software KeyStore in case of a PKCS12 or JKS KeyStore. + */ + private String softKeyStorePassword; + + /** + * Build a {@link KeyStoreConfiguration} from a configuration map. <br> + * <p> + * The configuration parameters defined in this class are used to load the + * configuration. + * </p> + * + * @param config Configuration + * @param friendlyName FriendlyName for this KeyStore + * @return Configuration object for {@link EaafKeyStoreFactory} + * @throws EaafConfigurationException In case of a configuration error. + */ + public static KeyStoreConfiguration buildFromConfigurationMap(Map<String, String> config, + String friendlyName) throws EaafConfigurationException { + + final KeyStoreConfiguration internalConfig = new KeyStoreConfiguration(); + internalConfig.setFriendlyName(friendlyName); + + final KeyStoreType internalKeyStoreType = KeyStoreType.fromString( + getConfigurationParameter(config, PROP_CONFIG_KEYSTORE_TYPE)); + if (internalKeyStoreType != null) { + internalConfig.setKeyStoreType(internalKeyStoreType); + + } else { + log.error("KeyStore: {} sets an unknown KeyStore type: {}", + friendlyName, getConfigurationParameter(config, PROP_CONFIG_KEYSTORE_TYPE)); + throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_01, + new Object[] { friendlyName }); + + } + + if (internalKeyStoreType.equals(KeyStoreType.HSMFACADE)) { + log.trace("Set-up HSM-Facade KeyStore ... "); + internalConfig.setKeyStoreName( + getConfigurationParameter(config, PROP_CONFIG_HSMFACADE_NAME)); + + } else if (internalKeyStoreType.equals(KeyStoreType.PKCS12) + || internalKeyStoreType.equals(KeyStoreType.JKS)) { + log.trace("Set-up software KeyStore ... "); + internalConfig.setSoftKeyStoreFilePath( + getConfigurationParameter(config, PROP_CONFIG_SOFTWARE_KEYSTORE_PATH)); + internalConfig.setSoftKeyStorePassword( + getConfigurationParameter(config, PROP_CONFIG_SOFTWARE_KEYSTORE_PASSORD)); + + } else { + log.info("Configuration of type: {} not supported yet", internalKeyStoreType); + throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_02, + new Object[] { friendlyName, config.get(PROP_CONFIG_KEYSTORE_TYPE) }); + + } + + return internalConfig; + } - private String keyStorePassword; + /** + * Set the Type of the KeyStore based on String identifier. + * + * @param keyStoreType String based KeyStore type + * @throws EaafConfigurationException In case of an unknown KeyStore type + */ + public void setKeyStoreType(@Nonnull String keyStoreType) throws EaafConfigurationException { + final KeyStoreType internalKeyStoreType = KeyStoreType.fromString(keyStoreType); + if (internalKeyStoreType != null) { + setKeyStoreType(internalKeyStoreType); + + } else { + log.error("KeyStore: {} sets an unknown KeyStore type: {}", + friendlyName, keyStoreType); + throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_01, + new Object[] { friendlyName }); + } + + } + + /** + * Set the Type of the KeyStore based on String identifier. + * + * @param type String based KeyStore type + */ + public void setKeyStoreType(@Nonnull KeyStoreType type) { + this.keyStoreType = type; + + } public enum KeyStoreType { - SOFTWARE("software"), HSMFACADE("hsmfacade"), PKCS11("pkcs11"); + PKCS12("pkcs12"), JKS("jks"), HSMFACADE("hsmfacade"), PKCS11("pkcs11"); private final String keyStoreType; @@ -54,6 +175,19 @@ public class KeyStoreConfiguration { return getKeyStoreType(); } + } + + @Nonnull + private static String getConfigurationParameter(@Nonnull Map<String, String> config, + @Nonnull String configParamKey) + throws EaafConfigurationException { + final String configValue = config.get(configParamKey); + if (StringUtils.isEmpty(configValue)) { + throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_04, new Object[] { configParamKey }); + + } + return configValue; } + } |