diff options
Diffstat (limited to 'modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/AbstractSoapClient.java')
-rw-r--r-- | modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/AbstractSoapClient.java | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/AbstractSoapClient.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/AbstractSoapClient.java new file mode 100644 index 00000000..a039881c --- /dev/null +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/AbstractSoapClient.java @@ -0,0 +1,199 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.clients; + +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.net.ssl.SSLContext; +import javax.xml.ws.BindingProvider; +import javax.xml.ws.handler.Handler; + +import org.apache.commons.lang3.StringUtils; +import org.apache.cxf.configuration.jsse.TLSClientParameters; +import org.apache.cxf.endpoint.Client; +import org.apache.cxf.frontend.ClientProxy; +import org.apache.cxf.jaxws.DispatchImpl; +import org.apache.cxf.transport.http.HTTPConduit; +import org.apache.cxf.transports.http.configuration.HTTPClientPolicy; +import org.apache.http.ssl.SSLContextBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.Nullable; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.LoggingHandler; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.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.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.http.HttpUtils; +import lombok.Builder; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class AbstractSoapClient { + + @Autowired + protected IConfiguration basicConfig; + @Autowired + EaafKeyStoreFactory keyStoreFactory; + + @Builder + @Getter + public static class HttpClientConfig { + + private final String clientName; + + private final String clientUrl; + private final String clientType; + + private final String connectionTimeout; + private final String responseTimeout; + + private final KeyStoreConfiguration keyStoreConfig; + private final String keyAlias; + private final String keyPassword; + + private final KeyStoreConfiguration trustStoreConfig; + + @Builder.Default + private final boolean trustAll = false; + + } + + /** + * Build a validated KeyStore Configuration-Object from configuration keys. + * + * @param keyStoreTypeKey Configuration key for type + * @param keyStorePathKey Configuration key for path + * @param keyStorePasswordKey Configuration key for password + * @param keyStoreNameKey Configuration key for name + * @param friendlyName Friendlyname for logging and errorhandling + * @return Valid KeyStore configuration or <code>null</code> if no type was + * defined + * @throws EaafConfigurationException In case of validation error + */ + @Nullable + protected KeyStoreConfiguration buildKeyStoreConfiguration(String keyStoreTypeKey, String keyStorePathKey, + String keyStorePasswordKey, String keyStoreNameKey, String friendlyName) + throws EaafConfigurationException { + if (StringUtils.isNotEmpty(basicConfig.getBasicConfiguration(keyStoreTypeKey))) { + log.debug("Starting configuration of: {} ... ", friendlyName); + final KeyStoreConfiguration config = new KeyStoreConfiguration(); + config.setFriendlyName(friendlyName); + config.setKeyStoreType(basicConfig.getBasicConfiguration(keyStoreTypeKey, KeyStoreType.PKCS12.name())); + config.setKeyStoreName(basicConfig.getBasicConfiguration(keyStoreNameKey)); + config.setSoftKeyStoreFilePath(basicConfig.getBasicConfiguration(keyStorePathKey)); + config.setSoftKeyStorePassword(basicConfig.getBasicConfiguration(keyStorePasswordKey)); + + // validate keystore configuration + config.validate(); + + return config; + + } else { + log.info("Skipping configuration of: {}", friendlyName); + return null; + + } + + } + + protected void injectHttpClient(Object raw, HttpClientConfig config) { + // extract client from implementation + Client client; + if (raw instanceof DispatchImpl<?>) { + client = ((DispatchImpl<?>) raw).getClient(); + } else if (raw instanceof Client) { + client = ClientProxy.getClient(raw); + } else { + throw new RuntimeException("SOAP Client for SZR connection is of UNSUPPORTED type: " + raw.getClass() + .getName()); + } + + // set basic connection policies + final HTTPConduit http = (HTTPConduit) client.getConduit(); + + // set timeout policy + final HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy(); + httpClientPolicy.setConnectionTimeout(Integer.parseInt(config.getConnectionTimeout()) * 1000L); + httpClientPolicy.setReceiveTimeout(Integer.parseInt(config.getResponseTimeout()) * 1000L); + http.setClient(httpClientPolicy); + + // inject SSL context in case of https + if (config.getClientUrl().toLowerCase().startsWith("https")) { + try { + log.debug("Adding SSLContext to client: " + config.getClientType() + " ... "); + + final TLSClientParameters tlsParams = new TLSClientParameters(); + if (config.getKeyStoreConfig() != null) { + final SSLContext sslContext = HttpUtils.buildSslContextWithSslClientAuthentication( + keyStoreFactory.buildNewKeyStore(config.getKeyStoreConfig()), + config.getKeyAlias(), + config.getKeyPassword(), + loadTrustStore(config.getTrustStoreConfig(), config.getClientName()), + config.isTrustAll(), + config.getClientName()); + tlsParams.setSSLSocketFactory(sslContext.getSocketFactory()); + + } else { + log.debug( + "No KeyStore for SSL Client Auth. found. Initializing SSLContext for: {} without authentication ... ", + config.getClientName()); + tlsParams.setSSLSocketFactory(SSLContextBuilder.create().build().getSocketFactory()); + + } + + http.setTlsClientParameters(tlsParams); + log.info("SSLContext initialized for client: " + config.getClientType()); + + } catch (EaafException | KeyManagementException | NoSuchAlgorithmException e) { + log.error("SSLContext initialization FAILED.", e); + throw new RuntimeException("SSLContext initialization FAILED.", e); + + } + } + } + + private Pair<KeyStore, Provider> loadTrustStore(KeyStoreConfiguration trustStoreConfig, String friendlyName) + throws EaafException { + if (trustStoreConfig != null) { + log.info("Build custom SSL truststore for: {}", friendlyName); + return keyStoreFactory.buildNewKeyStore(trustStoreConfig); + + } else { + log.info("Use default SSL truststore for: {}", friendlyName); + return null; + + } + + } + + protected void injectBindingProvider(BindingProvider bindingProvider, String clientType, String szrUrl, + boolean enableTraceLogging) { + final Map<String, Object> requestContext = bindingProvider.getRequestContext(); + requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, szrUrl); + + log.trace("Adding JAX-WS request/response trace handler to client: " + clientType); + List<Handler> handlerList = bindingProvider.getBinding().getHandlerChain(); + if (handlerList == null) { + handlerList = new ArrayList<>(); + bindingProvider.getBinding().setHandlerChain(handlerList); + + } + + // add logging handler to trace messages if required + if (enableTraceLogging) { + final LoggingHandler loggingHandler = new LoggingHandler(); + handlerList.add(loggingHandler); + + } + bindingProvider.getBinding().setHandlerChain(handlerList); + } +} |