Skip to content

Add support for LDAPS testing #588

@cdprete

Description

@cdprete

Hello.

I don't know if this ticket should be opened here or in spring-ldap, therefore feel free to redirect it if necessary.

The InMemoryDirectoryServer created in org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration supports only an LDAP connection, but the InMemoryListenerConfig used in there can be created easily for both.
The suggestion in this ticket is to extend the spring.ldap.embedded properties to allow to specify a server and, eventually, a client SslBundle name to use to create the InMemoryListenerConfig with SSL.

So far, I managed to make it partially work by copying what's in that auto-configuration, adapting it as follows and by not using @DataLdapTest:

@TestConfiguration(proxyBeanMethods = false)
@EnableConfigurationProperties(EmbeddedLdapProperties.class)
@ImportAutoConfiguration(exclude = EmbeddedLdapAutoConfiguration.class)
public class LdapsTestConfig implements DisposableBean {
    private InMemoryDirectoryServer server;

    @Bean(destroyMethod = "close")
    public InMemoryDirectoryServer directoryServer(GmsProperties gmsProperties, EmbeddedLdapProperties ldap, SslBundles sslBundles, ApplicationContext applicationContext) throws LDAPException {
        SslProperties ssl = gmsProperties.getSsl();
        InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(ldap.getBaseDn().toArray(new String[0]));
        config.addAdditionalBindCredentials(ldap.getCredential().getUsername(), ldap.getCredential().getPassword());
        InMemoryListenerConfig listenerConfig;
        if(ssl.isEnabled()) {
            SSLContext sslContext = sslBundles.getBundle(ssl.getBundle()).createSslContext();
            SSLServerSocketFactory serverSocketFactory = sslContext.getServerSocketFactory();
            SSLSocketFactory clientSocketFactory = sslContext.getSocketFactory();
            listenerConfig = createLDAPSConfig("LDAPS", null, ldap.getPort(), serverSocketFactory, clientSocketFactory);
        } else {
            listenerConfig = createLDAPConfig("LDAP", ldap.getPort());
        }
        config.setListenerConfigs(listenerConfig);
        server = new InMemoryDirectoryServer(config);
        importLdif(ldap, server, applicationContext);
        server.startListening();

        return server;
    }

    private static void importLdif(EmbeddedLdapProperties embeddedProperties, InMemoryDirectoryServer server, ApplicationContext applicationContext) {
        String location = embeddedProperties.getLdif();
        if (hasText(location)) {
            try {
                Resource resource = applicationContext.getResource(location);
                if (resource.exists()) {
                    try (InputStream inputStream = resource.getInputStream()) {
                        server.importFromLDIF(true, new LDIFReader(inputStream));
                    }
                }
            }
            catch (Exception ex) {
                throw new IllegalStateException("Unable to load LDIF " + location, ex);
            }
        }
    }

    @Override
    public void destroy() {
        server.close();
    }
}

But, that's not ideal and I can't manage to get the context closed when the test ends (it simply keeps running/hanging).

Metadata

Metadata

Assignees

No one assigned

    Labels

    for: external-projectFor an external project and not something we can fix

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions