diff --git a/build.gradle b/build.gradle index 8f28838825..ecd26abd0f 100644 --- a/build.gradle +++ b/build.gradle @@ -44,6 +44,7 @@ dependencies { exclude group: "org.hamcrest", module: "hamcrest-core" exclude group: "org.hamcrest", module: "hamcrest-library" } + testCompile "com.jayway.restassured:rest-assured:2.4.0" testCompile "net.sf.json-lib:json-lib:2.4:jdk15" testCompile "com.googlecode.jarjar:jarjar:1.3" testCompile "commons-io:commons-io:2.4" diff --git a/src/main/java/com/github/tomakehurst/wiremock/common/HttpsSettings.java b/src/main/java/com/github/tomakehurst/wiremock/common/HttpsSettings.java index 150b4b390a..5abf32351c 100644 --- a/src/main/java/com/github/tomakehurst/wiremock/common/HttpsSettings.java +++ b/src/main/java/com/github/tomakehurst/wiremock/common/HttpsSettings.java @@ -18,24 +18,24 @@ public class HttpsSettings { private final int port; - private final String keyStorePath; - private final String keyStorePassword; - private final String trustStorePath; - private final String trustStorePassword; + private final String keystore; + private final String keyPassword; + private final String truststore; + private final String trustPassword; private final boolean needClientAuth; - public HttpsSettings(int port, String keyStorePath, String keyStorePassword, String trustStorePath, String trustStorePassword, boolean needClientAuth) { + public HttpsSettings(int port, String keystore, String keyPassword, String truststore, String trustPassword, boolean needClientAuth) { this.port = port; - this.keyStorePath = keyStorePath; - this.keyStorePassword = keyStorePassword; - this.trustStorePath = trustStorePath; - this.trustStorePassword = trustStorePassword; + this.keystore = keystore; + this.keyPassword = keyPassword; + this.truststore = truststore; + this.trustPassword = trustPassword; this.needClientAuth = needClientAuth; } - public HttpsSettings(int port, String keyStorePath, String keyStorePassword) { - this(port, keyStorePath, keyStorePassword, null, null, false); + public HttpsSettings(int port, String keystore, String keyPassword) { + this(port, keystore, keyPassword, null, null, false); } public static final HttpsSettings NO_HTTPS = new HttpsSettings(0, null, null); @@ -44,24 +44,24 @@ public int port() { return port; } - public String keyStorePath() { - return keyStorePath; + public String keystore() { + return keystore; } public boolean enabled() { return this != NO_HTTPS; } - public String getKeyStorePassword() { - return keyStorePassword; + public String keyPassword() { + return keyPassword; } - public String getTrustStorePath() { - return trustStorePath; + public String truststore() { + return truststore; } - public String getTrustStorePassword() { - return trustStorePassword; + public String trustPassword() { + return trustPassword; } public boolean needClientAuth() { @@ -72,10 +72,10 @@ public boolean needClientAuth() { public String toString() { return "HttpsSettings{" + "port=" + port + - ", keyStorePath='" + keyStorePath + '\'' + - ", keyStorePassword='" + keyStorePassword + '\'' + - ", trustStorePath='" + trustStorePath + '\'' + - ", trustStorePassword='" + trustStorePassword + '\'' + + ", keystore='" + keystore + '\'' + + ", keyPassword='" + keyPassword + '\'' + + ", truststore='" + truststore + '\'' + + ", trustPassword='" + trustPassword + '\'' + ", needClientAuth=" + needClientAuth + '}'; } diff --git a/src/main/java/com/github/tomakehurst/wiremock/core/WireMockConfiguration.java b/src/main/java/com/github/tomakehurst/wiremock/core/WireMockConfiguration.java index c7f2d4d735..dc3619cae2 100644 --- a/src/main/java/com/github/tomakehurst/wiremock/core/WireMockConfiguration.java +++ b/src/main/java/com/github/tomakehurst/wiremock/core/WireMockConfiguration.java @@ -18,6 +18,7 @@ import com.github.tomakehurst.wiremock.common.*; import com.github.tomakehurst.wiremock.http.CaseInsensitiveKey; import com.google.common.io.Resources; +import org.apache.commons.lang.StringUtils; import java.util.List; @@ -59,23 +60,23 @@ public WireMockConfiguration httpsPort(Integer httpsPort) { return this; } - public WireMockConfiguration keystorePath(String path) { - this.keyStorePath = path; + public WireMockConfiguration keystore(String keystore) { + this.keyStorePath = keystore; return this; } - public WireMockConfiguration keystorePass(String path) { - this.keyStorePassword = path; + public WireMockConfiguration keyPassword(String password) { + this.keyStorePassword = password; return this; } - public WireMockConfiguration truststorePath(String path) { - this.trustStorePath = path; + public WireMockConfiguration truststore(String truststore) { + this.trustStorePath = truststore; return this; } - public WireMockConfiguration truststorePass(String path) { - this.trustStorePassword = path; + public WireMockConfiguration trustPassword(String password) { + this.trustStorePassword = password; return this; } @@ -164,11 +165,31 @@ public HttpsSettings httpsSettings() { return HttpsSettings.NO_HTTPS; } - if (keyStorePath == null) { - return new HttpsSettings(httpsPort, Resources.getResource("keystore").toString(), "password"); + final String keyStorePath; + if (StringUtils.isEmpty(this.keyStorePath)) { + keyStorePath = Resources.getResource("keystore").toString(); + } else { + keyStorePath = this.keyStorePath; } - return new HttpsSettings(httpsPort, keyStorePath, keyStorePassword, trustStorePath, trustStorePassword, needClientAuth); + + final String keyStorePassword; + if (StringUtils.isEmpty(this.keyStorePassword)) { + keyStorePassword = "password"; + } else { + keyStorePassword = this.keyStorePassword; + } + + if (StringUtils.isEmpty(keyStorePath)) { + throw new IllegalArgumentException("Try to enable HTTPS port but missing a valid Keystore. " + + "Please either specify a valid keystore path, " + + "or put the keystore in resource with name 'keystore'"); + } + + return new HttpsSettings(httpsPort, + keyStorePath, keyStorePassword, + trustStorePath, trustStorePassword, + needClientAuth); } @Override diff --git a/src/main/java/com/github/tomakehurst/wiremock/jetty6/Jetty6HttpServer.java b/src/main/java/com/github/tomakehurst/wiremock/jetty6/Jetty6HttpServer.java index c6fb50dc32..a051732f81 100644 --- a/src/main/java/com/github/tomakehurst/wiremock/jetty6/Jetty6HttpServer.java +++ b/src/main/java/com/github/tomakehurst/wiremock/jetty6/Jetty6HttpServer.java @@ -54,7 +54,6 @@ class Jetty6HttpServer implements HttpServer { StubRequestHandler stubRequestHandler, RequestDelayControl requestDelayControl ) { - jettyServer = new Server(); httpConnector = createHttpConnector( requestDelayControl, @@ -138,12 +137,12 @@ private DelayableSslSocketConnector createHttpsConnector( connector.setHost(bindAddress); connector.setPort(httpsSettings.port()); connector.setHeaderBufferSize(8192); - connector.setKeystore(httpsSettings.keyStorePath()); - connector.setKeyPassword(httpsSettings.getKeyStorePassword()); + connector.setKeystore(httpsSettings.keystore()); + connector.setKeyPassword(httpsSettings.keyPassword()); - connector.setTruststore(httpsSettings.getTrustStorePath()); - if (httpsSettings.getTrustStorePassword() != null) { - connector.setTrustPassword(httpsSettings.getTrustStorePassword()); + connector.setTruststore(httpsSettings.truststore()); + if (httpsSettings.trustPassword() != null) { + connector.setTrustPassword(httpsSettings.trustPassword()); } connector.setNeedClientAuth(httpsSettings.needClientAuth()); diff --git a/src/main/java/com/github/tomakehurst/wiremock/standalone/CommandLineOptions.java b/src/main/java/com/github/tomakehurst/wiremock/standalone/CommandLineOptions.java index 532e2b7b8b..9cf5bc7e89 100644 --- a/src/main/java/com/github/tomakehurst/wiremock/standalone/CommandLineOptions.java +++ b/src/main/java/com/github/tomakehurst/wiremock/standalone/CommandLineOptions.java @@ -27,6 +27,7 @@ import com.google.common.io.Resources; import joptsimple.OptionParser; import joptsimple.OptionSet; +import org.apache.commons.lang.StringUtils; import java.io.IOException; import java.io.StringWriter; @@ -158,16 +159,19 @@ public HttpsSettings httpsSettings() { return HttpsSettings.NO_HTTPS; } - if (optionSet.has(HTTPS_KEYSTORE)) { - return new HttpsSettings(httpsPortNumber(), - (String) optionSet.valueOf(HTTPS_KEYSTORE), - (String) optionSet.valueOf(HTTPS_KEYSTORE_PASS), - (String) optionSet.valueOf(HTTPS_TRUSTSTORE), - (String) optionSet.valueOf(HTTPS_TRUSTSTORE_PASS), - Boolean.valueOf( (String) optionSet.valueOf(HTTPS_NEED_CLIENT_AUTH))); + final String keyStorePath = optionSet.has(HTTPS_KEYSTORE) ? (String) optionSet.valueOf(HTTPS_KEYSTORE) : Resources.getResource("keystore").toString(); + final String keyStorePassword = optionSet.has(HTTPS_KEYSTORE_PASS) ? (String) optionSet.valueOf(HTTPS_KEYSTORE_PASS) : "password"; + + if (StringUtils.isEmpty(keyStorePath)) { + throw new IllegalArgumentException("Try to enable HTTPS port but missing a valid Keystore. " + + "Please either specify keystore path with --https-keystore argument, " + + "or put the keystore in resource with name 'keystore'"); } - return new HttpsSettings(httpsPortNumber(), Resources.getResource("keystore").toString(), "password"); + return new HttpsSettings(httpsPortNumber(), keyStorePath, keyStorePassword, + (String) optionSet.valueOf(HTTPS_TRUSTSTORE), + (String) optionSet.valueOf(HTTPS_TRUSTSTORE_PASS), + Boolean.valueOf((String) optionSet.valueOf(HTTPS_NEED_CLIENT_AUTH))); } private int httpsPortNumber() { @@ -238,7 +242,7 @@ public String toString() { if (httpsSettings().enabled()) { builder.put(HTTPS_PORT, nullToString(httpsSettings().port())) - .put(HTTPS_KEYSTORE, nullToString(httpsSettings().keyStorePath())); + .put(HTTPS_KEYSTORE, nullToString(httpsSettings().keystore())); } if (!(proxyVia() == NO_PROXY)) { diff --git a/src/test/java/com/github/tomakehurst/wiremock/HttpsAcceptanceTest.java b/src/test/java/com/github/tomakehurst/wiremock/HttpsAcceptanceTest.java index c1edb63d01..5e7657c573 100644 --- a/src/test/java/com/github/tomakehurst/wiremock/HttpsAcceptanceTest.java +++ b/src/test/java/com/github/tomakehurst/wiremock/HttpsAcceptanceTest.java @@ -16,136 +16,220 @@ package com.github.tomakehurst.wiremock; import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.common.FatalStartupException; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import com.github.tomakehurst.wiremock.http.Fault; -import com.github.tomakehurst.wiremock.http.HttpClientFactory; import com.google.common.io.Resources; -import org.apache.http.HttpResponse; +import com.jayway.restassured.RestAssured; +import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.http.MalformedChunkCodingException; import org.apache.http.NoHttpResponseException; import org.apache.http.ProtocolException; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.util.EntityUtils; +import org.apache.http.conn.ssl.SSLContexts; +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.junit.After; +import org.junit.Before; import org.junit.Test; +import javax.net.ssl.*; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; + import static com.github.tomakehurst.wiremock.client.WireMock.*; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static junit.framework.Assert.assertTrue; -import static org.hamcrest.Matchers.instanceOf; +import static com.jayway.restassured.config.SSLConfig.sslConfig; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; public class HttpsAcceptanceTest { private static final int HTTPS_PORT = 8443; - private WireMockServer wireMockServer; - private HttpClient httpClient; - private void startServerWithKeystore(String keystorePath) { - WireMockConfiguration config = wireMockConfig().httpsPort(HTTPS_PORT); - if (keystorePath != null) { - config.keystorePath(keystorePath); - } + private void startServerWithSSL(int port, + String keystorePath, String keystorePassword, + String truststorePath, String truststorePassword, + boolean needsClientAuth) { + WireMockConfiguration config = wireMockConfig().httpsPort(port) + .keystore(keystorePath) + .keyPassword(keystorePassword) + .truststore(truststorePath) + .trustPassword(truststorePassword) + .needClientAuth(needsClientAuth); wireMockServer = new WireMockServer(config); wireMockServer.start(); WireMock.configure(); + } + + private void startDefaultHttpsServer() { + startServerWithSSL(HTTPS_PORT, null, null, null, null, false); + } + + private void startHttpsServerWithKeystore(final String keystorePath) { + startServerWithSSL(HTTPS_PORT, keystorePath, null, null, null, false); + } + + private void startHttpsServerWithKeystore(final String keystorePath, final String keyPassword) { + startServerWithSSL(HTTPS_PORT, keystorePath, keyPassword, null, null, false); + } - httpClient = HttpClientFactory.createClient(); + private void startHttpsServerWithClientAuth(final String keystorePath, final String truststorePath) { + startServerWithSSL(HTTPS_PORT, keystorePath, "password", truststorePath, "password", true); } - private void startServerWithDefaultKeystore() { - startServerWithKeystore(null); + @Before + public void setup() { + RestAssured.baseURI = "https://localhost"; + RestAssured.port = HTTPS_PORT; + } + + /** + * trust all hosts regardless if the SSL certificate is invalid + */ + private void relaxHttpsValidation() { + RestAssured.useRelaxedHTTPSValidation(); } @After - public void serverShutdown() { + public void teardown() { wireMockServer.stop(); + RestAssured.reset(); } @Test public void shouldReturnStubOnSpecifiedPort() throws Exception { - startServerWithDefaultKeystore(); - stubFor(get(urlEqualTo("/https-test")).willReturn(aResponse().withStatus(200).withBody("HTTPS content"))); + relaxHttpsValidation(); + startDefaultHttpsServer(); - assertThat(contentFor(url("/https-test")), is("HTTPS content")); + expectGetHttpsContent(); } - @Test - public void emptyResponseFault() { - startServerWithDefaultKeystore(); + @Test(expected = NoHttpResponseException.class) + public void emptyResponseFault() throws Throwable { + relaxHttpsValidation(); + startDefaultHttpsServer(); stubFor(get(urlEqualTo("/empty/response")).willReturn( aResponse() .withFault(Fault.EMPTY_RESPONSE))); - - getAndAssertUnderlyingExceptionInstanceClass(url("/empty/response"), NoHttpResponseException.class); + getAndThrowUnderlyingException("/empty/response"); } - @Test - public void malformedResponseChunkFault() { - startServerWithDefaultKeystore(); + @Test(expected = MalformedChunkCodingException.class) + public void malformedResponseChunkFault() throws Throwable { + relaxHttpsValidation(); + startDefaultHttpsServer(); stubFor(get(urlEqualTo("/malformed/response")).willReturn( aResponse() .withFault(Fault.MALFORMED_RESPONSE_CHUNK))); - getAndAssertUnderlyingExceptionInstanceClass(url("/malformed/response"), MalformedChunkCodingException.class); + getAndThrowUnderlyingException("/malformed/response"); } - @Test - public void randomDataOnSocketFault() { - startServerWithDefaultKeystore(); + @Test(expected = ProtocolException.class) + public void randomDataOnSocketFault() throws Throwable { + relaxHttpsValidation(); + startDefaultHttpsServer(); stubFor(get(urlEqualTo("/random/data")).willReturn( aResponse() .withFault(Fault.RANDOM_DATA_THEN_CLOSE))); - getAndAssertUnderlyingExceptionInstanceClass(url("/random/data"), ProtocolException.class); + getAndThrowUnderlyingException("/random/data"); } - @Test(expected = Exception.class) + @Test(expected = FatalStartupException.class) public void throwsExceptionWhenBadAlternativeKeystore() { - String testKeystorePath = Resources.getResource("bad-keystore").toString(); - startServerWithKeystore(testKeystorePath); + String testKeystorePath = Resources.getResource("stores/bad-keystore.jks").getFile(); + startHttpsServerWithKeystore(testKeystorePath); + } + + @Test(expected = FatalStartupException.class) + public void throwsExceptionWhenKeypasswordIsWrong() { + String testKeystorePath = Resources.getResource("stores/test-keystore.jks").getFile(); + startHttpsServerWithKeystore(testKeystorePath, "wrong-pass"); } @Test public void acceptsAlternativeKeystore() throws Exception { - String testKeystorePath = Resources.getResource("test-keystore").toString(); - startServerWithKeystore(testKeystorePath); - stubFor(get(urlEqualTo("/https-test")).willReturn(aResponse().withStatus(200).withBody("HTTPS content"))); + relaxHttpsValidation(); - assertThat(contentFor(url("/https-test")), is("HTTPS content")); + String testKeystorePath = Resources.getResource("stores/test-keystore.jks").getFile(); + startHttpsServerWithKeystore(testKeystorePath); + + expectGetHttpsContent(); } - private String url(String path) { - return String.format("https://localhost:%d%s", HTTPS_PORT, path); + @Test(expected = SSLHandshakeException.class) + public void expectDenyRequestIfNotTrusted() { + String testKeystorePath = Resources.getResource("stores/test-keystore.jks").getFile(); + String testTruststorePath = Resources.getResource("stores/test-truststore.jks").getFile(); + startHttpsServerWithClientAuth(testKeystorePath, testTruststorePath); + + expectGetHttpsContent(); } - private void getAndAssertUnderlyingExceptionInstanceClass(String url, Class expectedClass) { - boolean thrown = false; + @Test + public void expectGetHttpsContentWithClientAuth() throws Exception { + String testKeystorePath = Resources.getResource("stores/test-keystore.jks").getFile(); + String testTruststorePath = Resources.getResource("stores/test-truststore.jks").getFile(); + startHttpsServerWithClientAuth(testKeystorePath, testTruststorePath); + + // Client carry certificate that the server trusts + SSLContext sslcontext = SSLContexts.custom() + .loadTrustMaterial(createKeyStore(testTruststorePath, "password"), new TrustSelfSignedStrategy()) + .loadKeyMaterial(createKeyStore(testKeystorePath, "password"), "password".toCharArray()) + .useTLS() + .build(); + + RestAssured.config = RestAssured.config().sslConfig(sslConfig().sslSocketFactory(new org.apache.http.conn.ssl.SSLSocketFactory(sslcontext))); + + expectGetHttpsContent(); + } + + private KeyStore createKeyStore(final String path, final String password) + throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException { + InputStream inputStream = null; try { - contentFor(url); + inputStream = new FileInputStream(path); + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(inputStream, password.toCharArray()); + + return keyStore; + } finally { + if (inputStream != null) { + inputStream.close(); + } + } + } + + private void expectGetHttpsContent() { + final String path = "/https-test"; + final String content = "HTTPS content"; + + stubFor(get(urlEqualTo(path)) + .willReturn(aResponse().withStatus(200).withBody(content))); + + RestAssured.expect().statusCode(200) + .when().get(path) + .then().body(is(content)); + } + + private void getAndThrowUnderlyingException(String url) throws Throwable { + try { + RestAssured.get(url).body().asString(); } catch (Exception e) { Throwable cause = e.getCause(); if (cause != null) { - assertThat(e.getCause(), instanceOf(expectedClass)); + throw ExceptionUtils.getRootCause(e); } else { - assertThat(e, instanceOf(expectedClass)); + throw e; } - - thrown = true; } - - assertTrue("No exception was thrown", thrown); - } - - private String contentFor(String url) throws Exception { - HttpGet get = new HttpGet(url); - HttpResponse response = httpClient.execute(get); - String content = EntityUtils.toString(response.getEntity()); - return content; } } diff --git a/src/test/java/com/github/tomakehurst/wiremock/common/HttpsSettingsTest.java b/src/test/java/com/github/tomakehurst/wiremock/common/HttpsSettingsTest.java new file mode 100644 index 0000000000..6ea7ae5d13 --- /dev/null +++ b/src/test/java/com/github/tomakehurst/wiremock/common/HttpsSettingsTest.java @@ -0,0 +1,21 @@ +package com.github.tomakehurst.wiremock.common; + +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +public class HttpsSettingsTest { + + @Test + public void expectHttpEnableReturnFalseForNoHttpsSettings() { + assertThat(HttpsSettings.NO_HTTPS.enabled(), equalTo(false)); + } + + @Test + public void expectHttpEnableReturnTrueForValidSettings() { + final HttpsSettings settings = new HttpsSettings(8443, "keystore_path", "keystore_password", + "truststore_path", "truststore_password", true); + assertThat(settings.enabled(), equalTo(true)); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/tomakehurst/wiremock/core/WireMockConfigurationTest.java b/src/test/java/com/github/tomakehurst/wiremock/core/WireMockConfigurationTest.java new file mode 100644 index 0000000000..46aadb8acf --- /dev/null +++ b/src/test/java/com/github/tomakehurst/wiremock/core/WireMockConfigurationTest.java @@ -0,0 +1,41 @@ +package com.github.tomakehurst.wiremock.core; + +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +public class WireMockConfigurationTest { + @Test + public void expectToSetAndGetHttpsSettings() { + final String keystorePath = "keystore-path"; + final String keystorePassword = "keystore-password"; + final String truststorePath = "truststore-path"; + final String truststorePassword = "truststore-password"; + final int httpsPort = 8443; + final boolean needClientAuth = true; + + final WireMockConfiguration configuration = new WireMockConfiguration(); + configuration.httpsPort(httpsPort); + configuration.needClientAuth(needClientAuth); + configuration.keystore(keystorePath); + configuration.keyPassword(keystorePassword); + configuration.truststore(truststorePath); + configuration.trustPassword(truststorePassword); + + + assertThat(configuration.httpsSettings().enabled(), equalTo(true)); + assertThat(configuration.httpsSettings().port(), equalTo(httpsPort)); + assertThat(configuration.httpsSettings().needClientAuth(), equalTo(needClientAuth)); + assertThat(configuration.httpsSettings().keystore(), equalTo(keystorePath)); + assertThat(configuration.httpsSettings().keyPassword(), equalTo(keystorePassword)); + assertThat(configuration.httpsSettings().truststore(), equalTo(truststorePath)); + assertThat(configuration.httpsSettings().trustPassword(), equalTo(truststorePassword)); + } + + @Test + public void expectNoHttpsByDefault() { + final WireMockConfiguration configuration = new WireMockConfiguration(); + assertThat(configuration.httpsSettings().enabled(), equalTo(false)); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/tomakehurst/wiremock/standalone/CommandLineOptionsTest.java b/src/test/java/com/github/tomakehurst/wiremock/standalone/CommandLineOptionsTest.java index c191c0bdc5..2a5cd5d707 100644 --- a/src/test/java/com/github/tomakehurst/wiremock/standalone/CommandLineOptionsTest.java +++ b/src/test/java/com/github/tomakehurst/wiremock/standalone/CommandLineOptionsTest.java @@ -71,7 +71,7 @@ public void enablesHttpsAndSetsPortNumberWhenOptionPresent() { @Test public void setsKeyStorePath() { CommandLineOptions options = new CommandLineOptions("--https-port", "8443", "--https-keystore", "/my/keystore"); - assertThat(options.httpsSettings().keyStorePath(), is("/my/keystore")); + assertThat(options.httpsSettings().keystore(), is("/my/keystore")); } @Test(expected=IllegalArgumentException.class) @@ -160,6 +160,42 @@ public void returnPreserveHostHeaderFalseWhenNotPresent() { public void preventsRecordingWhenRequestJournalDisabled() { new CommandLineOptions("--no-request-journal", "--record-mappings"); } - + @Test + public void returnKeystorePwdWhenPresent() { + final CommandLineOptions options = new CommandLineOptions("--https-port", "8443", + "--https-keystore-pass", "password"); + assertThat(options.httpsSettings().keyPassword(), is("password")); + } + + @Test + public void returnKeystorePathWhenPresent() { + final CommandLineOptions options = new CommandLineOptions("--https-port", "8443", + "--https-keystore", "keystore_path"); + assertThat(options.httpsSettings().keystore(), is("keystore_path")); + } + + @Test + public void returnTruststorePwdWhenPresent() { + final CommandLineOptions options = new CommandLineOptions("--https-port", "8443", + "--https-keystore", "keystore_path", + "--https-truststore-pass", "password"); + assertThat(options.httpsSettings().keyPassword(), is("password")); + } + + @Test + public void returnTruststorePathWhenPresent() { + final CommandLineOptions options = new CommandLineOptions("--https-port", "8443", + "--https-keystore", "keystore_path", + "--https-truststore", "truststore_path"); + assertThat(options.httpsSettings().truststore(), is("truststore_path")); + } + + @Test + public void returnNeedsClientAuthWhenPresent() { + final CommandLineOptions options = new CommandLineOptions("--https-port", "8443", + "--https-keystore", "keystore_path", + "--https-need-client-auth", "true"); + assertThat(options.httpsSettings().needClientAuth(), is(true)); + } } diff --git a/src/test/resources/bad-keystore b/src/test/resources/bad-keystore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/test/resources/stores/bad-keystore.jks b/src/test/resources/stores/bad-keystore.jks new file mode 100644 index 0000000000..efe6edf8c5 --- /dev/null +++ b/src/test/resources/stores/bad-keystore.jks @@ -0,0 +1 @@ +THIS IS AN INVALID KEYSTORE \ No newline at end of file diff --git a/src/test/resources/stores/ca/README.md b/src/test/resources/stores/ca/README.md new file mode 100644 index 0000000000..bb195f765b --- /dev/null +++ b/src/test/resources/stores/ca/README.md @@ -0,0 +1,10 @@ +# Certificate Authority for Acceptance Test + +This folder stores the CA for creating certificates that were used in HTTPS acceptance test. + +All the places where password is asked, the password is "password" + +## References +* [How to act as your own certificate authority (CA)](https://jamielinux.com/articles/2013/08/act-as-your-own-certificate-authority/) +* [How to create and sign SSL certificates when acting as a certificate authority (CA)](https://jamielinux.com/articles/2013/08/create-and-sign-ssl-certificates-certificate-authority/) +* [Common Java Keytool Commands](http://www.lmhproductions.com/37/common-java-keytool-commands/) \ No newline at end of file diff --git a/src/test/resources/stores/ca/certs/ca.cert.pem b/src/test/resources/stores/ca/certs/ca.cert.pem new file mode 100644 index 0000000000..546eea7f86 --- /dev/null +++ b/src/test/resources/stores/ca/certs/ca.cert.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFiTCCA3GgAwIBAgIJAJwAhbCaZMLiMA0GCSqGSIb3DQEBCwUAMFsxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxFDASBgNVBAMMC1dpcmVNb2NrIENBMB4XDTE0MTIwNzAz +MTkxOVoXDTI0MTIwNDAzMTkxOVowWzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNv +bWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIG +A1UEAwwLV2lyZU1vY2sgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCZnPliMl8Kb3JrlSYfw3p5PtNCl3XasjF03339Al3JFS02ukJpff2xy4UVXQWE +JVdmf6vm4Gv+KeszPj18R01E4ayjkcEYE3Ril2wrXfHL15H2Mhb+IzfiDXjFP0HL +BEHEcyvL/+yW6ZL4ZkiJ5daAIz65sNxyHkNWfXaRecqBYrPQT9zq7UvwJnoR0XgY +JE4plp+/nF7rz/9PuKLkRmbFl6OlNKzghlhp6CJ/utqYDfJOnHorwgi1tIBwe8IG +6XPadzRpdIjTPwIdwohFeFmESUBQSproSZfDqeaSnsdoKFa5T/+6+ioYjJVJUzvz +5cfN+2LMD5hBZL5SLKVxtaz4Yw9bn84NGmOA16Zc8FW2tF79aRNmrMUOi6Zn64Qx +ffncWoBXqPoei8kBvHFpTbQG4OmeqZ+CKtV785m513j1kIqx0BYn+8LGMI6bpqGC +8iuMo5t9Q0br0evnIubGXBDf10NnK4iSXz0p+4dfGESSnohZIB0XpRg906FVhIGS +A0QnERjyXCDFHC29osi9ELXgUCSWNVwsxdghyrk30LPZrk2HR20uRZlrlbpnh5sm +3FDIzXKHcn46eQX/+LejmxQ1D9/5kzZ5b9ySywqsQ11rmWI0NmuWEVRRCEyjc/D+ +4LnAeGhwezeWbOPQxgtFJMnDXJnOOfi5u6aNWBAm7WyOxwIDAQABo1AwTjAdBgNV +HQ4EFgQUGOGjZes4ynltVnse0WbXjP+3VxcwHwYDVR0jBBgwFoAUGOGjZes4ynlt +Vnse0WbXjP+3VxcwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAlF14 +4dXOj4VhlK1ZGTyaF3MOy69t/MwAp2ekIM7BRJ/8DlMKy2jirB8/oy8mwhkpDxeg +cR2ZxfrV8Zk7cZzHl6erFDfZ4M3xcjcouWzmdbzVckzSbgZvWB6Z1MnffVOKOlEC +w/w8cHJqsm/uCM5PU/7gO64w/QemNF5mbTboxulMBTDyzF+dqTg1OdV18Hbax4wl +bJK9Habaa/l1nXi8WVroFq7jXjzR4u3srSspRMsMzIhvEgklLJZzjbPEW8P4FQVx +O7sVJKipHvlw34P668WHSsbVoyOIXfpA58eIBO5iU2Ydks6wBVpndn8mZzRVCH/d +WnqBdKqEaJAW5Hd5HZvmWBGioaRVOuADLblxl4ArQfRCUoS2h8acFhXYKD73xgQ3 +0hEZMGyRzB3akr3SRXawe/rQqtGBJKQO3EjwcuA5mIvbN+U5VOypycCkIOK1rzj1 +XFjjFHfQpQ7XfjVTYM0ymRf8Bb22m/wCO4ZQWsYOL4RLng22YwI+qMow4gaim6e3 +ef/EwDVbbi5pkhVzx8+MMblvguonwmHC5eMBYPdya+3lriyCNKTX6lp2wIXTFh4s +ruNi/rzy/3umvYEkLA2q5Wi8E58AZ32aG5DCwA08iys5I8Ykx5ZzW14zPJESrI3z +nF73CZrr0s8wcFRNtoa1e98ZjW/56mEq84fsYWs= +-----END CERTIFICATE----- diff --git a/src/test/resources/stores/ca/certs/localhost.cert.pem b/src/test/resources/stores/ca/certs/localhost.cert.pem new file mode 100644 index 0000000000..50d74a2c58 --- /dev/null +++ b/src/test/resources/stores/ca/certs/localhost.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIErjCCApagAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCQVUx +EzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMg +UHR5IEx0ZDEUMBIGA1UEAwwLV2lyZU1vY2sgQ0EwHhcNMTQxMjA3MDQxNTI0WhcN +MTUxMjA3MDQxNTI0WjBcMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtu +b3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRIwEAYDVQQD +Ewlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCHMrQR +XvmYaWvplFLxRVoUfHYhXneeZGs9GYrW7V1+8x5DY9gegspqCH7UhMn4MnRVgXCP +3v3piKMw9Dh/2xG51z9io6ivWeTSb3yAJhDY+hmYPRQxW0vJXkvu3wJwgk5IepuY +vS37RaRqwUP0AEe/qUotc9qjbobpQWX/arndZFak0l4lED1efJzWXmoeJIuit3KM +snYvkOWzLxx9t6ugqQsDHPICZl/xpNoDVY0H1bNJ0HTCSDwcDej+BC26lJVHm5Zs +ynMNCWtx/tDX6Sgp7WWnWtZDmR3L4cdffQpxCIyJfgRIjhhH/ntHp+ZnC/Ts/mYn +bEms9KGWs/zlZLkpAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8W +HU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQ5y/H6otm2 +pcyRrkHjNu2IYysw0zAfBgNVHSMEGDAWgBQY4aNl6zjKeW1Wex7RZteM/7dXFzAN +BgkqhkiG9w0BAQsFAAOCAgEALz+GtM/UloDgiOkvSxVcEbpWluR/PW4u1OyfklMF +zpy1A0eKgXzs0wKcN4j8LDd2tWV7mAe4+fcYZvz+5W+CSieQFgWxBBVuojFUWoju +b/fHlwtct3+oyJ4exDkMUfLSza+aniMQbg/Bt5WnBu0kO4COgxjrDCGi8ISzLVbz +S2yBEUOq8iKxaSiDpoy5zHgMSTK9rYj4NYrou8GnSnpTTbMQV1juTMqFy+FCMIpy +LzMVreOwBy1vtywctDjuhJaO5g101a4sW7QGVVF82BT/FCsg4AtSrNYWhFXZkBZt +uCjXl/Yf38e02111/t5dgJ1Z5K3OY5KJhctii/nM+QqrRt+RZMnddKth3tTROxQG +i5+s003reGR1a4e363NUYnFNpn1kT7LAZFisceP2Zw3/cm1utDJMK2qU4tw0N+LB +hmaQuzL2zAfX26nxvlDF41CnBez3Wp1Rov3H6zbhUrbg68AFFGjiCVyV2IxTLiBN +BCn8s5OnniveitgthMsqHz8XHiFC+YAMbLnrDbjOVY/QKHWejHyaH0LpwXtlwOjk +F9ha0Q4pgIoUTp9d4IZhV7SIk2ucuV2XeMvGQKpUvbJPqg5ecGiOICLtTM4AyKXB +PktUcqpX4fe8mr6WDK7esqZv1dRiXW1l2j58e8aZK0dYHD8ER5wHsANJOOPrIlQ/ +rIc= +-----END CERTIFICATE----- diff --git a/src/test/resources/stores/ca/index.txt b/src/test/resources/stores/ca/index.txt new file mode 100644 index 0000000000..1efd1f8918 --- /dev/null +++ b/src/test/resources/stores/ca/index.txt @@ -0,0 +1,2 @@ +V 151207032952Z 1000 unknown /C=Unknown/ST=Unknown/O=Unknown/OU=Unknown/CN=WireMock.Test.Keystore +V 151207041524Z 1001 unknown /C=Unknown/ST=Unknown/O=Unknown/OU=Unknown/CN=localhost diff --git a/src/test/resources/stores/ca/index.txt.attr b/src/test/resources/stores/ca/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/src/test/resources/stores/ca/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/src/test/resources/stores/ca/index.txt.attr.old b/src/test/resources/stores/ca/index.txt.attr.old new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/src/test/resources/stores/ca/index.txt.attr.old @@ -0,0 +1 @@ +unique_subject = yes diff --git a/src/test/resources/stores/ca/index.txt.old b/src/test/resources/stores/ca/index.txt.old new file mode 100644 index 0000000000..10d70f92a1 --- /dev/null +++ b/src/test/resources/stores/ca/index.txt.old @@ -0,0 +1 @@ +V 151207032952Z 1000 unknown /C=Unknown/ST=Unknown/O=Unknown/OU=Unknown/CN=WireMock.Test.Keystore diff --git a/src/test/resources/stores/ca/newcerts/1000.pem b/src/test/resources/stores/ca/newcerts/1000.pem new file mode 100644 index 0000000000..6a915a4a6a --- /dev/null +++ b/src/test/resources/stores/ca/newcerts/1000.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEuzCCAqOgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCQVUx +EzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMg +UHR5IEx0ZDEUMBIGA1UEAwwLV2lyZU1vY2sgQ0EwHhcNMTQxMjA3MDMyOTUyWhcN +MTUxMjA3MDMyOTUyWjBpMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtu +b3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMR8wHQYDVQQD +ExZXaXJlTW9jay5UZXN0LktleXN0b3JlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAiVOjGzAmDM8jiRdztwgrW39VEuXS2X1c59k9JXpftAmZBefmbwoh +7gTBzP0TWHrINXG1aTjkkvuRtptWReHViiQA4FQgv0bLLvEdB5H5sXuGajBoYMJW +je4+I/8z5rRD0PGCOOrqI2QtVil7LoeM0qDRXMYCyvh6Ac+V4pbj4ZNFwkscvRFV +K50WS0RDE+2bs0P9UAgr0x4lMaybn9RqyTkF/lfLd9CEQcpX+G8CcGzPntx/j8XT +vvCTO3LcGj9RClt2fWM4313Bq6O8AfkN2vcTdeUTGV6Vs2ApxFsyFKsi4CSSBvpJ +yjzwhlV6BDDuYwmGCvVs0XPAXVRWXMFDyQIDAQABo3sweTAJBgNVHRMEAjAAMCwG +CWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV +HQ4EFgQUR9Pmwqd07rYvKD5dcvVCzKwZ0r0wHwYDVR0jBBgwFoAUGOGjZes4ynlt +Vnse0WbXjP+3VxcwDQYJKoZIhvcNAQELBQADggIBAFGG/lI0pxje2Qfbg/i6DAPV +FzeGpGlyZO5IINZXE5lUaGEMG5NAE+x/MZKYkJFEFIfdWbvo14v94ZiXAnp+/K++ +GZy/g52KNJbsq5VdJYzbrIXfnEWrWcD86bBxXfM2R/AGvclVofaK31VX2caB+pu3 +PAqzyJdhyEtTCqWQ3gIvLAx8o8BSaeox+QsoTcoDU5V6+Knk2ek3RE6eemwVc46k +flUcD6yxIWJLlSjLlBe/i3jyoO4PmmtJoFmqKm1eLJ2d+g4rEVeouokkhfKun/8r +V20UCJp8P7D2Dmowq99QYpRUBDrwQkZ3oNbIkxMXMfMXRGAMoN/x4p29Gnyxg+i8 +/F4pAZj6WKi9PgMfb3tkhB2HhYUDELGTUmmGOhtiThgrhQDZfZfKTmkJdf62UNHu +DdnSQ5BtvNTvnKvcr3kX8TTpZKYVhkU1SxaRNlzd9/jh5+Hw0eBAInadfgB+DHWD +BLB8jQjcao3tljnNc+Yi4n8J8yWZHOv6RICOHIQ9eeKum0RHIDsgFQo6evcz7DSI +Q1cF6lpXlsAO/JSMCYtV8flFyuwtgjByRPvyJ2Gb+ybdqIlj8Ie65t/Rn801pClN +clAIewM0zViJy8LuJg8Sw0mJOqZb+5WKEyray7MTmUQrDb3TW9OhhyZvDbaSF1Lk +9LBvX7/fZTRFF2YcuYeN +-----END CERTIFICATE----- diff --git a/src/test/resources/stores/ca/newcerts/1001.pem b/src/test/resources/stores/ca/newcerts/1001.pem new file mode 100644 index 0000000000..50d74a2c58 --- /dev/null +++ b/src/test/resources/stores/ca/newcerts/1001.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIErjCCApagAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCQVUx +EzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMg +UHR5IEx0ZDEUMBIGA1UEAwwLV2lyZU1vY2sgQ0EwHhcNMTQxMjA3MDQxNTI0WhcN +MTUxMjA3MDQxNTI0WjBcMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtu +b3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRIwEAYDVQQD +Ewlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCHMrQR +XvmYaWvplFLxRVoUfHYhXneeZGs9GYrW7V1+8x5DY9gegspqCH7UhMn4MnRVgXCP +3v3piKMw9Dh/2xG51z9io6ivWeTSb3yAJhDY+hmYPRQxW0vJXkvu3wJwgk5IepuY +vS37RaRqwUP0AEe/qUotc9qjbobpQWX/arndZFak0l4lED1efJzWXmoeJIuit3KM +snYvkOWzLxx9t6ugqQsDHPICZl/xpNoDVY0H1bNJ0HTCSDwcDej+BC26lJVHm5Zs +ynMNCWtx/tDX6Sgp7WWnWtZDmR3L4cdffQpxCIyJfgRIjhhH/ntHp+ZnC/Ts/mYn +bEms9KGWs/zlZLkpAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8W +HU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQ5y/H6otm2 +pcyRrkHjNu2IYysw0zAfBgNVHSMEGDAWgBQY4aNl6zjKeW1Wex7RZteM/7dXFzAN +BgkqhkiG9w0BAQsFAAOCAgEALz+GtM/UloDgiOkvSxVcEbpWluR/PW4u1OyfklMF +zpy1A0eKgXzs0wKcN4j8LDd2tWV7mAe4+fcYZvz+5W+CSieQFgWxBBVuojFUWoju +b/fHlwtct3+oyJ4exDkMUfLSza+aniMQbg/Bt5WnBu0kO4COgxjrDCGi8ISzLVbz +S2yBEUOq8iKxaSiDpoy5zHgMSTK9rYj4NYrou8GnSnpTTbMQV1juTMqFy+FCMIpy +LzMVreOwBy1vtywctDjuhJaO5g101a4sW7QGVVF82BT/FCsg4AtSrNYWhFXZkBZt +uCjXl/Yf38e02111/t5dgJ1Z5K3OY5KJhctii/nM+QqrRt+RZMnddKth3tTROxQG +i5+s003reGR1a4e363NUYnFNpn1kT7LAZFisceP2Zw3/cm1utDJMK2qU4tw0N+LB +hmaQuzL2zAfX26nxvlDF41CnBez3Wp1Rov3H6zbhUrbg68AFFGjiCVyV2IxTLiBN +BCn8s5OnniveitgthMsqHz8XHiFC+YAMbLnrDbjOVY/QKHWejHyaH0LpwXtlwOjk +F9ha0Q4pgIoUTp9d4IZhV7SIk2ucuV2XeMvGQKpUvbJPqg5ecGiOICLtTM4AyKXB +PktUcqpX4fe8mr6WDK7esqZv1dRiXW1l2j58e8aZK0dYHD8ER5wHsANJOOPrIlQ/ +rIc= +-----END CERTIFICATE----- diff --git a/src/test/resources/stores/ca/openssl.cnf b/src/test/resources/stores/ca/openssl.cnf new file mode 100644 index 0000000000..10547dc7fb --- /dev/null +++ b/src/test/resources/stores/ca/openssl.cnf @@ -0,0 +1,350 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca', 'req' and 'ts'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +# Policies used by the TSA examples. +tsa_policy1 = 1.2.3.4.1 +tsa_policy2 = 1.2.3.4.5.6 +tsa_policy3 = 1.2.3.4.5.7 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./ # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several ctificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem# The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extentions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = default # use public key default MD +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = optional +stateOrProvinceName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extentions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = AU +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Some-State + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Internet Widgits Pty Ltd + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +#organizationalUnitName_default = + +commonName = Common Name (e.g. server FQDN or YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This is required for TSA certificates. +# extendedKeyUsage = critical,timeStamping + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer + +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo + +#################################################################### +[ tsa ] + +default_tsa = tsa_config1 # the default TSA section + +[ tsa_config1 ] + +# These are used by the TSA reply generation only. +dir = ./demoCA # TSA root directory +serial = $dir/tsaserial # The current serial number (mandatory) +crypto_device = builtin # OpenSSL engine to use for signing +signer_cert = $dir/tsacert.pem # The TSA signing certificate + # (optional) +certs = $dir/cacert.pem # Certificate chain to include in reply + # (optional) +signer_key = $dir/private/tsakey.pem # The TSA private key (optional) + +default_policy = tsa_policy1 # Policy if request did not specify it + # (optional) +other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional) +digests = md5, sha1 # Acceptable message digests (mandatory) +accuracy = secs:1, millisecs:500, microsecs:100 # (optional) +clock_precision_digits = 0 # number of digits after dot. (optional) +ordering = yes # Is ordering defined for timestamps? + # (optional, default: no) +tsa_name = yes # Must the TSA name be included in the reply? + # (optional, default: no) +ess_cert_id_chain = no # Must the ESS cert id chain be included? + # (optional, default: no) diff --git a/src/test/resources/stores/ca/private/ca.key.pem b/src/test/resources/stores/ca/private/ca.key.pem new file mode 100644 index 0000000000..feea58b84b --- /dev/null +++ b/src/test/resources/stores/ca/private/ca.key.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,FEB3D195FD4289C3DF8240311909E7BF + +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 +-----END RSA PRIVATE KEY----- diff --git a/src/test/resources/stores/ca/serial b/src/test/resources/stores/ca/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/src/test/resources/stores/ca/serial @@ -0,0 +1 @@ +1002 diff --git a/src/test/resources/stores/ca/serial.old b/src/test/resources/stores/ca/serial.old new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/src/test/resources/stores/ca/serial.old @@ -0,0 +1 @@ +1001 diff --git a/src/test/resources/stores/test-keystore.jks b/src/test/resources/stores/test-keystore.jks new file mode 100644 index 0000000000..8f829a14ae Binary files /dev/null and b/src/test/resources/stores/test-keystore.jks differ diff --git a/src/test/resources/stores/test-truststore.jks b/src/test/resources/stores/test-truststore.jks new file mode 100644 index 0000000000..5451ed1867 Binary files /dev/null and b/src/test/resources/stores/test-truststore.jks differ diff --git a/src/test/resources/test-keystore b/src/test/resources/test-keystore deleted file mode 100644 index 398082654c..0000000000 Binary files a/src/test/resources/test-keystore and /dev/null differ