Spring Boot AutoConfigure provides auto-configuration capabilities that automatically configure Spring applications based on jar dependencies present on the classpath
—
Spring Boot AutoConfigure provides comprehensive SSL/TLS configuration support through centralized SSL bundle management. SSL bundles allow you to define reusable SSL trust material that can be referenced throughout your application, supporting both JKS (Java KeyStore) and PEM (Privacy Enhanced Mail) formats.
import org.springframework.boot.autoconfigure.ssl.*;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundleRegistry;SSL bundles provide a way to configure SSL trust material (certificates, private keys, truststores) in a centralized location that can be referenced by name throughout your application. This approach simplifies SSL configuration and promotes reusability.
Root configuration properties for centralized SSL trust material configuration.
@ConfigurationProperties("spring.ssl")
public class SslProperties {
/**
* Get the SSL bundles configuration.
*/
public Bundles getBundle();
/**
* SSL bundles configuration container.
*/
public static class Bundles {
/**
* PEM-encoded SSL trust material bundles.
* Map key is the bundle name.
*/
public Map<String, PemSslBundleProperties> getPem();
/**
* Java keystore SSL trust material bundles.
* Map key is the bundle name.
*/
public Map<String, JksSslBundleProperties> getJks();
/**
* Trust material file watching configuration.
*/
public Watch getWatch();
}
/**
* Configuration for watching SSL bundle files for changes.
*/
public static class Watch {
/**
* Get file watching configuration.
*/
public File getFile();
public static class File {
/**
* Quiet period after which file changes are detected.
* Default is 10 seconds.
*/
public Duration getQuietPeriod();
/**
* Set the quiet period for file change detection.
*/
public void setQuietPeriod(Duration quietPeriod);
}
}
}Configuration example:
spring:
ssl:
bundle:
pem:
my-bundle:
keystore:
certificate: classpath:cert.pem
private-key: classpath:key.pem
truststore:
certificate: classpath:ca.pem
jks:
another-bundle:
keystore:
location: classpath:keystore.jks
password: secret
truststore:
location: classpath:truststore.jks
password: secret
watch:
file:
quiet-period: 5sConfiguration properties for PEM-encoded SSL bundles. PEM format uses base64-encoded X.509 certificates and PKCS8 private keys.
public class PemSslBundleProperties extends SslBundleProperties {
/**
* Get keystore configuration for PEM bundle.
*/
public Store getKeystore();
/**
* Get truststore configuration for PEM bundle.
*/
public Store getTruststore();
/**
* PEM store configuration.
*/
public static class Store {
/**
* Type of the store to create (e.g., JKS, PKCS12).
* If not specified, a suitable type will be inferred.
*/
public String getType();
public void setType(String type);
/**
* Location or content of the certificate or certificate chain in PEM format.
* Can be a classpath resource, file path, or inline PEM content.
*/
public String getCertificate();
public void setCertificate(String certificate);
/**
* Location or content of the private key in PEM format.
* Can be a classpath resource, file path, or inline PEM content.
*/
public String getPrivateKey();
public void setPrivateKey(String privateKey);
/**
* Password used to decrypt an encrypted private key.
*/
public String getPrivateKeyPassword();
public void setPrivateKeyPassword(String privateKeyPassword);
/**
* Whether to verify that the private key matches the public key.
* Default is false.
*/
public boolean isVerifyKeys();
public void setVerifyKeys(boolean verifyKeys);
}
}Configuration example:
spring:
ssl:
bundle:
pem:
web-server:
keystore:
certificate: classpath:server-cert.pem
private-key: classpath:server-key.pem
private-key-password: ${KEY_PASSWORD}
truststore:
certificate: classpath:ca-bundle.pem
options:
ciphers:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
enabled-protocols:
- TLSv1.2
- TLSv1.3
protocol: TLS
reload-on-update: trueConfiguration properties for Java KeyStore (JKS) SSL bundles. Supports JKS, PKCS12, and other Java KeyStore formats.
public class JksSslBundleProperties extends SslBundleProperties {
/**
* Get keystore configuration for JKS bundle.
*/
public Store getKeystore();
/**
* Get truststore configuration for JKS bundle.
*/
public Store getTruststore();
/**
* JKS store configuration.
*/
public static class Store {
/**
* Type of the store (e.g., JKS, PKCS12).
* If not specified, the type is determined from the file extension.
*/
public String getType();
public void setType(String type);
/**
* Provider for the store.
* If not specified, the default provider is used.
*/
public String getProvider();
public void setProvider(String provider);
/**
* Location of the resource containing the store content.
* Can be a classpath resource or file path.
*/
public String getLocation();
public void setLocation(String location);
/**
* Password used to access the store.
*/
public String getPassword();
public void setPassword(String password);
}
}Configuration example:
spring:
ssl:
bundle:
jks:
client:
keystore:
location: file:/etc/ssl/client-keystore.p12
password: ${KEYSTORE_PASSWORD}
type: PKCS12
truststore:
location: file:/etc/ssl/truststore.jks
password: ${TRUSTSTORE_PASSWORD}
type: JKS
key:
alias: client-key
password: ${KEY_PASSWORD}Abstract base class for all SSL bundle properties. Contains common configuration shared by both PEM and JKS bundles.
public abstract class SslBundleProperties {
/**
* Get key details for the bundle.
*/
public Key getKey();
/**
* Get SSL connection options.
*/
public Options getOptions();
/**
* Get the SSL protocol to use.
* Default is "TLS".
*/
public String getProtocol();
/**
* Set the SSL protocol to use (e.g., "TLS", "TLSv1.2", "TLSv1.3").
*/
public void setProtocol(String protocol);
/**
* Check if the bundle should be reloaded when updated.
* Default is false.
*/
public boolean isReloadOnUpdate();
/**
* Set whether to reload the SSL bundle when files are updated.
*/
public void setReloadOnUpdate(boolean reloadOnUpdate);
/**
* SSL connection options.
*/
public static class Options {
/**
* Supported SSL ciphers.
* If not specified, the default ciphers are used.
*/
public Set<String> getCiphers();
public void setCiphers(Set<String> ciphers);
/**
* Enabled SSL protocols.
* If not specified, the default protocols are used.
*/
public Set<String> getEnabledProtocols();
public void setEnabledProtocols(Set<String> enabledProtocols);
}
/**
* Key details for accessing keys in keystores.
*/
public static class Key {
/**
* The password used to access the key in the key store.
* May be null if the key is not password-protected.
*/
public String getPassword();
public void setPassword(String password);
/**
* The alias that identifies the key in the key store.
* If not specified, the first key in the store is used.
*/
public String getAlias();
public void setAlias(String alias);
}
}Interface for types that register SslBundle instances with an SslBundleRegistry. Implement this interface to programmatically register custom SSL bundles.
public interface SslBundleRegistrar {
/**
* Register SSL bundles with the given registry.
*
* @param registry the SSL bundle registry
*/
void registerBundles(SslBundleRegistry registry);
}Usage example:
import org.springframework.boot.autoconfigure.ssl.SslBundleRegistrar;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundleRegistry;
import org.springframework.boot.ssl.pem.PemSslStoreBundle;
import org.springframework.boot.ssl.pem.PemSslStoreDetails;
public class CustomSslBundleRegistrar implements SslBundleRegistrar {
@Override
public void registerBundles(SslBundleRegistry registry) {
// Create PEM store details
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate(
"classpath:custom-cert.pem")
.withPrivateKey("classpath:custom-key.pem")
.build();
PemSslStoreDetails trustStoreDetails = PemSslStoreDetails.forCertificate(
"classpath:custom-ca.pem")
.build();
// Create and register the bundle
PemSslStoreBundle storeBundle = new PemSslStoreBundle(
keyStoreDetails,
trustStoreDetails
);
SslBundle bundle = SslBundle.of(storeBundle);
registry.registerBundle("custom-bundle", bundle);
}
}server:
port: 8443
ssl:
bundle: web-server
enabled: true
spring:
ssl:
bundle:
pem:
web-server:
keystore:
certificate: classpath:server.crt
private-key: classpath:server.keyimport org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ServerConfiguration {
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory>
sslBundleCustomizer(SslBundles sslBundles) {
return factory -> {
factory.setSslBundles(sslBundles);
};
}
}import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.web.client.RestClient;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import javax.net.ssl.SSLContext;
@Service
public class MyApiClient {
private final RestClient restClient;
public MyApiClient(SslBundles sslBundles) {
SslBundle bundle = sslBundles.getBundle("client");
SSLContext sslContext = bundle.createSslContext();
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setSSLSocketFactory(sslContext.getSocketFactory());
this.restClient = RestClient.builder()
.requestFactory(factory)
.baseUrl("https://api.example.com")
.build();
}
public String fetchData() {
return restClient.get()
.uri("/data")
.retrieve()
.body(String.class);
}
}spring:
ssl:
bundle:
pem:
# Bundle for web server
web-server:
keystore:
certificate: classpath:server.crt
private-key: classpath:server.key
reload-on-update: true
# Bundle for external API client
api-client:
truststore:
certificate: classpath:api-ca.crt
# Bundle for database connection
database:
keystore:
certificate: classpath:db-client.crt
private-key: classpath:db-client.key
private-key-password: ${DB_KEY_PASSWORD}
truststore:
certificate: classpath:db-ca.crt
jks:
# Legacy JKS bundle
legacy-system:
keystore:
location: classpath:legacy.jks
password: ${LEGACY_PASSWORD}
type: JKS
key:
alias: legacy-keyimport org.springframework.boot.autoconfigure.ssl.SslBundleRegistrar;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundleRegistry;
import org.springframework.boot.ssl.jks.JksSslStoreBundle;
import org.springframework.boot.ssl.jks.JksSslStoreDetails;
import org.springframework.stereotype.Component;
@Component
public class DynamicSslBundleRegistrar implements SslBundleRegistrar {
@Override
public void registerBundles(SslBundleRegistry registry) {
// Register bundles based on runtime conditions
if (isProductionEnvironment()) {
registerProductionBundle(registry);
} else {
registerDevelopmentBundle(registry);
}
}
private void registerProductionBundle(SslBundleRegistry registry) {
JksSslStoreDetails keyStoreDetails = JksSslStoreDetails.forLocation(
"file:/etc/ssl/prod-keystore.p12")
.withPassword("prod-password")
.build();
JksSslStoreDetails trustStoreDetails = JksSslStoreDetails.forLocation(
"file:/etc/ssl/prod-truststore.jks")
.withPassword("trust-password")
.build();
JksSslStoreBundle storeBundle = new JksSslStoreBundle(
keyStoreDetails,
trustStoreDetails
);
SslBundle bundle = SslBundle.of(storeBundle);
registry.registerBundle("production", bundle);
}
private void registerDevelopmentBundle(SslBundleRegistry registry) {
// Register development bundle with self-signed certificates
// ... similar to above
}
private boolean isProductionEnvironment() {
return System.getenv("ENVIRONMENT") != null &&
System.getenv("ENVIRONMENT").equals("production");
}
}Enable automatic reloading of SSL bundles when certificate files change:
spring:
ssl:
bundle:
pem:
auto-reload:
keystore:
certificate: file:/etc/ssl/cert.pem
private-key: file:/etc/ssl/key.pem
reload-on-update: true # Enable automatic reloading
watch:
file:
quiet-period: 15s # Wait 15 seconds after last change before reloadingimport org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.TestPropertySource;
@SpringBootTest
@TestPropertySource(properties = {
"spring.ssl.bundle.pem.test.keystore.certificate=classpath:test-cert.pem",
"spring.ssl.bundle.pem.test.keystore.private-key=classpath:test-key.pem"
})
class MyServiceTest {
@Autowired
private SslBundles sslBundles;
@Test
void testSslConfiguration() {
assertThat(sslBundles.getBundle("test")).isNotNull();
}
@TestConfiguration
static class TestSslConfiguration {
// Additional test configuration if needed
}
}Use environment variables or external configuration for sensitive values:
spring:
ssl:
bundle:
jks:
secure:
keystore:
location: ${SSL_KEYSTORE_LOCATION}
password: ${SSL_KEYSTORE_PASSWORD}
key:
alias: ${SSL_KEY_ALIAS}
password: ${SSL_KEY_PASSWORD}Ensure SSL certificate and key files have appropriate permissions:
# Set restrictive permissions on private keys
chmod 600 /etc/ssl/private/server.key
chown app-user:app-group /etc/ssl/private/server.key
# Public certificates can be more permissive
chmod 644 /etc/ssl/certs/server.crtConfigure strong ciphers and modern TLS protocols:
spring:
ssl:
bundle:
pem:
secure-web:
keystore:
certificate: classpath:server.crt
private-key: classpath:server.key
options:
ciphers:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
enabled-protocols:
- TLSv1.3
- TLSv1.2
protocol: TLS