/******************************************************************************* * Copyright 2019 Graz University of Technology * MOA ZS has been developed in a cooperation between EGIZ * and Graz University of Technology. * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. *******************************************************************************/ package at.gv.egiz.moazs.client; import at.gv.egiz.moazs.preprocess.ConfigUtil; import at.gv.egiz.moazs.util.FileUtils; import at.gv.egiz.moazs.util.StoreSOAPBodyBinaryInRepositoryInterceptor; import at.gv.zustellung.app2mzs.xsd.ClientType; import at.gv.zustellung.app2mzs.xsd.KeyStoreType; import at.gv.zustellung.app2mzs.xsd.Mzs2AppPortType; import at.gv.zustellung.app2mzs.xsd.SSLType; import at.gv.zustellung.msg.xsd.App2ZusePort; import at.gv.zustellung.tnvz.xsd.TNVZServicePort; import org.apache.cxf.configuration.jsse.TLSClientParameters; import org.apache.cxf.endpoint.Client; import org.apache.cxf.ext.logging.LoggingInInterceptor; import org.apache.cxf.ext.logging.LoggingOutInterceptor; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.interceptor.Interceptor; import org.apache.cxf.jaxws.JaxWsClientFactoryBean; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import org.apache.cxf.message.Message; import org.apache.cxf.transport.http.HTTPConduit; import org.apache.cxf.transports.http.configuration.HTTPClientPolicy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; import javax.net.ssl.SSLContext; import javax.xml.ws.BindingProvider; import javax.xml.ws.soap.SOAPBinding; import static at.gv.zustellung.app2mzs.xsd.KeyStoreType.keyStoreTypeBuilder; /** * @author Christof Rabensteiner * */ @Component public class ClientFactory { private static final Logger log = LoggerFactory.getLogger(ClientFactory.class); private final StoreSOAPBodyBinaryInRepositoryInterceptor storeResponseInterceptor; private final SSLContextCreator sslContextCreator; private final FileUtils fileUtils; private final ConfigUtil configUtil; private static final Interceptor LOGGING_IN_INTERCEPTOR = new LoggingInInterceptor(); private static final Interceptor LOGGING_OUT_INTERCEPTOR = new LoggingOutInterceptor(); @Autowired public ClientFactory(StoreSOAPBodyBinaryInRepositoryInterceptor storeResponseInterceptor, SSLContextCreator creator, FileUtils fileUtils, ConfigUtil configUtil) { this.storeResponseInterceptor = storeResponseInterceptor; this.sslContextCreator = creator; this.fileUtils = fileUtils; this.configUtil = configUtil; } public TNVZServicePort createTnvzClient(ClientType params) { return createSOAPClient(params, TNVZServicePort.class, true, false, false); } public Mzs2AppPortType createAppClient(ClientType params) { return createSOAPClient(params, Mzs2AppPortType.class, false, false, true); } public App2ZusePort createMsgClient(ClientType params) { return createSOAPClient(params, App2ZusePort.class, true, true, true); } private T createSOAPClient(ClientType params, Class clazz, boolean isSoap12, boolean storeResponse, boolean mtomEnabled) { log.info("Create client for service {}", params.getURL()); var factory = new JaxWsClientFactoryBean(); factory.setServiceClass(clazz); factory.setAddress(params.getURL()); if (storeResponse) { factory.getInInterceptors().add(storeResponseInterceptor); } if (isSoap12) { factory.setBindingId(SOAPBinding.SOAP12HTTP_BINDING); } setupLoggingInterceptors(factory); var proxy = new JaxWsProxyFactoryBean(factory).create(); Client client = ClientProxy.getClient(proxy); HTTPConduit http = (HTTPConduit) client.getConduit(); if (mtomEnabled) { var bindingProvider = (BindingProvider) proxy; SOAPBinding binding = (SOAPBinding) bindingProvider.getBinding(); binding.setMTOMEnabled(true); } var httpClientPolicy = new HTTPClientPolicy(); httpClientPolicy.setConnectionTimeout(params.getConnectionTimeout().longValueExact()); httpClientPolicy.setReceiveTimeout(params.getReceiveTimeout().longValueExact()); http.setClient(httpClientPolicy); var customHeaders = configUtil.convertHeadersToMap(params.getCustomHTTPHeader()); client.getRequestContext().put(Message.PROTOCOL_HEADERS, customHeaders); if (params.getURL().startsWith("https")) { TLSClientParameters tlsParams = setupTLSParams(params.getSSL()); http.setTlsClientParameters(tlsParams); log.info("SSLContext initialized. "); } return ((T)proxy); } private void setupLoggingInterceptors(JaxWsClientFactoryBean factory) { factory.getInInterceptors().add(LOGGING_IN_INTERCEPTOR); factory.getInFaultInterceptors().add(LOGGING_IN_INTERCEPTOR); factory.getOutInterceptors().add(LOGGING_OUT_INTERCEPTOR); factory.getOutFaultInterceptors().add(LOGGING_OUT_INTERCEPTOR); } private TLSClientParameters setupTLSParams(SSLType ssl) { var tlsParams = new TLSClientParameters(); var keystore = resolveKeyStorePath(ssl.getKeyStore()); SSLContext sslContext; if (ssl.isTrustAll()) { sslContext = sslContextCreator.createUnsafeSSLContext(keystore); } else { var truststore = resolveKeyStorePath(ssl.getTrustStore()); sslContext = sslContextCreator.createSSLContext(keystore, truststore); } tlsParams.setSSLSocketFactory(sslContext.getSocketFactory()); if (ssl.isLaxHostNameVerification()) { tlsParams.setDisableCNCheck(true); } return tlsParams; } private KeyStoreType resolveKeyStorePath(@Nullable KeyStoreType store) { if (store == null) return null; var resolvedURI = "file:" + fileUtils.determinePath(store.getFileName()); log.trace("Resolved key store path from {} to {}.", store.getFileName(), resolvedURI); return keyStoreTypeBuilder(store) .withFileName(resolvedURI) .build(); } }