Merge branch '3.1.x' into 3.2.x

Fixes gh-39158
This commit is contained in:
Scott Frederick 2024-01-16 16:27:25 -06:00
commit 90564d722d
2 changed files with 163 additions and 14 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -69,12 +69,30 @@ public final class WebServerSslBundle implements SslBundle {
return new PemSslStoreBundle(keyStoreDetails, trustStoreDetails); return new PemSslStoreBundle(keyStoreDetails, trustStoreDetails);
} }
private static SslStoreBundle createJksStoreBundle(Ssl ssl) { private static SslStoreBundle createPemKeyStoreBundle(Ssl ssl) {
PemSslStoreDetails keyStoreDetails = new PemSslStoreDetails(ssl.getKeyStoreType(), ssl.getCertificate(),
ssl.getCertificatePrivateKey())
.withAlias(ssl.getKeyAlias());
return new PemSslStoreBundle(keyStoreDetails, null);
}
private static SslStoreBundle createPemTrustStoreBundle(Ssl ssl) {
PemSslStoreDetails trustStoreDetails = new PemSslStoreDetails(ssl.getTrustStoreType(),
ssl.getTrustCertificate(), ssl.getTrustCertificatePrivateKey())
.withAlias(ssl.getKeyAlias());
return new PemSslStoreBundle(null, trustStoreDetails);
}
private static SslStoreBundle createJksKeyStoreBundle(Ssl ssl) {
JksSslStoreDetails keyStoreDetails = new JksSslStoreDetails(ssl.getKeyStoreType(), ssl.getKeyStoreProvider(), JksSslStoreDetails keyStoreDetails = new JksSslStoreDetails(ssl.getKeyStoreType(), ssl.getKeyStoreProvider(),
ssl.getKeyStore(), ssl.getKeyStorePassword()); ssl.getKeyStore(), ssl.getKeyStorePassword());
return new JksSslStoreBundle(keyStoreDetails, null);
}
private static SslStoreBundle createJksTrustStoreBundle(Ssl ssl) {
JksSslStoreDetails trustStoreDetails = new JksSslStoreDetails(ssl.getTrustStoreType(), JksSslStoreDetails trustStoreDetails = new JksSslStoreDetails(ssl.getTrustStoreType(),
ssl.getTrustStoreProvider(), ssl.getTrustStore(), ssl.getTrustStorePassword()); ssl.getTrustStoreProvider(), ssl.getTrustStore(), ssl.getTrustStorePassword());
return new JksSslStoreBundle(keyStoreDetails, trustStoreDetails); return new JksSslStoreBundle(null, trustStoreDetails);
} }
@Override @Override
@ -157,30 +175,55 @@ public final class WebServerSslBundle implements SslBundle {
} }
private static SslStoreBundle createStoreBundle(Ssl ssl) { private static SslStoreBundle createStoreBundle(Ssl ssl) {
if (hasCertificateProperties(ssl)) { KeyStore keyStore = createKeyStore(ssl);
return createPemStoreBundle(ssl); KeyStore trustStore = createTrustStore(ssl);
return new WebServerSslStoreBundle(keyStore, trustStore, ssl.getKeyStorePassword());
}
private static KeyStore createKeyStore(Ssl ssl) {
if (hasPemKeyStoreProperties(ssl)) {
return createPemKeyStoreBundle(ssl).getKeyStore();
} }
if (hasJavaKeyStoreProperties(ssl)) { else if (hasJksKeyStoreProperties(ssl)) {
return createJksStoreBundle(ssl); return createJksKeyStoreBundle(ssl).getKeyStore();
} }
throw new IllegalStateException("SSL is enabled but no trust material is configured"); return null;
}
private static KeyStore createTrustStore(Ssl ssl) {
if (hasPemTrustStoreProperties(ssl)) {
return createPemTrustStoreBundle(ssl).getTrustStore();
}
else if (hasJksTrustStoreProperties(ssl)) {
return createJksTrustStoreBundle(ssl).getTrustStore();
}
return null;
} }
static SslBundle createCertificateFileSslStoreProviderDelegate(Ssl ssl) { static SslBundle createCertificateFileSslStoreProviderDelegate(Ssl ssl) {
if (!hasCertificateProperties(ssl)) { if (!hasPemKeyStoreProperties(ssl)) {
return null; return null;
} }
SslStoreBundle stores = createPemStoreBundle(ssl); SslStoreBundle stores = createPemStoreBundle(ssl);
return new WebServerSslBundle(stores, ssl.getKeyPassword(), ssl); return new WebServerSslBundle(stores, ssl.getKeyPassword(), ssl);
} }
private static boolean hasCertificateProperties(Ssl ssl) { private static boolean hasPemKeyStoreProperties(Ssl ssl) {
return Ssl.isEnabled(ssl) && ssl.getCertificate() != null && ssl.getCertificatePrivateKey() != null; return Ssl.isEnabled(ssl) && ssl.getCertificate() != null && ssl.getCertificatePrivateKey() != null;
} }
private static boolean hasJavaKeyStoreProperties(Ssl ssl) { private static boolean hasPemTrustStoreProperties(Ssl ssl) {
return Ssl.isEnabled(ssl) && ssl.getKeyStore() != null return Ssl.isEnabled(ssl) && ssl.getTrustCertificate() != null;
|| (ssl.getKeyStoreType() != null && ssl.getKeyStoreType().equals("PKCS11")); }
private static boolean hasJksKeyStoreProperties(Ssl ssl) {
return Ssl.isEnabled(ssl) && (ssl.getKeyStore() != null
|| (ssl.getKeyStoreType() != null && ssl.getKeyStoreType().equals("PKCS11")));
}
private static boolean hasJksTrustStoreProperties(Ssl ssl) {
return Ssl.isEnabled(ssl) && (ssl.getTrustStore() != null
|| (ssl.getTrustStoreType() != null && ssl.getTrustStoreType().equals("PKCS11")));
} }
/** /**
@ -212,4 +255,36 @@ public final class WebServerSslBundle implements SslBundle {
} }
private static final class WebServerSslStoreBundle implements SslStoreBundle {
private final KeyStore keyStore;
private final KeyStore trustStore;
private final String keyStorePassword;
private WebServerSslStoreBundle(KeyStore keyStore, KeyStore trustStore, String keyStorePassword) {
Assert.state(keyStore != null || trustStore != null, "SSL is enabled but no trust material is configured");
this.keyStore = keyStore;
this.trustStore = trustStore;
this.keyStorePassword = keyStorePassword;
}
@Override
public KeyStore getKeyStore() {
return this.keyStore;
}
@Override
public KeyStore getTrustStore() {
return this.trustStore;
}
@Override
public String getKeyStorePassword() {
return this.keyStorePassword;
}
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -95,6 +95,25 @@ class WebServerSslBundleTests {
.withMessageContaining("must be empty or null for PKCS11 hardware key stores"); .withMessageContaining("must be empty or null for PKCS11 hardware key stores");
} }
@Test
void whenFromPkcs11Properties() {
Ssl ssl = new Ssl();
ssl.setKeyStoreType("PKCS11");
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
ssl.setTrustStoreType("PKCS11");
ssl.setTrustStoreProvider(MockPkcs11SecurityProvider.NAME);
ssl.setKeyPassword("password");
ssl.setClientAuth(Ssl.ClientAuth.NONE);
SslBundle bundle = WebServerSslBundle.get(ssl);
assertThat(bundle).isNotNull();
assertThat(bundle.getProtocol()).isEqualTo("TLS");
SslBundleKey key = bundle.getKey();
assertThat(key.getPassword()).isEqualTo("password");
SslStoreBundle stores = bundle.getStores();
assertThat(stores.getKeyStore()).isNotNull();
assertThat(stores.getTrustStore()).isNotNull();
}
@Test @Test
void whenFromPemProperties() { void whenFromPemProperties() {
Ssl ssl = new Ssl(); Ssl ssl = new Ssl();
@ -122,6 +141,61 @@ class WebServerSslBundleTests {
assertThat(options.getEnabledProtocols()).containsExactly("TLSv1.1", "TLSv1.2"); assertThat(options.getEnabledProtocols()).containsExactly("TLSv1.1", "TLSv1.2");
} }
@Test
void whenPemKeyStoreAndJksTrustStoreProperties() {
Ssl ssl = new Ssl();
ssl.setCertificate("classpath:test-cert.pem");
ssl.setCertificatePrivateKey("classpath:test-key.pem");
ssl.setKeyStoreType("PKCS12");
ssl.setKeyPassword("password");
ssl.setTrustStore("classpath:test.p12");
ssl.setTrustStorePassword("secret");
ssl.setTrustStoreType("PKCS12");
ssl.setClientAuth(Ssl.ClientAuth.NONE);
ssl.setCiphers(new String[] { "ONE", "TWO", "THREE" });
ssl.setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" });
ssl.setProtocol("TLSv1.1");
SslBundle bundle = WebServerSslBundle.get(ssl);
assertThat(bundle).isNotNull();
SslBundleKey key = bundle.getKey();
assertThat(key.getAlias()).isNull();
assertThat(key.getPassword()).isEqualTo("password");
SslStoreBundle stores = bundle.getStores();
assertThat(stores.getKeyStorePassword()).isNull();
assertThat(stores.getKeyStore()).isNotNull();
assertThat(stores.getTrustStore()).isNotNull();
SslOptions options = bundle.getOptions();
assertThat(options.getCiphers()).containsExactly("ONE", "TWO", "THREE");
assertThat(options.getEnabledProtocols()).containsExactly("TLSv1.1", "TLSv1.2");
}
@Test
void whenJksKeyStoreAndPemTrustStoreProperties() {
Ssl ssl = new Ssl();
ssl.setKeyStore("classpath:test.p12");
ssl.setKeyStoreType("PKCS12");
ssl.setKeyPassword("password");
ssl.setTrustCertificate("classpath:test-cert-chain.pem");
ssl.setTrustStorePassword("secret");
ssl.setTrustStoreType("PKCS12");
ssl.setClientAuth(Ssl.ClientAuth.NONE);
ssl.setCiphers(new String[] { "ONE", "TWO", "THREE" });
ssl.setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" });
ssl.setProtocol("TLSv1.1");
SslBundle bundle = WebServerSslBundle.get(ssl);
assertThat(bundle).isNotNull();
SslBundleKey key = bundle.getKey();
assertThat(key.getAlias()).isNull();
assertThat(key.getPassword()).isEqualTo("password");
SslStoreBundle stores = bundle.getStores();
assertThat(stores.getKeyStorePassword()).isNull();
assertThat(stores.getKeyStore()).isNotNull();
assertThat(stores.getTrustStore()).isNotNull();
SslOptions options = bundle.getOptions();
assertThat(options.getCiphers()).containsExactly("ONE", "TWO", "THREE");
assertThat(options.getEnabledProtocols()).containsExactly("TLSv1.1", "TLSv1.2");
}
@Test @Test
@Deprecated(since = "3.1.0", forRemoval = true) @Deprecated(since = "3.1.0", forRemoval = true)
@SuppressWarnings("removal") @SuppressWarnings("removal")