MockServer uses port unification to simplify configuration so all protocols (i.e. HTTP, HTTPS / SSL, SOCKS, etc) are supported on the same port. This means when a request is sent over TLS (i.e. an HTTPS request) MockServer dynamically detects that the request is encrypted.

The majority of HTTP clients perform the following steps when making an HTTPS request:

  1. establish TCP connection to remote server
  2. perform TLS handshake with remote server and verify trust chain by receiving remote server X.509 Certificate and verifying it is signed by a know Certificate Authority
  3. perform hostname validation by comparing hostname (or IP address) of remote server with Subject Alternative Name (SAN) or Common Name (CN) on X.509

MockServer provides multiple ways its TLS can be configured.

 

Ensure MockServer Certificates Are Trusted

The MockServer CA X.509 must be considered a valid trust root to ensure MockServer's dynamically generate X.509 certificates are trusted by an HTTP Client. This means the CA X.509 needs to be added into the JVM, HTTP Client or operating system as appropriate.

The MockServer CA X.509 can be found (in PEM format) in the MockServer github repo or can be loaded from the classpath location /org/mockserver/socket/CertificateAuthorityCertificate.pem

Operating System

It is technically possible to add the MockServer CA X.509 as a trusted root CA to your operating system, this will make most clients applications running on your OS (such as browsers) trust dynamically generated certificates from MockServer.

This is generally not a good idea or if it is done it should be done for a very short period to record expectations or perform a quick test. During this period do not navigate to any sensitive sites like banks or email servers.

This is not completely safe to do this because the private key for the MockServer Root CA is in the MockServer repository and therefore anyone could potentially use this to generate certificates that appear to have comes from MockServer.

Web Browsers

Browsers (such as Chrome, Firefox or IE) may not always trust dynamically generated certificates from MockServer because of Certificate Transparency and Public Key Pinning both of which make it hard to dynamically generate certificates that are trusted.

Some sites will work but others (such as google sites) won't work due to certificate pinning.

Browser that rely on Certificate Transparency will likely not trust dynamically generated certificates from MockServer

Java via Classpath

The following code shows how to load a file from the classpath or a relative filesystem location:

public void doSomething() {
    String mockServerCA = loadFileFromLocation("/org/mockserver/socket/CertificateAuthorityCertificate.pem");
}

public String loadFileFromLocation(String location) {
    location = location.trim().replaceAll("\\\\", "/");

    Path path;
    if (location.toLowerCase().startsWith("file:")) {
        path = Paths.get(URI.create(location));
    } else {
        path = Paths.get(location);
    }

    if (Files.exists(path)) {
        // org.apache.commons.io.FileUtils
        return FileUtils.readFileToString(path.toFile(), "UTF-8");
    } else {
        return loadFileFromClasspath(location);
    }
}

private String loadFileFromClasspath(String location) {
    InputStream inputStream = this.getClass().getResourceAsStream(location);

    if (inputStream == null) {
        inputStream = this.getClass().getClassLoader().getResourceAsStream(location);
    }

    if (inputStream == null) {
        inputStream = ClassLoader.getSystemResourceAsStream(location);
    }

    if (inputStream != null) {
        try {
            // org.apache.commons.io.IOUtils
            return IOUtils.toString(inputStream, Charsets.UTF_8);
        } catch (IOException e) {
            throw new RuntimeException("Could not read " + location + " from the classpath", e);
        }
    }

    throw new RuntimeException("Could not find " + location + " on the classpath");
}

Java DefaultSSLSocketFactory

Another mechanism to ensure the MockServer X.509 is trusted is to configure the DefaultSSLSocketFactory in the JVM using the following line:

HttpsURLConnection.setDefaultSSLSocketFactory(new KeyStoreFactory(new MockServerLogger()).sslContext().getSocketFactory());

This can be used in a test case, as follows:

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockserver.integration.ClientAndServer;
import org.mockserver.logging.MockServerLogger;
import org.mockserver.socket.PortFactory;
import org.mockserver.socket.tls.KeyStoreFactory;

import javax.net.ssl.HttpsURLConnection;

public class ExampleTestClass {

    private static ClientAndServer mockServer;

