diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index e9b0bba440f..1f08b411959 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -61,9 +61,13 @@ content into your application; rather pick only the properties that you need. server.ssl.key-password= server.ssl.key-store= server.ssl.key-store-password= + server.ssl.key-store-provider= + server.ssl.key-store-type= server.ssl.protocol=TLS server.ssl.trust-store= server.ssl.trust-store-password= + server.ssl.trust-store-provider= + server.ssl.trust-store-type= server.tomcat.access-log-pattern= # log pattern of the access log server.tomcat.access-log-enabled=false # is access logging enabled server.tomcat.protocol-header=x-forwarded-proto # ssl forward headers diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/Ssl.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/Ssl.java index b8726771434..1bed8222221 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/Ssl.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/Ssl.java @@ -36,10 +36,18 @@ public class Ssl { private String keyStorePassword; + private String keyStoreType; + + private String keyStoreProvider; + private String trustStore; private String trustStorePassword; + private String trustStoreType; + + private String trustStoreProvider; + private String protocol = "TLS"; public ClientAuth getClientAuth() { @@ -90,6 +98,22 @@ public class Ssl { this.keyStorePassword = keyStorePassword; } + public String getKeyStoreType() { + return this.keyStoreType; + } + + public void setKeyStoreType(String keyStoreType) { + this.keyStoreType = keyStoreType; + } + + public String getKeyStoreProvider() { + return this.keyStoreProvider; + } + + public void setKeyStoreProvider(String keyStoreProvider) { + this.keyStoreProvider = keyStoreProvider; + } + public String getTrustStore() { return this.trustStore; } @@ -106,6 +130,22 @@ public class Ssl { this.trustStorePassword = trustStorePassword; } + public String getTrustStoreType() { + return this.trustStoreType; + } + + public void setTrustStoreType(String trustStoreType) { + this.trustStoreType = trustStoreType; + } + + public String getTrustStoreProvider() { + return this.trustStoreProvider; + } + + public void setTrustStoreProvider(String trustStoreProvider) { + this.trustStoreProvider = trustStoreProvider; + } + public String getProtocol() { return this.protocol; } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java index 5268dc1ee5d..8e228cedf68 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java @@ -175,6 +175,12 @@ public class JettyEmbeddedServletContainerFactory extends throw new EmbeddedServletContainerException("Could not find key store '" + ssl.getKeyStore() + "'", ex); } + if (ssl.getKeyStoreType() != null) { + factory.setKeyStoreType(ssl.getKeyStoreType()); + } + if (ssl.getKeyStoreProvider() != null) { + factory.setKeyStoreProvider(ssl.getKeyStoreProvider()); + } } private void configureSslTrustStore(SslContextFactory factory, Ssl ssl) { @@ -191,6 +197,12 @@ public class JettyEmbeddedServletContainerFactory extends "Could not find trust store '" + ssl.getTrustStore() + "'", ex); } } + if (ssl.getTrustStoreType() != null) { + factory.setTrustStoreType(ssl.getTrustStoreType()); + } + if (ssl.getTrustStoreProvider() != null) { + factory.setTrustStoreProvider(ssl.getTrustStoreProvider()); + } } /** diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java index b1385094679..51fa948a82e 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java @@ -290,6 +290,12 @@ public class TomcatEmbeddedServletContainerFactory extends throw new EmbeddedServletContainerException("Could not find key store " + ssl.getKeyStore(), ex); } + if (ssl.getKeyStoreType() != null) { + protocol.setKeystoreType(ssl.getKeyStoreType()); + } + if (ssl.getKeyStoreProvider() != null) { + protocol.setKeystoreProvider(ssl.getKeyStoreProvider()); + } } private void configureSslTrustStore(AbstractHttp11JsseProtocol protocol, Ssl ssl) { @@ -304,6 +310,12 @@ public class TomcatEmbeddedServletContainerFactory extends } } protocol.setTruststorePass(ssl.getTrustStorePassword()); + if (ssl.getTrustStoreType() != null) { + protocol.setTruststoreType(ssl.getTrustStoreType()); + } + if (ssl.getTrustStoreProvider() != null) { + protocol.setTruststoreProvider(ssl.getTrustStoreProvider()); + } } /** diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java index 74bbd7aab93..2850624d4dd 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java @@ -341,6 +341,46 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests { equalTo("test")); } + @Test + public void pkcs12KeyStoreAndTrustStore() throws Exception { + FileCopyUtils.copy("test", + new FileWriter(this.temporaryFolder.newFile("test.txt"))); + + AbstractEmbeddedServletContainerFactory factory = getFactory(); + factory.setDocumentRoot(this.temporaryFolder.getRoot()); + + Ssl ssl = new Ssl(); + ssl.setKeyStore("src/test/resources/test.p12"); + ssl.setKeyStorePassword("secret"); + ssl.setKeyStoreType("pkcs12"); + ssl.setTrustStore("src/test/resources/test.p12"); + ssl.setTrustStorePassword("secret"); + ssl.setTrustStoreType("pkcs12"); + ssl.setClientAuth(ClientAuth.NEED); + factory.setSsl(ssl); + + this.container = factory.getEmbeddedServletContainer(); + this.container.start(); + + KeyStore keyStore = KeyStore.getInstance("pkcs12"); + keyStore.load(new FileInputStream(new File("src/test/resources/test.p12")), + "secret".toCharArray()); + + SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( + new SSLContextBuilder() + .loadTrustMaterial(null, new TrustSelfSignedStrategy()) + .loadKeyMaterial(keyStore, "secret".toCharArray()).build()); + + HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory) + .build(); + + HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory( + httpClient); + + assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory), + equalTo("test")); + } + @Test public void sslNeedsClientAuthenticationSucceedsWithClientCertificate() throws Exception { diff --git a/spring-boot/src/test/resources/test.p12 b/spring-boot/src/test/resources/test.p12 new file mode 100644 index 00000000000..5726ff02f4b Binary files /dev/null and b/spring-boot/src/test/resources/test.p12 differ