From dfd41a6b9ff6b7105e1135d04b61300fadd29aa9 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 19 Dec 2025 10:50:39 +0000 Subject: [PATCH] Polish "Add LDAPS support to embedded LDAP server" See gh-48315 --- .../modules/reference/pages/data/nosql.adoc | 17 ++ .../EmbeddedLdapAutoConfiguration.java | 118 +++----------- .../embedded/EmbeddedLdapProperties.java | 152 +----------------- .../EmbeddedLdapAutoConfigurationTests.java | 147 +++++++---------- 4 files changed, 104 insertions(+), 330 deletions(-) diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/data/nosql.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/data/nosql.adoc index fadce3ad13b..8bb18267aef 100644 --- a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/data/nosql.adoc +++ b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/data/nosql.adoc @@ -736,3 +736,20 @@ If you want to load the initialization script from a different resource, you can By default, a standard schema is used to validate `LDIF` files. You can turn off validation altogether by setting the configprop:spring.ldap.embedded.validation.enabled[] property. If you have custom attributes, you can use configprop:spring.ldap.embedded.validation.schema[] to define your custom attribute types or object classes. + + + +[[data.nosql.ldap.embedded.ssl]] +==== SSL + +The in-memory LDAP server supports SSL (LDAPS). +To enable SSL, configure the xref:features/ssl.adoc[SSL bundle] to use by setting the configprop:spring.ldap.embedded.ssl.bundle[] property, as shown in the following example: + +[configprops,yaml] +---- +spring: + ldap: + embedded: + ssl: + bundle: "example" +---- diff --git a/module/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapAutoConfiguration.java b/module/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapAutoConfiguration.java index 982cce9726c..a2f51bc1419 100644 --- a/module/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapAutoConfiguration.java +++ b/module/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapAutoConfiguration.java @@ -16,27 +16,15 @@ package org.springframework.boot.ldap.autoconfigure.embedded; -import java.io.IOException; import java.io.InputStream; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; import com.unboundid.ldap.listener.InMemoryDirectoryServer; import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; @@ -64,6 +52,7 @@ import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.ldap.autoconfigure.LdapAutoConfiguration; import org.springframework.boot.ldap.autoconfigure.LdapProperties; import org.springframework.boot.ldap.autoconfigure.embedded.EmbeddedLdapAutoConfiguration.EmbeddedLdapAutoConfigurationRuntimeHints; +import org.springframework.boot.ldap.autoconfigure.embedded.EmbeddedLdapProperties.Ssl; import org.springframework.boot.ssl.SslBundle; import org.springframework.boot.ssl.SslBundles; import org.springframework.context.ApplicationContext; @@ -79,8 +68,6 @@ import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.PropertySource; import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.ldap.core.ContextSource; import org.springframework.ldap.core.support.LdapContextSource; @@ -106,8 +93,6 @@ public final class EmbeddedLdapAutoConfiguration implements DisposableBean { private final EmbeddedLdapProperties embeddedProperties; - private final ResourceLoader resourceLoader = new PathMatchingResourcePatternResolver(); - private @Nullable InMemoryDirectoryServer server; EmbeddedLdapAutoConfiguration(EmbeddedLdapProperties embeddedProperties) { @@ -116,8 +101,7 @@ public final class EmbeddedLdapAutoConfiguration implements DisposableBean { @Bean InMemoryDirectoryServer directoryServer(ApplicationContext applicationContext, - ObjectProvider sslBundles) throws LDAPException, KeyStoreException, IOException, - NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException { + ObjectProvider sslBundles) throws LDAPException { String[] baseDn = StringUtils.toStringArray(this.embeddedProperties.getBaseDn()); InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(baseDn); String username = this.embeddedProperties.getCredential().getUsername(); @@ -125,19 +109,8 @@ public final class EmbeddedLdapAutoConfiguration implements DisposableBean { if (StringUtils.hasText(username) && StringUtils.hasText(password)) { config.addAdditionalBindCredentials(username, password); } + config.setListenerConfigs(createListenerConfig(sslBundles)); setSchema(config); - if (this.embeddedProperties.getSsl().isEnabled()) { - EmbeddedLdapProperties.Ssl ssl = this.embeddedProperties.getSsl(); - SSLContext sslContext = getSslContext(ssl, sslBundles.getIfAvailable()); - SSLServerSocketFactory serverSocketFactory = sslContext.getServerSocketFactory(); - SSLSocketFactory clientSocketFactory = sslContext.getSocketFactory(); - config.setListenerConfigs(InMemoryListenerConfig.createLDAPSConfig("LDAPS", null, - this.embeddedProperties.getPort(), serverSocketFactory, clientSocketFactory)); - } - else { - config - .setListenerConfigs(InMemoryListenerConfig.createLDAPConfig("LDAP", this.embeddedProperties.getPort())); - } this.server = new InMemoryDirectoryServer(config); importLdif(this.server, applicationContext); this.server.startListening(); @@ -145,6 +118,27 @@ public final class EmbeddedLdapAutoConfiguration implements DisposableBean { return this.server; } + private InMemoryListenerConfig createListenerConfig(ObjectProvider sslBundles) throws LDAPException { + SslBundle sslBundle = getSslBundle(sslBundles.getIfAvailable()); + if (sslBundle != null) { + SSLContext sslContext = sslBundle.createSslContext(); + SSLServerSocketFactory serverSocketFactory = sslContext.getServerSocketFactory(); + SSLSocketFactory clientSocketFactory = sslContext.getSocketFactory(); + return InMemoryListenerConfig.createLDAPSConfig("LDAPS", null, this.embeddedProperties.getPort(), + serverSocketFactory, clientSocketFactory); + } + return InMemoryListenerConfig.createLDAPConfig("LDAP", this.embeddedProperties.getPort()); + } + + private @Nullable SslBundle getSslBundle(@Nullable SslBundles sslBundles) { + Ssl ssl = this.embeddedProperties.getSsl(); + if (ssl.isEnabled() && StringUtils.hasLength(ssl.getBundle())) { + Assert.notNull(sslBundles, "SSL bundle name has been set but no SSL bundles found in context"); + return sslBundles.getBundle(ssl.getBundle()); + } + return null; + } + private void setSchema(InMemoryDirectoryServerConfig config) { if (!this.embeddedProperties.getValidation().isEnabled()) { config.setSchema(null); @@ -216,70 +210,6 @@ public final class EmbeddedLdapAutoConfiguration implements DisposableBean { } } - private SSLContext getSslContext(EmbeddedLdapProperties.Ssl ssl, @Nullable SslBundles sslBundles) - throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, - UnrecoverableKeyException, KeyManagementException { - if (sslBundles != null && StringUtils.hasText(ssl.getBundle())) { - SslBundle sslBundle = sslBundles.getBundle(ssl.getBundle()); - Assert.notNull(sslBundle, "SSL bundle name has been set but no SSL bundles found in context"); - return sslBundle.createSslContext(); - - } - else { - SSLContext sslContext = SSLContext.getInstance(ssl.getAlgorithm()); - KeyManager[] keyManagers = configureKeyManagers(ssl); - TrustManager[] trustManagers = configureTrustManagers(ssl); - sslContext.init(keyManagers, trustManagers, new SecureRandom()); - return sslContext; - } - } - - private KeyManager @Nullable [] configureKeyManagers(EmbeddedLdapProperties.Ssl ssl) throws KeyStoreException, - IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException { - String keyStoreName = ssl.getKeyStore(); - String keyStorePassword = ssl.getKeyStorePassword(); - String storeType = ssl.getKeyStoreType(); - char[] keyPassphrase = null; - if (keyStorePassword != null) { - keyPassphrase = keyStorePassword.toCharArray(); - } - KeyManager[] keyManagers = null; - if (StringUtils.hasText(keyStoreName)) { - Resource resource = this.resourceLoader.getResource(keyStoreName); - KeyStore ks = KeyStore.getInstance(storeType); - try (InputStream inputStream = resource.getInputStream()) { - ks.load(inputStream, keyPassphrase); - } - KeyManagerFactory kmf = KeyManagerFactory.getInstance(ssl.getKeyStoreAlgorithm()); - kmf.init(ks, keyPassphrase); - keyManagers = kmf.getKeyManagers(); - } - return keyManagers; - } - - private TrustManager @Nullable [] configureTrustManagers(EmbeddedLdapProperties.Ssl ssl) - throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { - String trustStoreName = ssl.getTrustStore(); - String trustStorePassword = ssl.getTrustStorePassword(); - String storeType = ssl.getTrustStoreType(); - char[] trustPassphrase = null; - if (trustStorePassword != null) { - trustPassphrase = trustStorePassword.toCharArray(); - } - TrustManager[] trustManagers = null; - if (StringUtils.hasText(trustStoreName)) { - Resource resource = this.resourceLoader.getResource(trustStoreName); - KeyStore tks = KeyStore.getInstance(storeType); - try (InputStream inputStream = resource.getInputStream()) { - tks.load(inputStream, trustPassphrase); - } - TrustManagerFactory tmf = TrustManagerFactory.getInstance(ssl.getTrustStoreAlgorithm()); - tmf.init(tks); - trustManagers = tmf.getTrustManagers(); - } - return trustManagers; - } - /** * {@link SpringBootCondition} to determine when to apply embedded LDAP * auto-configuration. diff --git a/module/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapProperties.java b/module/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapProperties.java index 3e85ec2ee13..c43c72237db 100644 --- a/module/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapProperties.java +++ b/module/spring-boot-ldap/src/main/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapProperties.java @@ -16,12 +16,9 @@ package org.springframework.boot.ldap.autoconfigure.embedded; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; -import javax.net.ssl.SSLContext; - import org.jspecify.annotations.Nullable; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -146,87 +143,22 @@ public class EmbeddedLdapProperties { public static class Ssl { - private static final String SUN_X509 = "SunX509"; - - private static final String DEFAULT_PROTOCOL; - - static { - String protocol = "TLSv1.1"; - try { - String[] protocols = SSLContext.getDefault().getSupportedSSLParameters().getProtocols(); - for (String prot : protocols) { - if ("TLSv1.2".equals(prot)) { - protocol = "TLSv1.2"; - break; - } - } - } - catch (NoSuchAlgorithmException ex) { - // nothing - } - DEFAULT_PROTOCOL = protocol; - } - /** - * Whether to enable SSL support. + * Whether to enable SSL support. Enabled automatically if "bundle" is provided + * unless specified otherwise. */ - private Boolean enabled = false; + private @Nullable Boolean enabled; /** * SSL bundle name. */ private @Nullable String bundle; - /** - * Path to the key store that holds the SSL certificate. - */ - private @Nullable String keyStore; - - /** - * Key store type. - */ - private String keyStoreType = "PKCS12"; - - /** - * Password used to access the key store. - */ - private @Nullable String keyStorePassword; - - /** - * Key store algorithm. - */ - private String keyStoreAlgorithm = SUN_X509; - - /** - * Trust store that holds SSL certificates. - */ - private @Nullable String trustStore; - - /** - * Trust store type. - */ - private String trustStoreType = "JKS"; - - /** - * Password used to access the trust store. - */ - private @Nullable String trustStorePassword; - - /** - * Trust store algorithm. - */ - private String trustStoreAlgorithm = SUN_X509; - - /** - * SSL algorithm to use. - */ - private String algorithm = DEFAULT_PROTOCOL; - - public Boolean isEnabled() { - return this.enabled; + public boolean isEnabled() { + return (this.enabled != null) ? this.enabled : this.bundle != null; } - public void setEnabled(Boolean enabled) { + public void setEnabled(boolean enabled) { this.enabled = enabled; } @@ -238,78 +170,6 @@ public class EmbeddedLdapProperties { this.bundle = bundle; } - public @Nullable String getKeyStore() { - return this.keyStore; - } - - public void setKeyStore(@Nullable String keyStore) { - this.keyStore = keyStore; - } - - public String getKeyStoreType() { - return this.keyStoreType; - } - - public void setKeyStoreType(String keyStoreType) { - this.keyStoreType = keyStoreType; - } - - public @Nullable String getKeyStorePassword() { - return this.keyStorePassword; - } - - public void setKeyStorePassword(@Nullable String keyStorePassword) { - this.keyStorePassword = keyStorePassword; - } - - public String getKeyStoreAlgorithm() { - return this.keyStoreAlgorithm; - } - - public void setKeyStoreAlgorithm(String keyStoreAlgorithm) { - this.keyStoreAlgorithm = keyStoreAlgorithm; - } - - public @Nullable String getTrustStore() { - return this.trustStore; - } - - public void setTrustStore(@Nullable String trustStore) { - this.trustStore = trustStore; - } - - public String getTrustStoreType() { - return this.trustStoreType; - } - - public void setTrustStoreType(String trustStoreType) { - this.trustStoreType = trustStoreType; - } - - public @Nullable String getTrustStorePassword() { - return this.trustStorePassword; - } - - public void setTrustStorePassword(@Nullable String trustStorePassword) { - this.trustStorePassword = trustStorePassword; - } - - public String getTrustStoreAlgorithm() { - return this.trustStoreAlgorithm; - } - - public void setTrustStoreAlgorithm(String trustStoreAlgorithm) { - this.trustStoreAlgorithm = trustStoreAlgorithm; - } - - public String getAlgorithm() { - return this.algorithm; - } - - public void setAlgorithm(String sslAlgorithm) { - this.algorithm = sslAlgorithm; - } - } public static class Validation { diff --git a/module/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapAutoConfigurationTests.java b/module/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapAutoConfigurationTests.java index c28fd29e4ed..9830effb7ab 100644 --- a/module/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapAutoConfigurationTests.java +++ b/module/spring-boot-ldap/src/test/java/org/springframework/boot/ldap/autoconfigure/embedded/EmbeddedLdapAutoConfigurationTests.java @@ -67,101 +67,11 @@ class EmbeddedLdapAutoConfigurationTests { .run((context) -> { InMemoryDirectoryServer server = context.getBean(InMemoryDirectoryServer.class); assertThat(server.getListenPort()).isEqualTo(1234); - }); - } - - @Test - void testServerDefaultNoSsl() { - this.contextRunner - .withPropertyValues("spring.ldap.embedded.port:1234", "spring.ldap.embedded.base-dn:dc=spring,dc=org") - .run((context) -> { - InMemoryDirectoryServer server = context.getBean(InMemoryDirectoryServer.class); - assertThat(server.getConfig().getListenerConfigs().size()).isEqualTo(1); InMemoryListenerConfig config = server.getConfig().getListenerConfigs().get(0); assertThat(config.getListenerName()).isEqualTo("LDAP"); }); } - @Test - void testServerWithSslBundle() { - List propertyValues = new ArrayList<>(); - String location = "classpath:org/springframework/boot/ldap/autoconfigure/embedded/"; - propertyValues.add("spring.ssl.bundle.jks.test.keystore.password=secret"); - propertyValues.add("spring.ssl.bundle.jks.test.keystore.location=" + location + "test.jks"); - propertyValues.add("spring.ssl.bundle.jks.test.truststore.location=" + location + "test.jks"); - propertyValues.add("spring.ssl.bundle.jks.test.protocol=TLSv1.2"); - propertyValues.add("spring.ldap.embedded.port:1234"); - propertyValues.add("spring.ldap.embedded.base-dn:dc=spring,dc=org"); - propertyValues.add("spring.ldap.embedded.ssl.enabled:true"); - propertyValues.add("spring.ldap.embedded.ssl.bundle:test"); - this.contextRunner.withPropertyValues(propertyValues.toArray(String[]::new)).run((context) -> { - InMemoryDirectoryServer server = context.getBean(InMemoryDirectoryServer.class); - assertThat(server.getConfig().getListenerConfigs().size()).isEqualTo(1); - InMemoryListenerConfig config = server.getConfig().getListenerConfigs().get(0); - assertThat(config.getListenerName()).isEqualTo("LDAPS"); - assertThat(config.getListenPort()).isEqualTo(1234); - assertThat(server.getListenPort()).isEqualTo(1234); - assertThat(server.getConnection("LDAPS").getSSLSession()).isNotNull(); - }); - } - - @Test - void testServerWithInvalidSslBundleShouldFail() { - List propertyValues = new ArrayList<>(); - String location = "classpath:org/springframework/boot/ldap/autoconfigure/embedded/"; - propertyValues.add("spring.ssl.bundle.jks.test.keystore.password=secret"); - propertyValues.add("spring.ssl.bundle.jks.test.keystore.location=" + location + "test.jks"); - propertyValues.add("spring.ldap.embedded.port:1234"); - propertyValues.add("spring.ldap.embedded.base-dn:dc=spring,dc=org"); - propertyValues.add("spring.ldap.embedded.ssl.enabled:true"); - propertyValues.add("spring.ldap.embedded.ssl.bundle:foo"); - this.contextRunner.withPropertyValues(propertyValues.toArray(String[]::new)).run((context) -> { - assertThat(context).hasFailed(); - assertThat(context).getFailure().hasMessageContaining("foo"); - assertThat(context).getFailure().hasMessageContaining("cannot be found"); - }); - } - - @Test - void testServerWithSsl() { - List propertyValues = new ArrayList<>(); - String location = "classpath:org/springframework/boot/ldap/autoconfigure/embedded/"; - propertyValues.add("spring.ldap.embedded.port:1234"); - propertyValues.add("spring.ldap.embedded.base-dn:dc=spring,dc=org"); - propertyValues.add("spring.ldap.embedded.ssl.enabled:true"); - propertyValues.add("spring.ldap.embedded.ssl.keyStorePassword=secret"); - propertyValues.add("spring.ldap.embedded.ssl.keyStore=" + location + "test.jks"); - propertyValues.add("spring.ldap.embedded.ssl.trustStorePassword=secret"); - propertyValues.add("spring.ldap.embedded.ssl.trustStore=" + location + "test.jks"); - this.contextRunner.withPropertyValues(propertyValues.toArray(String[]::new)).run((context) -> { - InMemoryDirectoryServer server = context.getBean(InMemoryDirectoryServer.class); - assertThat(server.getConfig().getListenerConfigs().size()).isEqualTo(1); - InMemoryListenerConfig config = server.getConfig().getListenerConfigs().get(0); - assertThat(config.getListenerName()).isEqualTo("LDAPS"); - assertThat(config.getListenPort()).isEqualTo(1234); - assertThat(server.getListenPort()).isEqualTo(1234); - assertThat(server.getConnection("LDAPS").getSSLSession()).isNotNull(); - }); - } - - @Test - void testServerWithInvalidSslShouldFail() { - List propertyValues = new ArrayList<>(); - String location = "classpath:org/springframework/boot/ldap/autoconfigure/embedded/"; - propertyValues.add("spring.ldap.embedded.port:1234"); - propertyValues.add("spring.ldap.embedded.base-dn:dc=spring,dc=org"); - propertyValues.add("spring.ldap.embedded.ssl.enabled:true"); - propertyValues.add("spring.ldap.embedded.ssl.keyStorePassword=secret"); - propertyValues.add("spring.ldap.embedded.ssl.keyStore=" + location + "foo"); - propertyValues.add("spring.ldap.embedded.ssl.trustStorePassword=secret"); - propertyValues.add("spring.ldap.embedded.ssl.trustStore=" + location + "foo"); - this.contextRunner.withPropertyValues(propertyValues.toArray(String[]::new)).run((context) -> { - assertThat(context).hasFailed(); - assertThat(context).getFailure().hasMessageContaining("foo"); - assertThat(context).getFailure().hasMessageContaining("does not exist"); - }); - } - @Test void testRandomPortWithEnvironment() { this.contextRunner.withPropertyValues("spring.ldap.embedded.base-dn:dc=spring,dc=org").run((context) -> { @@ -444,6 +354,63 @@ class EmbeddedLdapAutoConfigurationTests { }); } + @Test + void whenSslBundleIsConfiguredLdapsListenerIsConfigured() { + List propertyValues = new ArrayList<>(); + String location = "classpath:org/springframework/boot/ldap/autoconfigure/embedded/"; + propertyValues.add("spring.ssl.bundle.jks.test.keystore.password=secret"); + propertyValues.add("spring.ssl.bundle.jks.test.keystore.location=" + location + "test.jks"); + propertyValues.add("spring.ssl.bundle.jks.test.truststore.location=" + location + "test.jks"); + propertyValues.add("spring.ssl.bundle.jks.test.protocol=TLSv1.2"); + propertyValues.add("spring.ldap.embedded.port:0"); + propertyValues.add("spring.ldap.embedded.base-dn:dc=spring,dc=org"); + propertyValues.add("spring.ldap.embedded.ssl.bundle:test"); + this.contextRunner.withPropertyValues(propertyValues.toArray(String[]::new)).run((context) -> { + InMemoryDirectoryServer server = context.getBean(InMemoryDirectoryServer.class); + assertThat(server.getConfig().getListenerConfigs().size()).isEqualTo(1); + InMemoryListenerConfig config = server.getConfig().getListenerConfigs().get(0); + assertThat(config.getListenerName()).isEqualTo("LDAPS"); + assertThat(server.getConnection("LDAPS").getSSLSession()).isNotNull(); + }); + } + + @Test + void whenSslBundleIsConfiguredButSslIsDisabledLdapListenerIsConfigured() { + List propertyValues = new ArrayList<>(); + String location = "classpath:org/springframework/boot/ldap/autoconfigure/embedded/"; + propertyValues.add("spring.ssl.bundle.jks.test.keystore.password=secret"); + propertyValues.add("spring.ssl.bundle.jks.test.keystore.location=" + location + "test.jks"); + propertyValues.add("spring.ssl.bundle.jks.test.truststore.location=" + location + "test.jks"); + propertyValues.add("spring.ssl.bundle.jks.test.protocol=TLSv1.2"); + propertyValues.add("spring.ldap.embedded.port:0"); + propertyValues.add("spring.ldap.embedded.base-dn:dc=spring,dc=org"); + propertyValues.add("spring.ldap.embedded.ssl.enabled:false"); + propertyValues.add("spring.ldap.embedded.ssl.bundle:test"); + this.contextRunner.withPropertyValues(propertyValues.toArray(String[]::new)).run((context) -> { + InMemoryDirectoryServer server = context.getBean(InMemoryDirectoryServer.class); + assertThat(server.getConfig().getListenerConfigs().size()).isEqualTo(1); + InMemoryListenerConfig config = server.getConfig().getListenerConfigs().get(0); + assertThat(config.getListenerName()).isEqualTo("LDAP"); + }); + } + + @Test + void whenInvalidSslBundleIsConfiguredThenStartFails() { + List propertyValues = new ArrayList<>(); + String location = "classpath:org/springframework/boot/ldap/autoconfigure/embedded/"; + propertyValues.add("spring.ssl.bundle.jks.test.keystore.password=secret"); + propertyValues.add("spring.ssl.bundle.jks.test.keystore.location=" + location + "test.jks"); + propertyValues.add("spring.ldap.embedded.port:0"); + propertyValues.add("spring.ldap.embedded.base-dn:dc=spring,dc=org"); + propertyValues.add("spring.ldap.embedded.ssl.enabled:true"); + propertyValues.add("spring.ldap.embedded.ssl.bundle:foo"); + this.contextRunner.withPropertyValues(propertyValues.toArray(String[]::new)).run((context) -> { + assertThat(context).hasFailed(); + assertThat(context).getFailure().hasMessageContaining("foo"); + assertThat(context).getFailure().hasMessageContaining("cannot be found"); + }); + } + @Configuration(proxyBeanMethods = false) static class LdapClientConfiguration {