    @BeforeClass
    public static void startMockServer() {
        // ensure all connection using HTTPS will use the SSL context defined by
        // MockServer to allow dynamically generated certificates to be accepted
        HttpsURLConnection.setDefaultSSLSocketFactory(new KeyStoreFactory(new MockServerLogger()).sslContext().getSocketFactory());
        mockServer = ClientAndServer.startClientAndServer(PortFactory.findFreePort());
    }

    @AfterClass
    public static void stopMockServer() {
        mockServer.stop();
    }

    @Test
    public void shouldDoSomething() {
        // test system
    }
}

Java Keytool

The Java keytool command can also be used to add the MockServer CA X.509 certificate to the list of trust CA Certificates for a JVM, as follows:

keytool -import -v -keystore /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts -alias mockserver-ca -file CertificateAuthorityCertificate.pem -storepass changeit -trustcacerts -noprompt

An example bash script showing how this can be done can be found in the MockServer github repo

 

Hostname Validation

MockServer is able to mock the behaviour of multiple hostnames (i.e. servers) and present a valid X.509 Certificates for them. MockServer achieves this by dynamically generating its X.509 Certificate using an in-memory list of hostnames. When the list of hostnames changes a new certificate is generated. The list of hostnames is updated, when:

  • configuration for SAN hostnames or SAN IP addresses is specified
  • an expectation is added containing a Host header with a hostname not seen before
  • a request is received containing a Host header with a hostname not seen before
  • a TLS handshake using Server Name Indication (SNI) with a hostname not seen before

Note: if a request is received with a Host header for a hostname not seen before the first request will fail validation because the TLS connection has already been established before the Host header can be read, any subsequent requests with that hostname will pass hostname validation.

 

Configuration:

HTTPS (i.e. TLS / SSL) support can be configured as follows:

The relative or absolute file path to the java key store

Type: string Default: `mockserver_keystore` file name with extension depending on `mockserver.javaKeyStoreType` property

Java Code:

ConfigurationProperties.javaKeyStoreFilePath(String keyStoreFilePath)

System Property:

-Dmockserver.javaKeyStoreFilePath=...

Environment Variable:

MOCKSERVER_JAVA_KEY_STORE_FILE_PATH=...

Property File:

mockserver.javaKeyStoreFilePath=...

Example:

-Dmockserver.javaKeyStoreFilePath="mockserver_keystore.jks"

The java key store password

Type: string Default: changeit

Java Code:

ConfigurationProperties.javaKeyStorePassword(String keyStorePassword)

System Property:

-Dmockserver.javaKeyStorePassword=...

Environment Variable:

MOCKSERVER_JAVA_KEY_STORE_PASSWORD=...

Property File:

mockserver.javaKeyStorePassword=...

Example:

-Dmockserver.javaKeyStorePassword="changeit"

The type of the java key store

Type: string Default: KeyStore.getDefaultType() - in Java 1.7 this uses the system property `keystore.type` or defaults to `jks`

Java Code:

ConfigurationProperties.javaKeyStoreType(String keyStoreType)

System Property:

-Dmockserver.javaKeyStoreType=...

Environment Variable:

MOCKSERVER_JAVA_KEY_STORE_TYPE=...

Property File:

mockserver.javaKeyStoreType=...

Example:

-Dmockserver.javaKeyStoreType="jks"

Determines if an auto-generated java key store file is deleted on exit

Type: boolean Default: true

Java Code:

ConfigurationProperties.deleteGeneratedKeyStoreOnExit(boolean deleteGeneratedKeyStoreOnExit)

System Property:

-Dmockserver.deleteGeneratedKeyStoreOnExit=...

Environment Variable:

MOCKSERVER_DELETE_GENERATED_KEY_STORE_ON_EXIT=...

Property File:

mockserver.deleteGeneratedKeyStoreOnExit=...

Example:

-Dmockserver.deleteGeneratedKeyStoreOnExit="false"

The domain name for auto-generate TLS certificates

Type: string Default: localhost

Java Code:

ConfigurationProperties.sslCertificateDomainName(String domainName)

System Property:

-Dmockserver.sslCertificateDomainName=...

Environment Variable:

MOCKSERVER_SSL_CERTIFICATE_DOMAIN_NAME=...

Property File:

mockserver.sslCertificateDomainName=...

Example:

-Dmockserver.sslCertificateDomainName="localhost"

The Subject Alternative Name (SAN) domain names for auto-generate TLS certificates as a comma separated list

