diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/SslServerCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/SslServerCustomizer.java index 2d0e14ce952..cb2fbfb3641 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/SslServerCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/SslServerCustomizer.java @@ -16,6 +16,7 @@ package org.springframework.boot.web.embedded.netty; +import java.io.FileNotFoundException; import java.net.URL; import java.security.KeyStore; import java.util.Arrays; @@ -31,6 +32,7 @@ import reactor.netty.tcp.SslProvider; import org.springframework.boot.web.server.Http2; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.SslStoreProvider; +import org.springframework.boot.web.server.WebServerException; import org.springframework.util.ResourceUtils; /** @@ -38,6 +40,7 @@ import org.springframework.util.ResourceUtils; * instance. * * @author Brian Clozel + * @author Raheela Aslam */ public class SslServerCustomizer implements NettyServerCustomizer { @@ -135,21 +138,40 @@ public class SslServerCustomizer implements NettyServerCustomizer { if (sslStoreProvider != null) { return sslStoreProvider.getTrustStore(); } - return loadKeyStore(ssl.getTrustStoreType(), ssl.getTrustStoreProvider(), + return loadTrustStore(ssl.getTrustStoreType(), ssl.getTrustStoreProvider(), ssl.getTrustStore(), ssl.getTrustStorePassword()); } private KeyStore loadKeyStore(String type, String provider, String resource, String password) throws Exception { - type = (type != null) ? type : "JKS"; + + return loadStore(type, provider, resource, password); + } + + private KeyStore loadTrustStore(String type, String provider, String resource, + String password) throws Exception { if (resource == null) { return null; } + else { + return loadStore(type, provider, resource, password); + } + } + + private KeyStore loadStore(String type, String provider, String resource, + String password) throws Exception { + type = (type != null) ? type : "JKS"; KeyStore store = (provider != null) ? KeyStore.getInstance(type, provider) : KeyStore.getInstance(type); - URL url = ResourceUtils.getURL(resource); - store.load(url.openStream(), (password != null) ? password.toCharArray() : null); - return store; + try { + URL url = ResourceUtils.getURL(resource); + store.load(url.openStream(), + (password != null) ? password.toCharArray() : null); + return store; + } + catch (FileNotFoundException ex) { + throw new WebServerException("Could not load store: " + ex.getMessage(), ex); + } } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/SslBuilderCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/SslBuilderCustomizer.java index bcc427de3ff..8385fd7abd3 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/SslBuilderCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/SslBuilderCustomizer.java @@ -16,6 +16,7 @@ package org.springframework.boot.web.embedded.undertow; +import java.io.FileNotFoundException; import java.net.InetAddress; import java.net.Socket; import java.net.URL; @@ -41,12 +42,14 @@ import org.xnio.SslClientAuthMode; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.SslStoreProvider; +import org.springframework.boot.web.server.WebServerException; import org.springframework.util.ResourceUtils; /** * {@link UndertowBuilderCustomizer} that configures SSL on the given builder instance. * * @author Brian Clozel + * @author Raheela Aslam */ class SslBuilderCustomizer implements UndertowBuilderCustomizer { @@ -166,21 +169,39 @@ class SslBuilderCustomizer implements UndertowBuilderCustomizer { if (sslStoreProvider != null) { return sslStoreProvider.getTrustStore(); } - return loadKeyStore(ssl.getTrustStoreType(), ssl.getTrustStoreProvider(), + return loadTrustStore(ssl.getTrustStoreType(), ssl.getTrustStoreProvider(), ssl.getTrustStore(), ssl.getTrustStorePassword()); } private KeyStore loadKeyStore(String type, String provider, String resource, String password) throws Exception { - type = (type != null) ? type : "JKS"; + return loadStore(type, provider, resource, password); + } + + private KeyStore loadTrustStore(String type, String provider, String resource, + String password) throws Exception { if (resource == null) { return null; } + else { + return loadStore(type, provider, resource, password); + } + } + + private KeyStore loadStore(String type, String provider, String resource, + String password) throws Exception { + type = (type != null) ? type : "JKS"; KeyStore store = (provider != null) ? KeyStore.getInstance(type, provider) : KeyStore.getInstance(type); - URL url = ResourceUtils.getURL(resource); - store.load(url.openStream(), (password != null) ? password.toCharArray() : null); - return store; + try { + URL url = ResourceUtils.getURL(resource); + store.load(url.openStream(), + (password != null) ? password.toCharArray() : null); + return store; + } + catch (FileNotFoundException ex) { + throw new WebServerException("Could not load store: " + ex.getMessage(), ex); + } } /** diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/SslServerCustomizerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/SslServerCustomizerTests.java index 17ed85276ac..4c61a6b39de 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/SslServerCustomizerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/SslServerCustomizerTests.java @@ -29,6 +29,7 @@ import static org.junit.Assert.fail; * Tests for {@link SslServerCustomizer}. * * @author Andy Wilkinson + * @author Raheela Aslam */ public class SslServerCustomizerTests { @@ -68,4 +69,20 @@ public class SslServerCustomizerTests { } } + @Test + public void keyStoreProviderIsUsedWhenKeyStoreNotContaining() throws Exception { + Ssl ssl = new Ssl(); + ssl.setKeyPassword("password"); + SslServerCustomizer customizer = new SslServerCustomizer(ssl, null, null); + try { + customizer.getKeyManagerFactory(ssl, null); + fail(); + } + catch (IllegalStateException ex) { + Throwable cause = ex.getCause(); + assertThat(cause).isInstanceOf(IllegalArgumentException.class); + assertThat(cause).hasMessageContaining("Resource location must not be null"); + } + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/SslBuilderCustomizerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/SslBuilderCustomizerTests.java index bbf7c87e673..7a4db163303 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/SslBuilderCustomizerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/SslBuilderCustomizerTests.java @@ -33,6 +33,7 @@ import static org.junit.Assert.fail; * Tests for {@link SslBuilderCustomizer} * * @author Brian Clozel + * @author Raheela Aslam */ public class SslBuilderCustomizerTests { @@ -88,4 +89,24 @@ public class SslBuilderCustomizerTests { } } + @Test + public void getKeyManagersWhenKeyStoreIsNotProvided() throws Exception { + Ssl ssl = new Ssl(); + ssl.setKeyPassword("password"); + SslBuilderCustomizer customizer = new SslBuilderCustomizer(8080, + InetAddress.getLocalHost(), ssl, null); + try { + KeyManager[] keyManagers = ReflectionTestUtils.invokeMethod(customizer, + "getKeyManagers", ssl, null); + Class name = Class.forName("org.springframework.boot.web.embedded.undertow" + + ".SslBuilderCustomizer$ConfigurableAliasKeyManager"); + assertThat(keyManagers[0]).isNotInstanceOf(name); + } + catch (IllegalStateException ex) { + Throwable cause = ex.getCause(); + assertThat(cause).isInstanceOf(IllegalArgumentException.class); + assertThat(cause).hasMessageContaining("Resource location must not be null"); + } + } + }