Skip to content

Commit

Permalink
Polish
Browse files Browse the repository at this point in the history
  • Loading branch information
philwebb committed Dec 21, 2022
1 parent 1939d23 commit bc6fc33
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 219 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

/**
* {@link JettyServerCustomizer} that configures SSL on the given Jetty server instance.
Expand Down Expand Up @@ -224,10 +225,8 @@ private void configureSslKeyStore(SslContextFactory.Server factory, Ssl ssl) {
String keystoreType = (ssl.getKeyStoreType() != null) ? ssl.getKeyStoreType() : "JKS";
String keystoreLocation = ssl.getKeyStore();
if (keystoreType.equalsIgnoreCase("PKCS11")) {
if (keystoreLocation != null && !keystoreLocation.isEmpty()) {
throw new IllegalArgumentException("Input keystore location is not valid for keystore type 'PKCS11': '"
+ keystoreLocation + "'. Must be undefined / null.");
}
Assert.state(!StringUtils.hasText(keystoreLocation),
() -> "Keystore location '" + keystoreLocation + "' must be empty or null for PKCS11 key stores");
}
else {
try {
Expand All @@ -240,7 +239,7 @@ private void configureSslKeyStore(SslContextFactory.Server factory, Ssl ssl) {
}
factory.setKeyStoreType(keystoreType);
if (ssl.getKeyStoreProvider() != null) {
factory.setKeyStoreProvider(ssl.getKeyStoreProvider());
factory.setKeyStoreProvider(this.ssl.getKeyStoreProvider());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@
import org.springframework.boot.web.server.SslConfigurationValidator;
import org.springframework.boot.web.server.SslStoreProvider;
import org.springframework.boot.web.server.WebServerException;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

/**
* {@link NettyServerCustomizer} that configures SSL for the given Reactor Netty server
Expand Down Expand Up @@ -169,25 +171,26 @@ private KeyStore loadTrustStore(String type, String provider, String resource, S
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);
if (type.equalsIgnoreCase("PKCS11")) {
if (resource != null && !resource.isEmpty()) {
throw new IllegalArgumentException("Input keystore location is not valid for keystore type 'PKCS11': '"
+ resource + "'. Must be undefined / null.");
}
store.load(null, (password != null) ? password.toCharArray() : null);
private KeyStore loadStore(String keystoreType, String provider, String keystoreLocation, String password)
throws Exception {
keystoreType = (keystoreType != null) ? keystoreType : "JKS";
char[] passwordChars = (password != null) ? password.toCharArray() : null;
KeyStore store = (provider != null) ? KeyStore.getInstance(keystoreType, provider)
: KeyStore.getInstance(keystoreType);
if (keystoreType.equalsIgnoreCase("PKCS11")) {
Assert.state(!StringUtils.hasText(keystoreLocation),
() -> "Keystore location '" + keystoreLocation + "' must be empty or null for PKCS11 key stores");
store.load(null, passwordChars);
}
else {
try {
URL url = ResourceUtils.getURL(resource);
URL url = ResourceUtils.getURL(keystoreLocation);
try (InputStream stream = url.openStream()) {
store.load(stream, (password != null) ? password.toCharArray() : null);
store.load(stream, passwordChars);
}
}
catch (Exception ex) {
throw new WebServerException("Could not load key store '" + resource + "'", ex);
throw new WebServerException("Could not load key store '" + keystoreLocation + "'", ex);
}
}
return store;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,8 @@ private void configureSslKeyStore(SSLHostConfigCertificate certificate, Ssl ssl)
String keystoreType = (ssl.getKeyStoreType() != null) ? ssl.getKeyStoreType() : "JKS";
String keystoreLocation = ssl.getKeyStore();
if (keystoreType.equalsIgnoreCase("PKCS11")) {
if (keystoreLocation != null && !keystoreLocation.isEmpty()) {
throw new IllegalArgumentException("Input keystore location is not valid for keystore type 'PKCS11': '"
+ keystoreLocation + "'. Must be undefined / null.");
}
Assert.state(!StringUtils.hasText(keystoreLocation),
() -> "Keystore location '" + keystoreLocation + "' must be empty or null for PKCS11 key stores");
}
else {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
package org.springframework.boot.web.embedded.jetty;

import java.net.InetSocketAddress;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -29,20 +27,19 @@
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.OS;

import org.springframework.boot.testsupport.junit.DisabledOnOs;
import org.springframework.boot.web.embedded.netty.MockPkcs11SecurityProvider;
import org.springframework.boot.web.embedded.test.MockPkcs11Security;
import org.springframework.boot.web.embedded.test.MockPkcs11SecurityProvider;
import org.springframework.boot.web.server.Http2;
import org.springframework.boot.web.server.Ssl;
import org.springframework.boot.web.server.WebServerException;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.assertThatNoException;

/**
Expand All @@ -51,25 +48,9 @@
* @author Andy Wilkinson
* @author Cyril Dangerville
*/
@MockPkcs11Security
class SslServerCustomizerTests {

private static final Provider PKCS11_PROVIDER = new MockPkcs11SecurityProvider();

@BeforeAll
static void beforeAllTests() {
/*
* Add the mock Java security provider for PKCS#11-related unit tests.
*
*/
Security.addProvider(PKCS11_PROVIDER);
}

@AfterAll
static void afterAllTests() {
// Remove the provider previously added in setup()
Security.removeProvider(PKCS11_PROVIDER.getName());
}

@Test
@SuppressWarnings("rawtypes")
void whenHttp2IsNotEnabledServerConnectorHasSslAndHttpConnectionFactories() {
Expand Down Expand Up @@ -107,11 +88,8 @@ void alpnConnectionFactoryHasNullDefaultProtocolToAllowNegotiationToHttp11() {
assertThat(((ALPNServerConnectionFactory) factories.get(1)).getDefaultProtocol()).isNull();
}

/**
* Null/undefined keystore is invalid unless keystore type is PKCS11.
*/
@Test
void configureSslWhenSslIsEnabledWithNoKeyStoreAndNotPkcs11ThrowsWebServerException() {
void configureSslWhenSslIsEnabledWithNoKeyStoreAndNotPkcs11ThrowsException() {
Ssl ssl = new Ssl();
SslServerCustomizer customizer = new SslServerCustomizer(null, ssl, null, null);
assertThatExceptionOfType(Exception.class)
Expand All @@ -122,30 +100,26 @@ void configureSslWhenSslIsEnabledWithNoKeyStoreAndNotPkcs11ThrowsWebServerExcept
});
}

/**
* No keystore path should be defined if keystore type is PKCS#11.
*/
@Test
void configureSslWhenSslIsEnabledWithPkcs11AndKeyStoreThrowsIllegalArgumentException() {
void configureSslWhenSslIsEnabledWithPkcs11AndKeyStoreThrowsException() {
Ssl ssl = new Ssl();
ssl.setKeyStoreType("PKCS11");
ssl.setKeyStoreProvider(PKCS11_PROVIDER.getName());
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
ssl.setKeyStore("src/test/resources/test.jks");
ssl.setKeyPassword("password");
SslServerCustomizer customizer = new SslServerCustomizer(null, ssl, null, null);
assertThatIllegalArgumentException()
assertThatIllegalStateException()
.isThrownBy(() -> customizer.configureSsl(new SslContextFactory.Server(), ssl, null))
.withMessageContaining("Input keystore location is not valid for keystore type 'PKCS11'");
.withMessageContaining("must be empty or null for PKCS11 key stores");
}

@Test
void customizeWhenSslIsEnabledWithPkcs11AndKeyStoreProvider() {
Ssl ssl = new Ssl();
ssl.setKeyStoreType("PKCS11");
ssl.setKeyStoreProvider(PKCS11_PROVIDER.getName());
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
ssl.setKeyStorePassword("1234");
SslServerCustomizer customizer = new SslServerCustomizer(null, ssl, null, null);
// Loading the KeyManagerFactory should be successful
assertThatNoException().isThrownBy(() -> customizer.configureSsl(new SslContextFactory.Server(), ssl, null));
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@
package org.springframework.boot.web.embedded.netty;

import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Security;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import org.springframework.boot.web.embedded.test.MockPkcs11Security;
import org.springframework.boot.web.embedded.test.MockPkcs11SecurityProvider;
import org.springframework.boot.web.server.Ssl;
import org.springframework.boot.web.server.WebServerException;

Expand All @@ -38,29 +36,9 @@
* @author Cyril Dangerville
*/
@SuppressWarnings("deprecation")
@MockPkcs11Security
class SslServerCustomizerTests {

private static final Provider PKCS11_PROVIDER = new MockPkcs11SecurityProvider();

@BeforeAll
static void setup() {
/*
* Add the mock Java security provider for PKCS#11-related unit tests.
*
* For an integration test with an actual PKCS#11 library - SoftHSM - properly
* installed and configured on the system (inside a container), used via Java
* built-in SunPKCS11 provider, see the 'spring-boot-smoke-test-webflux-ssl'
* project in 'spring-boot-tests/spring-boot-smoke-tests' folder.
*/
Security.addProvider(PKCS11_PROVIDER);
}

@AfterAll
static void shutdown() {
// Remove the provider previously added in setup()
Security.removeProvider(PKCS11_PROVIDER.getName());
}

@Test
void keyStoreProviderIsUsedWhenCreatingKeyStore() {
Ssl ssl = new Ssl();
Expand All @@ -85,41 +63,34 @@ void trustStoreProviderIsUsedWhenCreatingTrustStore() {
.withMessageContaining("com.example.TrustStoreProvider");
}

/**
* Null/undefined keystore is not valid unless keystore type is PKCS11.
*/
@Test
void getKeyManagerFactoryWhenSslIsEnabledWithNoKeyStoreAndNotPkcs11ThrowsWebServerException() {
void getKeyManagerFactoryWhenSslIsEnabledWithNoKeyStoreAndNotPkcs11ThrowsException() {
Ssl ssl = new Ssl();
SslServerCustomizer customizer = new SslServerCustomizer(ssl, null, null);
assertThatIllegalStateException().isThrownBy(() -> customizer.getKeyManagerFactory(ssl, null))
.withCauseInstanceOf(WebServerException.class).withMessageContaining("Could not load key store 'null'");
}

/**
* No keystore path should be defined if keystore type is PKCS#11.
*/
@Test
void getKeyManagerFactoryWhenSslIsEnabledWithPkcs11AndKeyStoreThrowsIllegalArgumentException() {
void getKeyManagerFactoryWhenSslIsEnabledWithPkcs11AndKeyStoreThrowsException() {
Ssl ssl = new Ssl();
ssl.setKeyStoreType("PKCS11");
ssl.setKeyStoreProvider(PKCS11_PROVIDER.getName());
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
ssl.setKeyStore("src/test/resources/test.jks");
ssl.setKeyPassword("password");
SslServerCustomizer customizer = new SslServerCustomizer(ssl, null, null);
assertThatIllegalStateException().isThrownBy(() -> customizer.getKeyManagerFactory(ssl, null))
.withCauseInstanceOf(IllegalArgumentException.class)
.withMessageContaining("Input keystore location is not valid for keystore type 'PKCS11'");
.withCauseInstanceOf(IllegalStateException.class)
.withMessageContaining("must be empty or null for PKCS11 key stores");
}

@Test
void getKeyManagerFactoryWhenSslIsEnabledWithPkcs11AndKeyStoreProvider() {
Ssl ssl = new Ssl();
ssl.setKeyStoreType("PKCS11");
ssl.setKeyStoreProvider(PKCS11_PROVIDER.getName());
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
ssl.setKeyStorePassword("1234");
SslServerCustomizer customizer = new SslServerCustomizer(ssl, null, null);
// Loading the KeyManagerFactory should be successful
assertThatNoException().isThrownBy(() -> customizer.getKeyManagerFactory(ssl, null));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.springframework.boot.web.embedded.netty;
package org.springframework.boot.web.embedded.test;

import java.io.InputStream;
import java.io.OutputStream;
Expand All @@ -31,7 +31,7 @@
import java.util.Map;

/**
* Mock Security Provider for testing purposes only (e.g. SslServerCustomizerTests class)
* Mock Security Provider for testing purposes.
*
* @author Cyril Dangerville
*/
Expand All @@ -45,7 +45,7 @@ public class MockKeyStoreSpi extends KeyStoreSpi {
KEYGEN.initialize(2048);
}
catch (NoSuchAlgorithmException ex) {
throw new RuntimeException(ex);
throw new IllegalStateException(ex);
}
}

Expand Down Expand Up @@ -99,8 +99,6 @@ public Enumeration<String> engineAliases() {

@Override
public boolean engineContainsAlias(String alias) {
// contains any required alias, for testing purposes
// Add alias to aliases list on the fly
this.aliases.put(alias, KEYGEN.generateKeyPair());
return true;
}
Expand All @@ -112,7 +110,6 @@ public int engineSize() {

@Override
public boolean engineIsKeyEntry(String alias) {
// Handle all keystore entries as key entries
return this.aliases.containsKey(alias);
}

Expand All @@ -133,7 +130,6 @@ public void engineStore(OutputStream stream, char[] password) {

@Override
public void engineLoad(InputStream stream, char[] password) {
// Nothing to do, this is a mock keystore implementation, for testing only.
}

}

0 comments on commit bc6fc33

Please sign in to comment.