I have a weird behaviour of Spring Data Ldap and was wondering how I can fight it.
From the looks of it, it seems that the base
information is either lost or handled differently when I use a "proper" LDAP server and the embedded version.
The embedded version should be used for some of my integration tests. But what works perfectly fine when I configure my LDAP server like so:
spring:
ldap:
urls: ldap://localhost:389
base: dc=e-mehlbox,dc=eu
username: cn=admin,dc=e-mehlbox,dc=eu
password: root
in my application.yml. But once I set up the embedded server, my searches fail:
spring:
ldap:
urls: ldap://localhost:9321
base: dc=e-mehlbox,dc=eu
username: uid=admin
password: secret
embedded:
base-dn: dc=e-mehlbox,dc=eu
credential:
username: uid=admin
password: secret
ldif: classpath:test-schema.ldif
port: 9321
validation:
enabled: false
Enabling debugging, it shows the missing base DN. Here are the corresponding lines for the working configuration agains a "real" LDAP server:
2018-01-10 18:06:55.296 DEBUG 23275 --- [ main] o.s.ldap.core.LdapTemplate : Searching - base=ou=internal,ou=Users, finalFilter=(&(&(objectclass=inetOrgPerson)(objectclass=organizationalPerson)(objectclass=person)(objectclass=qmailUser))(uid=big.bird)), scope=javax.naming.directory.SearchControls@6a013bdd
2018-01-10 18:06:55.311 DEBUG 23275 --- [ main] o.s.l.c.support.AbstractContextSource : Got Ldap context on server 'ldap://localhost:389/dc=e-mehlbox,dc=eu'
The interesting bit is the Ldap context, having the base in it.
And this the output when I switch to the embedded LDAP:
2018-01-10 18:08:42.836 DEBUG 23569 --- [ main] o.s.ldap.core.LdapTemplate : Searching - base=ou=internal,ou=Users, finalFilter=(&(&(objectclass=inetOrgPerson)(objectclass=organizationalPerson)(objectclass=person)(objectclass=qmailUser))(uid=big.bird)), scope=javax.naming.directory.SearchControls@55202ba6
2018-01-10 18:08:42.871 DEBUG 23569 --- [ main] o.s.l.c.support.AbstractContextSource : Got Ldap context on server 'ldap://localhost:9321'
I am a bit lost, as I can not find any other configuration options to set the base DN.
Some details of my project:
Right now, I am using the following Spring Data LDAP related dependencies (my project is Gradle driven):
compile (
"org.springframework.boot:spring-boot-starter-data-ldap:1.5.9.RELEASE",
"org.springframework.data:spring-data-ldap:1.0.9.RELEASE"
)
testCompile (
"org.springframework.ldap:spring-ldap-test:2.3.2.RELEASE",
"com.unboundid:unboundid-ldapsdk:4.0.3"
)
And here is one of my entity classes:
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@EqualsAndHashCode(doNotUseGetters = true)
@ToString(doNotUseGetters = true)
@Entry(
objectClasses = {"inetOrgPerson", "organizationalPerson", "person", "qmailUser"},
base = "ou=internal,ou=Users")
public class User implements Serializable {
@Id
private Name dn;
@Attribute(name = "entryUuid", readonly = true)
private String entryUuid;
@Attribute(name = "uid")
private String username;
@Attribute(name = "userPassword")
private byte[] password;
@Attribute(name = "mail")
private String internalMailAddress;
@Attribute(name = "mailAlternateAddress")
private List<String> mailAddresses;
@Attribute(name = "displayName")
private String displayName;
@Attribute(name = "accountStatus")
private String status;
@Attribute(name = "givenName")
private String firstName;
@Attribute(name = "sn")
private String lastName;
@Attribute(name = "mailMessageStore")
private String mailboxHome;
}
Any ideas? Is this a bug or just me not seeing the obvious?
Thanks to @vdubus and this question, I got it working.
It seems like the embedded LDAP server version does not set the configured base DN (see the other SO question). But adding the following class to my project fixes this:
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.ldap.LdapProperties;
import org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.support.LdapContextSource;
@Configuration
@EnableConfigurationProperties({LdapProperties.class, EmbeddedLdapProperties.class})
@ConditionalOnClass(InMemoryDirectoryServer.class)
public class EmbeddedLdapConf {
private final Environment environment;
private final LdapProperties properties;
public EmbeddedLdapConf(Environment environment, LdapProperties properties) {
this.environment = environment;
this.properties = properties;
}
@Bean
@DependsOn("directoryServer")
public ContextSource ldapContextSource() {
final LdapContextSource source = new LdapContextSource();
source.setUrls(this.properties.determineUrls(this.environment));
source.setBase(this.properties.getBase());
return source;
}
}