Problem
Programmatically configure Spring Boot's to use my custom SSLContext
. And use for mTLS.
Context
Spring's documentation provides only one, clear way how to configure SSL (via application.properties
):
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.trust-store=classpath:truststore.jks
...
However, this solution lacks depth as there are scenarios, where I'd like to advantage of customizing my own SSLContext
. For example, configuring mTLS to trust not only single certificate generated via keytool
, but to trust both my self-signed certificate and ones placed within Java's default TrustStore (lib/security/cacerts
).
Of course, I could combine them using already mentioned keytool
, but I'm looking for more flexible approach, hence providing my own SSLContext
.
Spring provides a section on Configure the Web Server, which says to use either something like TomcatServletWebServerFactory
or ConfigurableServletWebServerFactory
, but they do not really go into depth.
I've tried creating a Component
:
@Component
public class CustomServletCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
private static final String SERVER_CERTIFICATE_PATH = "identity.jks";
private static final char[] PASSWORD = "secret".toCharArray();
private static final String CLIENT_CERTIFICATE_PATH = "certs/client.cer";
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
factory.setSslStoreProvider(new SslStoreProvider() {
@Override
public KeyStore getKeyStore() throws Exception {
var certificateAsInputStream = this.getClass().getClassLoader().getResourceAsStream(SERVER_CERTIFICATE_PATH);
var keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(certificateAsInputStream, PASSWORD);
return keyStore;
}
@Override
public KeyStore getTrustStore() throws Exception {
var keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
var organisationRootCertBytes = this.getClass().getClassLoader().getResourceAsStream(CLIENT_CERTIFICATE_PATH).readAllBytes();
var certificateFactory = CertificateFactory.getInstance("X.509");
var certificate = certificateFactory.generateCertificate(new ByteArrayInputStream(organisationRootCertBytes));
keyStore.setCertificateEntry("server", certificate);
return keyStore;
}
});
}
}
But to no avail.
question from:
https://stackoverflow.com/questions/65890334/configure-spring-boots-with-custom-sslcontext-programmatically-for-mtls 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…