Add SSL bundle auto-configuration support

Add auto-configuration for SSL bundles including new configuration
properties that can be used to define a bundle.

SSL bundle properties are provided under the `spring.ssl.bundle` key.
Currently `jks` and `pem` variants are support. Both are configured
as a `Map` where the bundle name is the key.

A typical example would be:

    spring:
      ssl:
        bundle:
          pem:
            mybundle
              key:
                password: secret
              keystore:
                certificate: classpath:mycert.pem
                private-key: classpath:mykey.pem

A `SslBundleRegistrar` interface is also provided to allow programmatic
contributions to the auto-configured `SslBundleRegistry`.

See gh-34814
pull/35107/head
Scott Frederick 2 years ago committed by Phillip Webb
parent e3677f7ff6
commit 8e1f24f98f

@ -0,0 +1,108 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.ssl;
import org.springframework.boot.ssl.jks.JksSslStoreBundle;
/**
* {@link SslBundleProperties} for Java keystores.
*
* @author Scott Frederick
* @author Phillip Webb
* @since 3.1.0
* @see JksSslStoreBundle
*/
public class JksSslBundleProperties extends SslBundleProperties {
/**
* Keystore properties.
*/
private final Store keystore = new Store();
/**
* Truststore properties.
*/
private final Store truststore = new Store();
public Store getKeystore() {
return this.keystore;
}
public Store getTruststore() {
return this.truststore;
}
/**
* Store properties.
*/
public static class Store {
/**
* Type of the store to create, e.g. JKS.
*/
private String type;
/**
* Provider for the store.
*/
private String provider;
/**
* Location of the resource containing the store content.
*/
private String location;
/**
* Password used to access the store.
*/
private String password;
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public String getProvider() {
return this.provider;
}
public void setProvider(String provider) {
this.provider = provider;
}
public String getLocation() {
return this.location;
}
public void setLocation(String location) {
this.location = location;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
}
}

@ -0,0 +1,95 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.ssl;
import org.springframework.boot.ssl.pem.PemSslStoreBundle;
/**
* {@link SslBundleProperties} for PEM-encoded certificates and private keys.
*
* @author Scott Frederick
* @author Phillip Webb
* @since 3.1.0
* @see PemSslStoreBundle
*/
public class PemSslBundleProperties extends SslBundleProperties {
/**
* Keystore properties.
*/
private Store keystore = new Store();
/**
* Truststore properties.
*/
private Store truststore = new Store();
public Store getKeystore() {
return this.keystore;
}
public Store getTruststore() {
return this.truststore;
}
/**
* Store properties.
*/
public static class Store {
/**
* Type of the store to create, e.g. JKS.
*/
String type;
/**
* Location or content of the certificate in PEM format.
*/
String certificate;
/**
* Location or content of the private key in PEM format.
*/
String privateKey;
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public String getCertificate() {
return this.certificate;
}
public void setCertificate(String certificate) {
this.certificate = certificate;
}
public String getPrivateKey() {
return this.privateKey;
}
public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}
}
}

