Merge pull request #39258 from PhilKes
* pr/39258: Polish "Add Docker Compose service connection support for OpenLDAP" Add Docker Compose service connection support for OpenLDAP Closes gh-39258
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -46,18 +46,25 @@ import org.springframework.ldap.core.support.LdapContextSource;
|
||||
@EnableConfigurationProperties(LdapProperties.class)
|
||||
public class LdapAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(LdapConnectionDetails.class)
|
||||
PropertiesLdapConnectionDetails propertiesLdapConnectionDetails(LdapProperties properties,
|
||||
Environment environment) {
|
||||
return new PropertiesLdapConnectionDetails(properties, environment);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public LdapContextSource ldapContextSource(LdapProperties properties, Environment environment,
|
||||
public LdapContextSource ldapContextSource(LdapConnectionDetails connectionDetails, LdapProperties properties,
|
||||
ObjectProvider<DirContextAuthenticationStrategy> dirContextAuthenticationStrategy) {
|
||||
LdapContextSource source = new LdapContextSource();
|
||||
dirContextAuthenticationStrategy.ifUnique(source::setAuthenticationStrategy);
|
||||
PropertyMapper propertyMapper = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
propertyMapper.from(properties.getUsername()).to(source::setUserDn);
|
||||
propertyMapper.from(properties.getPassword()).to(source::setPassword);
|
||||
propertyMapper.from(connectionDetails.getUsername()).to(source::setUserDn);
|
||||
propertyMapper.from(connectionDetails.getPassword()).to(source::setPassword);
|
||||
propertyMapper.from(properties.getAnonymousReadOnly()).to(source::setAnonymousReadOnly);
|
||||
propertyMapper.from(properties.getBase()).to(source::setBase);
|
||||
propertyMapper.from(properties.determineUrls(environment)).to(source::setUrls);
|
||||
propertyMapper.from(connectionDetails.getBase()).to(source::setBase);
|
||||
propertyMapper.from(connectionDetails.getUrls()).to(source::setUrls);
|
||||
propertyMapper.from(properties.getBaseEnvironment())
|
||||
.to((baseEnvironment) -> source.setBaseEnvironmentProperties(Collections.unmodifiableMap(baseEnvironment)));
|
||||
return source;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.ldap;
|
||||
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
|
||||
|
||||
/**
|
||||
* Details required to establish a connection to an LDAP service.
|
||||
*
|
||||
* @author Philipp Kessler
|
||||
* @since 3.3.0
|
||||
*/
|
||||
public interface LdapConnectionDetails extends ConnectionDetails {
|
||||
|
||||
/**
|
||||
* LDAP URLs of the server.
|
||||
* @return the LDAP URLs to use
|
||||
*/
|
||||
String[] getUrls();
|
||||
|
||||
/**
|
||||
* Base suffix from which all operations should originate.
|
||||
* @return base suffix
|
||||
*/
|
||||
default String getBase() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Login username of the server.
|
||||
* @return login username
|
||||
*/
|
||||
default String getUsername() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Login password of the server.
|
||||
* @return login password
|
||||
*/
|
||||
default String getPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.ldap;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* Adapts {@link LdapProperties} to {@link LdapConnectionDetails}.
|
||||
*
|
||||
* @author Philipp Kessler
|
||||
* @since 3.3.0
|
||||
*/
|
||||
public class PropertiesLdapConnectionDetails implements LdapConnectionDetails {
|
||||
|
||||
private final LdapProperties properties;
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
PropertiesLdapConnectionDetails(LdapProperties properties, Environment environment) {
|
||||
this.properties = properties;
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getUrls() {
|
||||
return this.properties.determineUrls(this.environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBase() {
|
||||
return this.properties.getBase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.properties.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return this.properties.getPassword();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -29,6 +29,7 @@ import org.springframework.ldap.core.support.LdapContextSource;
|
||||
import org.springframework.ldap.core.support.SimpleDirContextAuthenticationStrategy;
|
||||
import org.springframework.ldap.pool2.factory.PoolConfig;
|
||||
import org.springframework.ldap.pool2.factory.PooledContextSource;
|
||||
import org.springframework.ldap.support.LdapUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -112,6 +113,25 @@ class LdapAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesLdapConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void usesCustomConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withUserConfiguration(ConnectionDetailsConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(LdapContextSource.class)
|
||||
.hasSingleBean(LdapConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesLdapConnectionDetails.class);
|
||||
LdapContextSource contextSource = context.getBean(LdapContextSource.class);
|
||||
assertThat(contextSource.getUrls()).isEqualTo(new String[] { "ldaps://ldap.example.com" });
|
||||
assertThat(contextSource.getBaseLdapName()).isEqualTo(LdapUtils.newLdapName("dc=base"));
|
||||
assertThat(contextSource.getUserDn()).isEqualTo("ldap-user");
|
||||
assertThat(contextSource.getPassword()).isEqualTo("ldap-password");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void templateExists() {
|
||||
this.contextRunner.withPropertyValues("spring.ldap.urls:ldap://localhost:389").run((context) -> {
|
||||
@@ -174,6 +194,37 @@ class LdapAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class ConnectionDetailsConfiguration {
|
||||
|
||||
@Bean
|
||||
LdapConnectionDetails ldapConnectionDetails() {
|
||||
return new LdapConnectionDetails() {
|
||||
|
||||
@Override
|
||||
public String[] getUrls() {
|
||||
return new String[] { "ldaps://ldap.example.com" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBase() {
|
||||
return "dc=base";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return "ldap-user";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return "ldap-password";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class PooledContextSourceConfig {
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.docker.compose.service.connection.ldap;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.boot.autoconfigure.ldap.LdapConnectionDetails;
|
||||
import org.springframework.boot.docker.compose.core.RunningService;
|
||||
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory;
|
||||
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource;
|
||||
|
||||
/**
|
||||
* {@link DockerComposeConnectionDetailsFactory} to create {@link LdapConnectionDetails}
|
||||
* for an {@code ldap} service.
|
||||
*
|
||||
* @author Philipp Kessler
|
||||
*/
|
||||
class OpenLdapDockerComposeConnectionDetailsFactory
|
||||
extends DockerComposeConnectionDetailsFactory<LdapConnectionDetails> {
|
||||
|
||||
protected OpenLdapDockerComposeConnectionDetailsFactory() {
|
||||
super("osixia/openldap");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LdapConnectionDetails getDockerComposeConnectionDetails(DockerComposeConnectionSource source) {
|
||||
return new OpenLdapDockerComposeConnectionDetails(source.getRunningService());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link LdapConnectionDetails} backed by an {@code openldap} {@link RunningService}.
|
||||
*/
|
||||
static class OpenLdapDockerComposeConnectionDetails extends DockerComposeConnectionDetails
|
||||
implements LdapConnectionDetails {
|
||||
|
||||
private final String[] urls;
|
||||
|
||||
private final String base;
|
||||
|
||||
private final String username;
|
||||
|
||||
private final String password;
|
||||
|
||||
OpenLdapDockerComposeConnectionDetails(RunningService service) {
|
||||
super(service);
|
||||
Map<String, String> env = service.env();
|
||||
boolean usesTls = Boolean.parseBoolean(env.getOrDefault("LDAP_TLS", "true"));
|
||||
String ldapPort = usesTls ? env.getOrDefault("LDAPS_PORT", "636") : env.getOrDefault("LDAP_PORT", "389");
|
||||
this.urls = new String[] { "%s://%s:%d".formatted(usesTls ? "ldaps" : "ldap", service.host(),
|
||||
service.ports().get(Integer.parseInt(ldapPort))) };
|
||||
if (env.containsKey("LDAP_BASE_DN")) {
|
||||
this.base = env.get("LDAP_BASE_DN");
|
||||
}
|
||||
else {
|
||||
this.base = Arrays.stream(env.getOrDefault("LDAP_DOMAIN", "example.org").split("\\."))
|
||||
.map("dc=%s"::formatted)
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
this.password = env.getOrDefault("LDAP_ADMIN_PASSWORD", "admin");
|
||||
this.username = "cn=admin,%s".formatted(this.base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getUrls() {
|
||||
return this.urls;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBase() {
|
||||
return this.base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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 Docker Compose LDAP service connections.
|
||||
*/
|
||||
package org.springframework.boot.docker.compose.service.connection.ldap;
|
||||
@@ -9,6 +9,7 @@ org.springframework.boot.docker.compose.service.connection.activemq.ActiveMQDock
|
||||
org.springframework.boot.docker.compose.service.connection.cassandra.CassandraDockerComposeConnectionDetailsFactory,\
|
||||
org.springframework.boot.docker.compose.service.connection.elasticsearch.ElasticsearchDockerComposeConnectionDetailsFactory,\
|
||||
org.springframework.boot.docker.compose.service.connection.flyway.JdbcAdaptingFlywayConnectionDetailsFactory,\
|
||||
org.springframework.boot.docker.compose.service.connection.ldap.OpenLdapDockerComposeConnectionDetailsFactory,\
|
||||
org.springframework.boot.docker.compose.service.connection.liquibase.JdbcAdaptingLiquibaseConnectionDetailsFactory,\
|
||||
org.springframework.boot.docker.compose.service.connection.mariadb.MariaDbJdbcDockerComposeConnectionDetailsFactory,\
|
||||
org.springframework.boot.docker.compose.service.connection.mariadb.MariaDbR2dbcDockerComposeConnectionDetailsFactory,\
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.docker.compose.service.connection.ldap;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.ldap.LdapConnectionDetails;
|
||||
import org.springframework.boot.docker.compose.service.connection.test.AbstractDockerComposeIntegrationTests;
|
||||
import org.springframework.boot.testsupport.testcontainers.DockerImageNames;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link OpenLdapDockerComposeConnectionDetailsFactory}.
|
||||
*
|
||||
* @author Philipp Kessler
|
||||
*/
|
||||
class OpenLdapDockerComposeConnectionDetailsFactoryIntegrationTests extends AbstractDockerComposeIntegrationTests {
|
||||
|
||||
OpenLdapDockerComposeConnectionDetailsFactoryIntegrationTests() {
|
||||
super("ldap-compose.yaml", DockerImageNames.openLdap());
|
||||
}
|
||||
|
||||
@Test
|
||||
void runCreatesConnectionDetails() {
|
||||
LdapConnectionDetails connectionDetails = run(LdapConnectionDetails.class);
|
||||
assertThat(connectionDetails.getUsername()).isEqualTo("cn=admin,dc=ldap,dc=example,dc=org");
|
||||
assertThat(connectionDetails.getPassword()).isEqualTo("somepassword");
|
||||
assertThat(connectionDetails.getBase()).isEqualTo("dc=ldap,dc=example,dc=org");
|
||||
assertThat(connectionDetails.getUrls()).hasSize(1);
|
||||
assertThat(connectionDetails.getUrls()[0]).startsWith("ldaps://");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
services:
|
||||
ldap:
|
||||
image: '{imageName}'
|
||||
environment:
|
||||
- 'LDAP_DOMAIN=ldap.example.org'
|
||||
- 'LDAP_ADMIN_PASSWORD=somepassword'
|
||||
- 'LDAP_TLS=true'
|
||||
hostname: ldap
|
||||
ports:
|
||||
- "389"
|
||||
- "636"
|
||||
@@ -81,6 +81,9 @@ The following service connections are currently supported:
|
||||
| `JdbcConnectionDetails`
|
||||
| Containers named "gvenzl/oracle-free", "gvenzl/oracle-xe", "mariadb", "mssql/server", "mysql", or "postgres"
|
||||
|
||||
| `LdapConnectionDetails`
|
||||
| Containers named "osixia/openldap"
|
||||
|
||||
| `MongoConnectionDetails`
|
||||
| Containers named "mongo"
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ dependencies {
|
||||
testImplementation("org.springframework:spring-r2dbc")
|
||||
testImplementation("org.springframework.amqp:spring-rabbit")
|
||||
testImplementation("org.springframework.kafka:spring-kafka")
|
||||
testImplementation("org.springframework.ldap:spring-ldap-core")
|
||||
testImplementation("org.springframework.pulsar:spring-pulsar")
|
||||
testImplementation("org.testcontainers:junit-jupiter")
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.testcontainers.service.connection.ldap;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.testcontainers.containers.Container;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import org.springframework.boot.autoconfigure.ldap.LdapConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
|
||||
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* {@link ContainerConnectionDetailsFactory} to create {@link LdapConnectionDetails} from
|
||||
* a {@link ServiceConnection @ServiceConnection}-annotated {@link GenericContainer} using
|
||||
* the {@code "osixia/openldap"} image.
|
||||
*
|
||||
* @author Philipp Kessler
|
||||
*/
|
||||
class OpenLdapContainerConnectionDetailsFactory
|
||||
extends ContainerConnectionDetailsFactory<Container<?>, LdapConnectionDetails> {
|
||||
|
||||
OpenLdapContainerConnectionDetailsFactory() {
|
||||
super("osixia/openldap");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LdapConnectionDetails getContainerConnectionDetails(ContainerConnectionSource<Container<?>> source) {
|
||||
return new OpenLdapContainerConnectionDetails(source);
|
||||
}
|
||||
|
||||
private static final class OpenLdapContainerConnectionDetails extends ContainerConnectionDetails<Container<?>>
|
||||
implements LdapConnectionDetails {
|
||||
|
||||
private OpenLdapContainerConnectionDetails(ContainerConnectionSource<Container<?>> source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getUrls() {
|
||||
Map<String, String> env = getContainer().getEnvMap();
|
||||
boolean usesTls = Boolean.parseBoolean(env.getOrDefault("LDAP_TLS", "true"));
|
||||
String ldapPort = usesTls ? env.getOrDefault("LDAPS_PORT", "636") : env.getOrDefault("LDAP_PORT", "389");
|
||||
return new String[] { "%s://%s:%d".formatted(usesTls ? "ldaps" : "ldap", getContainer().getHost(),
|
||||
getContainer().getMappedPort(Integer.parseInt(ldapPort))) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBase() {
|
||||
Map<String, String> env = getContainer().getEnvMap();
|
||||
if (env.containsKey("LDAP_BASE_DN")) {
|
||||
return env.get("LDAP_BASE_DN");
|
||||
}
|
||||
return Arrays.stream(env.getOrDefault("LDAP_DOMAIN", "example.org").split("\\."))
|
||||
.map("dc=%s"::formatted)
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return "cn=admin,%s".formatted(getBase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return getContainer().getEnvMap().getOrDefault("LDAP_ADMIN_PASSWORD", "admin");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for testcontainers Ldap service connections.
|
||||
*/
|
||||
package org.springframework.boot.testcontainers.service.connection.ldap;
|
||||
@@ -16,6 +16,7 @@ org.springframework.boot.testcontainers.service.connection.flyway.FlywayContaine
|
||||
org.springframework.boot.testcontainers.service.connection.elasticsearch.ElasticsearchContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.testcontainers.service.connection.jdbc.JdbcContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.testcontainers.service.connection.kafka.KafkaContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.testcontainers.service.connection.ldap.OpenLdapContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.testcontainers.service.connection.liquibase.LiquibaseContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.testcontainers.service.connection.mongo.MongoContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.testcontainers.service.connection.neo4j.Neo4jContainerConnectionDetailsFactory,\
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.testcontainers.service.connection.ldap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
import org.springframework.boot.testsupport.testcontainers.OpenLdapContainer;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.ldap.core.AttributesMapper;
|
||||
import org.springframework.ldap.core.LdapTemplate;
|
||||
import org.springframework.ldap.query.LdapQueryBuilder;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link OpenLdapContainerConnectionDetailsFactory}.
|
||||
*
|
||||
* @author Philipp Kessler
|
||||
*/
|
||||
@SpringJUnitConfig
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class OpenLdapContainerConnectionDetailsFactoryIntegrationTests {
|
||||
|
||||
@Container
|
||||
@ServiceConnection
|
||||
static final OpenLdapContainer openLdap = new OpenLdapContainer().withEnv("LDAP_TLS", "false");
|
||||
|
||||
@Autowired
|
||||
private LdapTemplate ldapTemplate;
|
||||
|
||||
@Test
|
||||
void connectionCanBeMadeToLdapContainer() {
|
||||
List<String> cn = this.ldapTemplate.search(LdapQueryBuilder.query().where("objectclass").is("dcObject"),
|
||||
(AttributesMapper<String>) (attributes) -> attributes.get("dc").get().toString());
|
||||
assertThat(cn).hasSize(1);
|
||||
assertThat(cn.get(0)).isEqualTo("example");
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ImportAutoConfiguration({ LdapAutoConfiguration.class })
|
||||
static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -48,6 +48,8 @@ public final class DockerImageNames {
|
||||
|
||||
private static final String NEO4J_VERSION = "4.4.11";
|
||||
|
||||
private static final String OPEN_LDAP_VERSION = "1.5.0";
|
||||
|
||||
private static final String ORACLE_FREE_VERSION = "23.3-slim";
|
||||
|
||||
private static final String ORACLE_XE_VERSION = "18.4.0-slim";
|
||||
@@ -119,6 +121,14 @@ public final class DockerImageNames {
|
||||
return DockerImageName.parse("confluentinc/cp-kafka").withTag(KAFKA_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link DockerImageName} suitable for running OpenLDAP.
|
||||
* @return a docker image name for running OpenLDAP
|
||||
*/
|
||||
public static DockerImageName openLdap() {
|
||||
return DockerImageName.parse("osixia/openldap").withTag(OPEN_LDAP_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link DockerImageName} suitable for running MariaDB.
|
||||
* @return a docker image name for running MariaDB
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.testsupport.testcontainers;
|
||||
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
/**
|
||||
* A {@link GenericContainer} for OpenLDAP.
|
||||
*
|
||||
* @author Philipp Kessler
|
||||
*/
|
||||
public class OpenLdapContainer extends GenericContainer<OpenLdapContainer> {
|
||||
|
||||
private static final int DEFAULT_LDAP_PORT = 389;
|
||||
|
||||
public OpenLdapContainer() {
|
||||
super(DockerImageNames.openLdap());
|
||||
addExposedPorts(DEFAULT_LDAP_PORT);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user