Skip to content

Commit

Permalink
Merge branch '2.7.x'
Browse files Browse the repository at this point in the history
Closes gh-33433
  • Loading branch information
mhalbritter committed Dec 1, 2022
2 parents bf2bc44 + ad2b130 commit a4779b7
Show file tree
Hide file tree
Showing 17 changed files with 732 additions and 34 deletions.
Expand Up @@ -51,6 +51,7 @@
* @author Brian Clozel
* @author Olivier Lamy
* @author Chris Bono
* @author Cyril Dangerville
*/
class SslServerCustomizer implements JettyServerCustomizer {

Expand Down Expand Up @@ -220,16 +221,24 @@ private void configureSslPasswords(SslContextFactory.Server factory, Ssl ssl) {
}

private void configureSslKeyStore(SslContextFactory.Server factory, Ssl ssl) {
try {
URL url = ResourceUtils.getURL(ssl.getKeyStore());
factory.setKeyStoreResource(Resource.newResource(url));
}
catch (Exception ex) {
throw new WebServerException("Could not load key store '" + ssl.getKeyStore() + "'", ex);
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.");
}
}
if (ssl.getKeyStoreType() != null) {
factory.setKeyStoreType(ssl.getKeyStoreType());
else {
try {
URL url = ResourceUtils.getURL(keystoreLocation);
factory.setKeyStoreResource(Resource.newResource(url));
}
catch (Exception ex) {
throw new WebServerException("Could not load key store '" + keystoreLocation + "'", ex);
}
}
factory.setKeyStoreType(keystoreType);
if (ssl.getKeyStoreProvider() != null) {
factory.setKeyStoreProvider(ssl.getKeyStoreProvider());
}
Expand Down
Expand Up @@ -57,6 +57,7 @@
* @author Brian Clozel
* @author Raheela Aslam
* @author Chris Bono
* @author Cyril Dangerville
* @since 2.0.0
* @deprecated this class is meant for Spring Boot internal use only.
*/
Expand Down Expand Up @@ -171,17 +172,25 @@ private KeyStore loadTrustStore(String type, String provider, String resource, S
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);
try {
URL url = ResourceUtils.getURL(resource);
try (InputStream stream = url.openStream()) {
store.load(stream, (password != null) ? password.toCharArray() : null);
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.");
}
return store;
store.load(null, (password != null) ? password.toCharArray() : null);
}
catch (Exception ex) {
throw new WebServerException("Could not load key store '" + resource + "'", ex);
else {
try {
URL url = ResourceUtils.getURL(resource);
try (InputStream stream = url.openStream()) {
store.load(stream, (password != null) ? password.toCharArray() : null);
}
}
catch (Exception ex) {
throw new WebServerException("Could not load key store '" + resource + "'", ex);
}
}

return store;
}

/**
Expand Down
Expand Up @@ -39,6 +39,7 @@
* @author Brian Clozel
* @author Andy Wilkinson
* @author Scott Frederick
* @author Cyril Dangerville
*/
class SslConnectorCustomizer implements TomcatConnectorCustomizer {

Expand Down Expand Up @@ -139,15 +140,23 @@ protected void configureSslStoreProvider(AbstractHttp11JsseProtocol<?> protocol,
}

private void configureSslKeyStore(SSLHostConfigCertificate certificate, Ssl ssl) {
try {
certificate.setCertificateKeystoreFile(ResourceUtils.getURL(ssl.getKeyStore()).toString());
}
catch (Exception ex) {
throw new WebServerException("Could not load key store '" + ssl.getKeyStore() + "'", ex);
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.");
}
}
if (ssl.getKeyStoreType() != null) {
certificate.setCertificateKeystoreType(ssl.getKeyStoreType());
else {
try {
certificate.setCertificateKeystoreFile(ResourceUtils.getURL(keystoreLocation).toString());
}
catch (Exception ex) {
throw new WebServerException("Could not load key store '" + keystoreLocation + "'", ex);
}
}
certificate.setCertificateKeystoreType(keystoreType);
if (ssl.getKeyStoreProvider() != null) {
certificate.setCertificateKeystoreProvider(ssl.getKeyStoreProvider());
}
Expand Down
Expand Up @@ -51,6 +51,7 @@
*
* @author Brian Clozel
* @author Raheela Aslam
* @author Cyril Dangerville
*/
class SslBuilderCustomizer implements UndertowBuilderCustomizer {

Expand Down Expand Up @@ -180,16 +181,26 @@ private KeyStore loadTrustStore(String type, String provider, String resource, S
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);
try {
URL url = ResourceUtils.getURL(resource);
try (InputStream stream = url.openStream()) {
store.load(stream, (password != null) ? password.toCharArray() : null);
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.");
}
return store;
store.load(null, (password != null) ? password.toCharArray() : null);
}
catch (Exception ex) {
throw new WebServerException("Could not load key store '" + resource + "'", ex);
else {
try {
URL url = ResourceUtils.getURL(resource);
try (InputStream stream = url.openStream()) {
store.load(stream, (password != null) ? password.toCharArray() : null);
}
}
catch (Exception ex) {
throw new WebServerException("Could not load key store '" + resource + "'", ex);
}
}

return store;
}

/**
Expand Down
Expand Up @@ -17,6 +17,8 @@
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 @@ -27,24 +29,47 @@
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.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.assertThatNoException;

/**
* Tests for {@link SslServerCustomizer}.
*
* @author Andy Wilkinson
* @author Cyril Dangerville
*/
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 @@ -82,8 +107,11 @@ void alpnConnectionFactoryHasNullDefaultProtocolToAllowNegotiationToHttp11() {
assertThat(((ALPNServerConnectionFactory) factories.get(1)).getDefaultProtocol()).isNull();
}

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

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

@Test
void customizeWhenSslIsEnabledWithPkcs11AndKeyStoreProvider() {
Ssl ssl = new Ssl();
ssl.setKeyStoreType("PKCS11");
ssl.setKeyStoreProvider(PKCS11_PROVIDER.getName());
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));
}

private Server createCustomizedServer() {
return createCustomizedServer(new Http2());
}
Expand Down

0 comments on commit a4779b7

Please sign in to comment.