@ -0,0 +1,131 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.ssl;
import org.springframework.boot.autoconfigure.ssl.SslBundleProperties.Key;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundleKey;
import org.springframework.boot.ssl.SslManagerBundle;
import org.springframework.boot.ssl.SslOptions;
import org.springframework.boot.ssl.SslStoreBundle;
import org.springframework.boot.ssl.jks.JksSslStoreBundle;
import org.springframework.boot.ssl.jks.JksSslStoreDetails;
import org.springframework.boot.ssl.pem.PemSslStoreBundle;
import org.springframework.boot.ssl.pem.PemSslStoreDetails;
/**
* {@link SslBundle} backed by {@link JksSslBundleProperties} or
* {@link PemSslBundleProperties}.
*
* @author Scott Frederick
* @author Phillip Webb
* @since 3.1.0
*/
public final class PropertiesSslBundle implements SslBundle {
private final SslStoreBundle stores;
private final SslBundleKey key;
private final SslOptions options;
private final String protocol;
private final SslManagerBundle managers;
private PropertiesSslBundle(SslStoreBundle stores, SslBundleProperties properties) {
this.stores = stores;
this.key = asSslKeyReference(properties.getKey());
this.options = asSslOptions(properties.getOptions());
this.protocol = properties.getProtocol();
this.managers = SslManagerBundle.from(this.stores, this.key);
}
private static SslBundleKey asSslKeyReference(Key key) {
return (key != null) ? SslBundleKey.of(key.getPassword(), key.getAlias()) : SslBundleKey.NONE;
}
private static SslOptions asSslOptions(SslBundleProperties.Options properties) {
return (properties != null) ? SslOptions.of(properties.getCiphers(), properties.getEnabledProtocols())
: SslOptions.NONE;
}
@Override
public SslStoreBundle getStores() {
return this.stores;
}
@Override
public SslBundleKey getKey() {
return this.key;
}
@Override
public SslOptions getOptions() {
return this.options;
}
@Override
public String getProtocol() {
return this.protocol;
}
@Override
public SslManagerBundle getManagers() {
return this.managers;
}
/**
* Get an {@link SslBundle} for the given {@link PemSslBundleProperties}.
* @param properties the source properties
* @return an {@link SslBundle} instance
*/
public static SslBundle get(PemSslBundleProperties properties) {
return new PropertiesSslBundle(asSslStoreBundle(properties), properties);
}
/**
* Get an {@link SslBundle} for the given {@link JksSslBundleProperties}.
* @param properties the source properties
* @return an {@link SslBundle} instance
*/
public static SslBundle get(JksSslBundleProperties properties) {
return new PropertiesSslBundle(asSslStoreBundle(properties), properties);
}
private static SslStoreBundle asSslStoreBundle(PemSslBundleProperties properties) {
PemSslStoreDetails keyStoreDetails = asStoreDetails(properties.getKeystore());
PemSslStoreDetails trustStoreDetails = asStoreDetails(properties.getTruststore());
return new PemSslStoreBundle(keyStoreDetails, trustStoreDetails, properties.getKey().getAlias());
}
private static PemSslStoreDetails asStoreDetails(PemSslBundleProperties.Store properties) {
return new PemSslStoreDetails(properties.getType(), properties.getCertificate(), properties.getPrivateKey());
}
private static SslStoreBundle asSslStoreBundle(JksSslBundleProperties properties) {
JksSslStoreDetails keyStoreDetails = asStoreDetails(properties.getKeystore());
JksSslStoreDetails trustStoreDetails = asStoreDetails(properties.getTruststore());
return new JksSslStoreBundle(keyStoreDetails, trustStoreDetails);
}
private static JksSslStoreDetails asStoreDetails(JksSslBundleProperties.Store properties) {
return new JksSslStoreDetails(properties.getType(), properties.getProvider(), properties.getLocation(),
properties.getPassword());
}
}

@ -0,0 +1,56 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.ssl;
import java.util.List;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.ssl.DefaultSslBundleRegistry;
import org.springframework.boot.ssl.SslBundleRegistry;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.context.annotation.Bean;
/**
* {@link EnableAutoConfiguration Auto-configuration} for SSL.
*
* @author Scott Frederick
* @since 3.1.0
*/
@AutoConfiguration
@EnableConfigurationProperties(SslProperties.class)
public class SslAutoConfiguration {
SslAutoConfiguration() {
}
@Bean
public SslPropertiesBundleRegistrar sslPropertiesSslBundleRegistrar(SslProperties sslProperties) {
return new SslPropertiesBundleRegistrar(sslProperties);
}
@Bean
@ConditionalOnMissingBean({ SslBundleRegistry.class, SslBundles.class })
public DefaultSslBundleRegistry sslBundleRegistry(List<SslBundleRegistrar> sslBundleRegistrars) {
DefaultSslBundleRegistry registry = new DefaultSslBundleRegistry();
sslBundleRegistrars.forEach((registrar) -> registrar.registerBundles(registry));
return registry;
}
}

