Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpEL not supported in Spring annotation @Entry.base

Tags:

I use Spring Data LDAP and Spring Boot provides out of the box support for an embedded UnboundID server. However, when I use Spring Data LDAP's @Entry annotation, I need to specify a different base in the annotation based on whether I'm using the embedded UnboundID LDAP server, or a remote Active Directory server.

I was attempting to do this with SpEL and profile-based properties by specifying:

@Entry(base = "${ldap.person.base}", ...)

Then I have an application.propreties with ldap.person.base=OU=AD Person Base and an application-embedded.properties with ldap.person.base=OU=Embedded Person Base.

However, the @Entry annotation does not seem to support SpEL evaluation:

javax.naming.InvalidNameException: Invalid name: ${ldap.person.base}

There is an open issue in Spring LDAP to add support for this, but is there any workaround or some other way I can accomplish this until it is supported in Spring LDAP?

like image 876
Andrew Mairose Avatar asked May 04 '17 14:05

Andrew Mairose


2 Answers

I'm not sure I'm following here, but assuming you're using the LDAP auto-configuration in Spring Boot, is it not enough to set the property spring.ldap.base to one or the other (OU=AD Person Base or OU=Embedded Person Base) based on the profile you're using?

Both EmbeddedLdapAutoConfiguration and LdapAutoConfiguration use an LdapProperties object to set various attributes on the LdapContextSource during bean creation, including its base. As far as I can tell, you won't have to define it for each @Entry in your codebase if LdapContextSource.base is set.

If you're not using the auto-configuration, and if I'm correct in my assumptions, you should still be able to create your own LdapContextSource bean and set its base to the desired value based on a Spring property.

like image 90
Thomas Kåsene Avatar answered Sep 23 '22 10:09

Thomas Kåsene


Turns out the reason I needed a different base in the first place is because Spring was not setting the base on the ContextSource.

When you let Spring Boot autoconfigure the embedded LDAP server, it creates a ContextSource as such in EmbeddedLdapAutoConfiguration:

@Bean
@DependsOn("directoryServer")
@ConditionalOnMissingBean
public ContextSource ldapContextSource() {
    LdapContextSource source = new LdapContextSource();
    if (hasCredentials(this.embeddedProperties.getCredential())) {
        source.setUserDn(this.embeddedProperties.getCredential().getUsername());
        source.setPassword(this.embeddedProperties.getCredential().getPassword());
    }
    source.setUrls(this.properties.determineUrls(this.environment));
    return source;
}

As you can see, nowhere in there does it call source.setBase(). So to solve this, I added a configuration file with @Profile("embedded") and manually created a ContextSource where I set the base myself (I leave off the credentials part because I don't use credentials for the embedded server):

@Configuration
@Profile("embedded")
@EnableConfigurationProperties({ LdapProperties.class })
public class EmbeddedLdapConfig {

    private final Environment environment;
    private final LdapProperties properties;

    public EmbeddedLdapConfig(final Environment environment, final 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;
    }
}

Now, I can leave the value of the base attribute in my @Entry the same for both the Active Directory server and the embedded UnboundID server and it works properly.

like image 41
Andrew Mairose Avatar answered Sep 25 '22 10:09

Andrew Mairose