package eu.ztsh.mockserver.tests import eu.ztsh.mockserver.api.common.Https import eu.ztsh.mockserver.api.request.AddMock import eu.ztsh.mockserver.client.RemoteMockServer import eu.ztsh.mockserver.client.Util import eu.ztsh.mockserver.server.HttpMockServer import groovy.xml.slurpersupport.GPathResult import org.apache.http.client.methods.CloseableHttpResponse import org.apache.http.client.methods.HttpPost import org.apache.http.conn.ssl.SSLConnectionSocketFactory import org.apache.http.conn.ssl.SSLContexts import org.apache.http.entity.ContentType import org.apache.http.entity.StringEntity import org.apache.http.impl.client.CloseableHttpClient import org.apache.http.impl.client.HttpClients import spock.lang.AutoCleanup import spock.lang.Ignore import spock.lang.Shared import spock.lang.Specification import javax.net.ssl.SSLContext import javax.net.ssl.SSLHandshakeException import java.security.KeyStore @Ignore class MockServerHttpsTest extends Specification { RemoteMockServer remoteMockServer = new RemoteMockServer('localhost', 19000) @AutoCleanup('stop') HttpMockServer httpMockServer = new HttpMockServer(19000) @Shared SSLContext noClientAuthSslContext = SSLContexts.custom() .loadTrustMaterial(trustStore()) .build() @Shared SSLContext trustedCertificateSslContext = SSLContexts.custom() .loadKeyMaterial(trustedCertificateKeystore(), 'changeit'.toCharArray()) .loadTrustMaterial(trustStore()) .build() @Shared SSLContext untrustedCertificateSslContext = SSLContexts.custom() .loadKeyMaterial(untrustedCertificateKeystore(), 'changeit'.toCharArray()) .loadTrustMaterial(trustStore()) .build() @Ignore("TODO: SSL peer shut down incorrectly") def 'should handle HTTPS server' () { given: remoteMockServer.addMock(new AddMock( name: 'testHttps', path: 'testEndpoint', port: 10443, predicate: '''{req -> req.xml.name() == 'request'}''', response: '''{req -> ""}''', https: new Https( keyPassword: 'changeit', keystorePassword: 'changeit', keystorePath: MockServerHttpsTest.classLoader.getResource('keystore.jks').path ), soap: false )) when: HttpPost restPost = new HttpPost('https://localhost:10443/testEndpoint') restPost.entity = new StringEntity('', ContentType.create("text/xml", "UTF-8")) CloseableHttpResponse response = client(noClientAuthSslContext).execute(restPost) then: GPathResult restPostResponse = Util.extractXmlResponse(response) restPostResponse.name() == 'goodResponse-request' } @Ignore("TODO: SSL peer shut down incorrectly") def 'should handle HTTPS server with client auth' () { given: remoteMockServer.addMock(new AddMock( name: 'testHttps', path: 'testEndpoint', port: 10443, predicate: '''{req -> req.xml.name() == 'request'}''', response: '''{req -> ""}''', https: new Https( keyPassword: 'changeit', keystorePassword: 'changeit', keystorePath: MockServerHttpsTest.classLoader.getResource('keystore.jks').path, truststorePath: MockServerHttpsTest.classLoader.getResource('truststore.jks').path, truststorePassword: 'changeit', requireClientAuth: true ), soap: false )) when: HttpPost restPost = new HttpPost('https://localhost:10443/testEndpoint') restPost.entity = new StringEntity('', ContentType.create("text/xml", "UTF-8")) CloseableHttpResponse response = client(trustedCertificateSslContext).execute(restPost) then: GPathResult restPostResponse = Util.extractXmlResponse(response) restPostResponse.name() == 'goodResponse-request' } def 'should handle HTTPS server with wrong client auth' () { given: remoteMockServer.addMock(new AddMock( name: 'testHttps', path: 'testEndpoint', port: 10443, predicate: '''{req -> req.xml.name() == 'request'}''', response: '''{req -> ""}''', https: new Https( keyPassword: 'changeit', keystorePassword: 'changeit', keystorePath: MockServerHttpsTest.classLoader.getResource('keystore.jks').path, truststorePath: MockServerHttpsTest.classLoader.getResource('truststore.jks').path, truststorePassword: 'changeit', requireClientAuth: true ), soap: false )) when: HttpPost restPost = new HttpPost('https://localhost:10443/testEndpoint') restPost.entity = new StringEntity('', ContentType.create("text/xml", "UTF-8")) client(sslContext).execute(restPost) then: thrown(SSLHandshakeException) where: sslContext << [noClientAuthSslContext, untrustedCertificateSslContext] } private CloseableHttpClient client(SSLContext sslContext) { return HttpClients.custom() .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) .setSslcontext(sslContext) .build() } private KeyStore trustedCertificateKeystore() { return loadKeystore('trusted.jks') } private KeyStore untrustedCertificateKeystore() { return loadKeystore('untrusted.jks') } private KeyStore trustStore() { return loadKeystore('truststore.jks') } private KeyStore loadKeystore(String fileName) { KeyStore truststore = KeyStore.getInstance(KeyStore.defaultType) truststore.load(new FileInputStream(MockServerHttpsTest.classLoader.getResource(fileName).path), "changeit".toCharArray()); return truststore } }