@ -0,0 +1,124 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.ssl;
import java.util.Set;
import org.springframework.boot.ssl.SslBundle;
/**
* Base class for SSL Bundle properties.
*
* @author Scott Frederick
* @author Phillip Webb
* @since 3.1.0
* @see SslBundle
*/
public abstract class SslBundleProperties {
/**
* Key details for the bundle.
*/
private final Key key = new Key();
/**
* Options for the SLL connection.
*/
private final Options options = new Options();
/**
* SSL Protocol to use.
*/
private String protocol = SslBundle.DEFAULT_PROTOCOL;
public Key getKey() {
return this.key;
}
public Options getOptions() {
return this.options;
}
public String getProtocol() {
return this.protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public static class Options {
/**
* Supported SSL ciphers.
*/
private Set<String> ciphers;
/**
* Enabled SSL protocols.
*/
private Set<String> enabledProtocols;
public Set<String> getCiphers() {
return this.ciphers;
}
public void setCiphers(Set<String> ciphers) {
this.ciphers = ciphers;
}
public Set<String> getEnabledProtocols() {
return this.enabledProtocols;
}
public void setEnabledProtocols(Set<String> enabledProtocols) {
this.enabledProtocols = enabledProtocols;
}
}
public static class Key {
/**
* The password used to access the key in the key store.
*/
private String password;
/**
* The alias that identifies the key in the key store.
*/
private String alias;
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAlias() {
return this.alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
}
}

@ -0,0 +1,39 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.ssl;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundleRegistry;
/**
* Interface to be implemented by types that register {@link SslBundle} instances with an
* {@link SslBundleRegistry}.
*
* @author Scott Frederick
* @since 3.1.0
*/
@FunctionalInterface
public interface SslBundleRegistrar {
/**
* Callback method for registering {@link SslBundle}s with an
* {@link SslBundleRegistry}.
* @param registry the registry that accepts {@code SslBundle}s
*/
void registerBundles(SslBundleRegistry registry);
}

@ -0,0 +1,70 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.ssl;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
/**
* Properties for centralized SSL trust material configuration.
*
* @author Scott Frederick
* @since 3.1.0
*/
@ConfigurationProperties(prefix = "spring.ssl")
public class SslProperties {
/**
* SSL bundles.
*/
private final Bundles bundle = new Bundles();
public Bundles getBundle() {
return this.bundle;
}
/**
* Properties to define SSL Bundles.
*/
public static class Bundles {
/**
* PEM-encoded SSL trust material.
*/
@NestedConfigurationProperty
private final Map<String, PemSslBundleProperties> pem = new LinkedHashMap<>();
/**
* Java keystore SSL trust material.
*/
@NestedConfigurationProperty
private final Map<String, JksSslBundleProperties> jks = new LinkedHashMap<>();
public Map<String, PemSslBundleProperties> getPem() {
return this.pem;
}
public Map<String, JksSslBundleProperties> getJks() {
return this.jks;
}
}
}

@ -0,0 +1,52 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.ssl;
import java.util.Map;
import java.util.function.Function;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundleRegistry;
/**
* A {@link SslBundleRegistrar} that registers SSL bundles based
* {@link SslProperties#getBundle() configuration properties}.
*
* @author Scott Frederick
* @author Phillip Webb
*/
class SslPropertiesBundleRegistrar implements SslBundleRegistrar {
private final SslProperties.Bundles properties;
SslPropertiesBundleRegistrar(SslProperties properties) {
this.properties = properties.getBundle();
}
@Override
public void registerBundles(SslBundleRegistry registry) {
registerBundles(registry, this.properties.getPem(), PropertiesSslBundle::get);
registerBundles(registry, this.properties.getJks(), PropertiesSslBundle::get);
}
private <P extends SslBundleProperties> void registerBundles(SslBundleRegistry registry, Map<String, P> properties,
Function<P, SslBundle> bundleFactory) {
properties.forEach((bundleName, bundleProperties) -> registry.registerBundle(bundleName,
bundleFactory.apply(bundleProperties)));
}
}

@ -0,0 +1,20 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Auto-configuration for SSL bundles.
*/
package org.springframework.boot.autoconfigure.ssl;

@ -262,6 +262,10 @@
"name": "server.shutdown", "name": "server.shutdown",
"defaultValue": "immediate" "defaultValue": "immediate"
}, },
{
"name": "server.ssl.bundle",
"description": "The name of a configured SSL bundle."
},
{ {
"name": "server.ssl.certificate", "name": "server.ssl.certificate",
"description": "Path to a PEM-encoded SSL certificate file." "description": "Path to a PEM-encoded SSL certificate file."

@ -116,6 +116,7 @@ org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.Reactiv
org.springframework.boot.autoconfigure.security.oauth2.server.servlet.OAuth2AuthorizationServerAutoConfiguration org.springframework.boot.autoconfigure.security.oauth2.server.servlet.OAuth2AuthorizationServerAutoConfiguration
org.springframework.boot.autoconfigure.security.oauth2.server.servlet.OAuth2AuthorizationServerJwtAutoConfiguration org.springframework.boot.autoconfigure.security.oauth2.server.servlet.OAuth2AuthorizationServerJwtAutoConfiguration
org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration
org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration

@ -0,0 +1,145 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.ssl;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundleRegistry;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link SslAutoConfiguration}.
*
* @author Scott Frederick
* @author Phillip Webb
*/
class SslAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(SslAutoConfiguration.class));
@Test
void sslBundlesCreatedWithNoConfiguration() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(SslBundleRegistry.class));
}
@Test
void sslBundlesCreatedWithCertificates() {
List<String> propertyValues = new ArrayList<>();
propertyValues.add("spring.ssl.bundle.pem.first.key.alias=alias1");
propertyValues.add("spring.ssl.bundle.pem.first.key.password=secret1");
propertyValues.add("spring.ssl.bundle.pem.first.keystore.certificate=cert1.pem");
propertyValues.add("spring.ssl.bundle.pem.first.keystore.private-key=key1.pem");
propertyValues.add("spring.ssl.bundle.pem.first.keystore.type=JKS");
propertyValues.add("spring.ssl.bundle.pem.first.truststore.type=PKCS12");
propertyValues.add("spring.ssl.bundle.pem.second.key.alias=alias2");
propertyValues.add("spring.ssl.bundle.pem.second.key.password=secret2");
propertyValues.add("spring.ssl.bundle.pem.second.keystore.certificate=cert2.pem");
propertyValues.add("spring.ssl.bundle.pem.second.keystore.private-key=key2.pem");
propertyValues.add("spring.ssl.bundle.pem.second.keystore.type=PKCS12");
propertyValues.add("spring.ssl.bundle.pem.second.truststore.certificate=ca.pem");
propertyValues.add("spring.ssl.bundle.pem.second.truststore.private-key=ca-key.pem");
propertyValues.add("spring.ssl.bundle.pem.second.truststore.type=JKS");
this.contextRunner.withPropertyValues(propertyValues.toArray(String[]::new)).run((context) -> {
assertThat(context).hasSingleBean(SslBundles.class);
SslBundles bundles = context.getBean(SslBundles.class);
SslBundle first = bundles.getBundle("first");
assertThat(first).isNotNull();
assertThat(first.getStores()).isNotNull();
assertThat(first.getManagers()).isNotNull();
assertThat(first.getKey().getAlias()).isEqualTo("alias1");
assertThat(first.getKey().getPassword()).isEqualTo("secret1");
assertThat(first.getStores()).extracting("keyStoreDetails").extracting("type").isEqualTo("JKS");
assertThat(first.getStores()).extracting("trustStoreDetails").extracting("type").isEqualTo("PKCS12");
SslBundle second = bundles.getBundle("second");
assertThat(second).isNotNull();
assertThat(second.getStores()).isNotNull();
assertThat(second.getManagers()).isNotNull();
assertThat(second.getKey().getAlias()).isEqualTo("alias2");
assertThat(second.getKey().getPassword()).isEqualTo("secret2");
assertThat(second.getStores()).extracting("keyStoreDetails").extracting("type").isEqualTo("PKCS12");
assertThat(second.getStores()).extracting("trustStoreDetails").extracting("type").isEqualTo("JKS");
});
}
@Test
void sslBundlesCreatedWithCustomSslBundle() {
List<String> propertyValues = new ArrayList<>();
propertyValues.add("custom.ssl.key.alias=alias1");
propertyValues.add("custom.ssl.key.password=secret1");
propertyValues.add("custom.ssl.keystore.type=JKS");
propertyValues.add("custom.ssl.truststore.type=PKCS12");
this.contextRunner.withUserConfiguration(CustomSslBundleConfiguration.class)
.withPropertyValues(propertyValues.toArray(String[]::new))
.run((context) -> {
assertThat(context).hasSingleBean(SslBundles.class);
SslBundles bundles = context.getBean(SslBundles.class);
SslBundle first = bundles.getBundle("custom");
assertThat(first).isNotNull();
assertThat(first.getStores()).isNotNull();
assertThat(first.getManagers()).isNotNull();
assertThat(first.getKey().getAlias()).isEqualTo("alias1");
assertThat(first.getKey().getPassword()).isEqualTo("secret1");
assertThat(first.getStores()).extracting("keyStoreDetails").extracting("type").isEqualTo("JKS");
assertThat(first.getStores()).extracting("trustStoreDetails").extracting("type").isEqualTo("PKCS12");
});
}
@Configuration
@EnableConfigurationProperties(CustomSslProperties.class)
public static class CustomSslBundleConfiguration {
@Bean
public SslBundleRegistrar customSslBundlesRegistrar(CustomSslProperties properties) {
return new CustomSslBundlesRegistrar(properties);
}
}
@ConfigurationProperties("custom.ssl")
static class CustomSslProperties extends PemSslBundleProperties {
}
static class CustomSslBundlesRegistrar implements SslBundleRegistrar {
private final CustomSslProperties properties;
CustomSslBundlesRegistrar(CustomSslProperties properties) {
this.properties = properties;
}
@Override
public void registerBundles(SslBundleRegistry registry) {
registry.registerBundle("custom", PropertiesSslBundle.get(this.properties));
}
}
}
Loading…
Cancel
Save