/******************************************************************************* * Copyright 2020 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; import at.gv.egiz.moazs.client.ClientFactory; import at.gv.egiz.moazs.scheme.Marshaller; import at.gv.zustellung.app2mzs.xsd.ClientType; import at.gv.zustellung.app2mzs.xsd.KeyStoreType; import at.gv.zustellung.msg.xsd.App2ZusePort; import at.gv.zustellung.msg.xsd.DeliveryRequestType; import at.gv.zustellung.msg.xsd.ObjectFactory; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.xml.bind.JAXBElement; import javax.xml.ws.soap.SOAPFaultException; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.math.BigInteger; import static at.gv.zustellung.app2mzs.xsd.ClientType.clientTypeBuilder; import static at.gv.zustellung.app2mzs.xsd.KeyStoreType.keyStoreTypeBuilder; import static at.gv.zustellung.app2mzs.xsd.SSLType.SSLTypeBuilder; import static org.assertj.core.api.Assertions.assertThat; /** * @author Christof Rabensteiner * */ @RunWith(SpringRunner.class) @SpringBootTest public class ITSSLMsgClientTest { private static final Object VALID_MZS_REQUEST_ID = "valid-delivery-request-id" ; private final String basePath = "src/test/resources/at/gv/egiz/moazs/ITSSLMsgClientTest/"; @Autowired private Marshaller msgMarshaller; @Autowired private ClientFactory factory; private static final ObjectFactory OF = new ObjectFactory(); // Requirements: // - run zusemsg service under httpServiceURL @Test public void sendValidMessage() throws IOException { var request = loadFromFile("validDeliveryRequest.xml"); var httpServiceURL = "http://localhost:8081/services/app2zuse"; var clientParams = clientTypeBuilder() .withURL(httpServiceURL) .withConnectionTimeout(BigInteger.ZERO) .withReceiveTimeout(BigInteger.ZERO) .build(); App2ZusePort port = createPort(clientParams); var status = port.delivery(request); assertThat(status.getPartialSuccess().getAppDeliveryID()).isEqualTo(VALID_MZS_REQUEST_ID); } private App2ZusePort createPort(ClientType params) { return factory.createMsgClient(params); } // Requirements: // - run zusemsg service under httpsServiceURL // - server trusts client cert (by trusting CA bundle in ssl/trusted-cas-bundle.pem) // - server uses the server certificate in ssl/server/server.localhost.*.pem // - server sends certificate chain ssl/server/ca-chain.cert.pem @Test public void sendOverSSLWithClientAuthentication() throws IOException { var request = loadFromFile("validDeliveryRequest.xml"); var httpsServiceURL = "https://localhost/app2zuse/services/app2zuse"; var clientParams = generateSSLClientParams(httpsServiceURL, false, false); App2ZusePort port = createPort(clientParams); var status = port.delivery(request); assertThat(status.getPartialSuccess().getAppDeliveryID()).isEqualTo(VALID_MZS_REQUEST_ID); } // Requirements: // - run zusemsg service under httpsServiceURL // - server trusts client cert (by trusting CA bundle in ssl/trusted-cas-bundle.pem) // - server uses the server certificate in ssl/server/server.localhost.*.pem // - server sends certificate chain ssl/server/ca-chain.cert.pem @Test public void sendOverSSLWithClientAuthTrustAll() throws IOException { var request = loadFromFile("validDeliveryRequest.xml"); var httpsServiceURL = "https://localhost/app2zuse/services/app2zuse"; var clientParams = generateSSLClientParams(httpsServiceURL, true, false); App2ZusePort port = createPort(clientParams); var status = port.delivery(request); assertThat(status.getPartialSuccess().getAppDeliveryID()).isEqualTo(VALID_MZS_REQUEST_ID); } // Requirements: // - run zusemsg service under httpsServiceURL (e.g. by adding notlocalhost to /etc/hosts) // - server trusts client cert (by trusting CA bundle in ssl/trusted-cas-bundle.pem) // - server uses the server certificate in ssl/server/server.localhost.*.pem // - server sends certificate chain ssl/server/ca-chain.cert.pem @Test public void sendOverSSLWithClientAuthLaxHostnameVerification() throws IOException { var request = loadFromFile("validDeliveryRequest.xml"); var httpsServiceURL = "https://notlocalhost/app2zuse/services/app2zuse"; var clientParams = generateSSLClientParams(httpsServiceURL, false, true); App2ZusePort port = createPort(clientParams); var status = port.delivery(request); assertThat(status.getPartialSuccess().getAppDeliveryID()).isEqualTo(VALID_MZS_REQUEST_ID); } //Requirements: // - run zusemsg service under httpsServiceURL (e.g. by adding notlocalhost to /etc/hosts) // - server trusts client cert (by trusting CA bundle in ssl/trusted-cas-bundle.pem) // - server uses the server certificate in ssl/server/server.localhost.*.pem // - server sends certificate chain ssl/server/ca-chain.cert.pem @Test(expected=SOAPFaultException.class) public void rejectBecauseHostNameVerificationFails() throws IOException { var request = loadFromFile("validDeliveryRequest.xml"); var httpsServiceURL = "https://notlocalhost/app2zuse/services/app2zuse"; var clientParams = generateSSLClientParams(httpsServiceURL, false, false); App2ZusePort port = createPort(clientParams); port.delivery(request); } private ClientType generateSSLClientParams(String httpsServiceURL, boolean trustAll, boolean laxHostNameVerification) { return generateSSLClientParams(httpsServiceURL, trustAll, laxHostNameVerification, generateTrustLocalhostStore()); } private ClientType generateSSLClientParams(String httpsServiceURL, boolean trustAll, boolean laxHostNameVerification, KeyStoreType truststore) { var keystore = keyStoreTypeBuilder() .withFileName("config/ssl/client.cert.key.p12") .withFileType("PKCS12") .withPassword("123456") .build(); var sslParams = SSLTypeBuilder() .withLaxHostNameVerification(laxHostNameVerification) .withTrustAll(trustAll) .withKeyStore(keystore) .withTrustStore(trustAll ? null : truststore) .build(); return clientTypeBuilder() .withURL(httpsServiceURL) .withSSL(sslParams) .withReceiveTimeout(BigInteger.ZERO) .withConnectionTimeout(BigInteger.ZERO) .build(); } private KeyStoreType generateTrustLocalhostStore() { return keyStoreTypeBuilder() .withFileName("config/ssl/truststore.jks") .withPassword("123456") .withFileType("JKS") .build(); } private DeliveryRequestType loadFromFile(String fileName) throws IOException { try (var inputStream = new BufferedInputStream(new FileInputStream(basePath + fileName))) { var request = (JAXBElement) msgMarshaller.unmarshallXml(inputStream); return request.getValue(); } } }