Type: string Default: localhost

Java Code:

ConfigurationProperties.addSslSubjectAlternativeNameDomains(String... additionalSubjectAlternativeNameDomains)
or
ConfigurationProperties.clearSslSubjectAlternativeNameDomains()

System Property:

-Dmockserver.sslSubjectAlternativeNameDomains=...

Environment Variable:

MOCKSERVER_SSL_SUBJECT_ALTERNATIVE_NAME_DOMAINS=...

Property File:

mockserver.sslSubjectAlternativeNameDomains=...

Example:

-Dmockserver.sslSubjectAlternativeNameDomains="localhost,www.foo.bar"

The Subject Alternative Name (SAN) IP addresses for auto-generate TLS certificates as a comma separated list

Type: string Default: 127.0.0.1,0.0.0.0

Java Code:

ConfigurationProperties.addSslSubjectAlternativeNameIps(String... additionalSubjectAlternativeNameIps)
or
ConfigurationProperties.clearSslSubjectAlternativeNameIps()

System Property:

-Dmockserver.sslSubjectAlternativeNameIps=...

Environment Variable:

MOCKSERVER_SSL_SUBJECT_ALTERNATIVE_NAME_IPS=...

Property File:

mockserver.sslSubjectAlternativeNameIps=...

Example:

-Dmockserver.sslSubjectAlternativeNameIps="127.0.0.1,0.0.0.0"

MockServer dynamically updates the Subject Alternative Name (SAN) values for its TLS certificate to add domain names and IP addresses from request Host headers and Host headers in expectations, this configuration setting disables this automatic update and only uses SAN value provided in TLS Subject Alternative Name Domains and TLS Subject Alternative Name IPs configuration properties.

Type: boolean Default: false

Java Code:

ConfigurationProperties.preventCertificateDynamicUpdate(boolean prevent)

System Property:

-Dmockserver.preventCertificateDynamicUpdate=...

Environment Variable:

MOCKSERVER_PREVENT_CERTIFICATE_DYNAMIC_UPDATE=...

Property File:

mockserver.preventCertificateDynamicUpdate=...

Example:

-Dmockserver.preventCertificateDynamicUpdate="true"

Location of custom file for Certificate Authority for TLS, the private key must be a PEM file and must match the TLS Certificate Authority X509 Certificate.

Type: boolean Default: null

Java Code:

ConfigurationProperties.certificateAuthorityPrivateKey(String certificateAuthorityPrivateKey)

System Property:

-Dmockserver.certificateAuthorityPrivateKey=...

Environment Variable:

MOCKSERVER_CERTIFICATE_AUTHORITY_PRIVATE_KEY=...

Property File:

mockserver.certificateAuthorityPrivateKey=...

Example:

-Dmockserver.certificateAuthorityPrivateKey="true"

Location of custom file for Certificate Authority for TLS, the certificate must be a X509 PEM file and must match the TLS Certificate Authority Private Key.

Type: boolean Default: null

Java Code:

ConfigurationProperties.certificateAuthorityCertificate(String certificateAuthorityCertificate)

System Property:

-Dmockserver.certificateAuthorityCertificate=...

Environment Variable:

MOCKSERVER_CERTIFICATE_AUTHORITY_X509_CERTIFICATE=...

Property File:

mockserver.certificateAuthorityCertificate=...

Example:

-Dmockserver.certificateAuthorityCertificate="true"

Location used to save dynamically generated certificates, by default this is saved as a temporary file by the JVM, for example: /var/folders/lz/_kbrwxrx4ss3brnc0y9ms2vc0000gn/T/MockServerCertificate75d431bb-cbf1-4cfe-b8a2-000ece2150e3.pem1048371440427200504.tmp.

Type: boolean Default: File.createTempFile(...)

Java Code:

ConfigurationProperties.directoryToSaveDynamicSSLCertificate(String directoryToSaveDynamicSSLCertificate)

System Property:

-Dmockserver.directoryToSaveDynamicSSLCertificate=...

Environment Variable:

MOCKSERVER_CERTIFICATE_DIRECTORY_TO_SAVE_DYNAMIC_SSL_CERTIFICATE=...

Property File:

mockserver.directoryToSaveDynamicSSLCertificate=...

Example:

-Dmockserver.directoryToSaveDynamicSSLCertificate="/some/existing/path"