Question

Here there is a spring-security example, ldap-xml, which runs a ldap server and imports a LDIF file for testing:

https://github.com/spring-projects/spring-security/blob/master/samples/ldap-xml/src/main/webapp/WEB-INF/applicationContext-security.xml

[...]
    <s:ldap-server ldif="classpath:users.ldif" port="33389"/>

    <s:authentication-manager>
        <s:ldap-authentication-provider
            group-search-filter="member={0}"
            group-search-base="ou=groups"
            user-search-base="ou=people"
            user-search-filter="uid={0}"
        />
        <s:authentication-provider ref='secondLdapProvider' />
    </s:authentication-manager>
[...]

https://github.com/spring-projects/spring-security/blob/master/samples/ldap-xml/src/main/webapp/WEB-INF/classes/users.ldif

[...]
dn: uid=rod,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Rod Johnson
sn: Johnson
uid: rod
userPassword: koala
[...]

I need to modify this working example, in where the user-search-criteria is based on sAMAccountName instead of uid. I modify the users.ldif as follows:

[...]
dn: cn=rod,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Rod Johnson
sn: Johnson
sAMAccountName: rod
userPassword: koala
[...]

but apacheds shows a warning when importing users.ldif:

OID for name 'samaccountname' was not found within the OID registry

It seems that I need to add this new attribute, sAMAccountName, by modifing the LDAP schema. how to do that in the ldap-xml example?

In this gist example they modify the schema using "changetype: add". however adding this in users.ldif results in an error We cannot have entries when reading a file which already contains changes. In the gist example, they mention to update the schema running the ldifdecommand. How should I modify the ldap-xml project to do this?

How I need to modify the ldap-xml project, so that my users.ldif can contain a sAMAccountName attribute?

Was it helpful?

Solution

Add the following (it's the minimal fragment of Microsoft's schema that contains sAMAccountName) at the beginning of users.ldif file:

dn: cn=microsoft, ou=schema
objectclass: metaSchema
objectclass: top
cn: microsoft

dn: ou=attributetypes, cn=microsoft, ou=schema
objectclass: organizationalUnit
objectclass: top
ou: attributetypes

dn: m-oid=1.2.840.113556.1.4.221, ou=attributetypes, cn=microsoft, ou=schema
objectclass: metaAttributeType
objectclass: metaTop
objectclass: top
m-oid: 1.2.840.113556.1.4.221
m-name: sAMAccountName
m-equality: caseIgnoreMatch
m-syntax: 1.3.6.1.4.1.1466.115.121.1.15
m-singleValue: TRUE

dn: ou=objectclasses, cn=microsoft, ou=schema
objectclass: organizationalUnit
objectclass: top
ou: objectClasses

dn: m-oid=1.2.840.113556.1.5.6, ou=objectclasses, cn=microsoft, ou=schema
objectclass: metaObjectClass
objectclass: metaTop
objectclass: top
m-oid: 1.2.840.113556.1.5.6
m-name: securityPrincipal
m-supObjectClass: top
m-typeObjectClass: AUXILIARY
m-must: sAMAccountName

[rest of users.ldif]

Now add new objectClass to person entries:

[...]
dn: cn=rod,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
objectclass: securityPrincipal   <--- new objectClass
cn: Rod Johnson
sn: Johnson
sAMAccountName: rod
userPassword: koala
[...]

It's not enough to have new entries. ApacheDS' configuration in Spring Security has disabled schema interceptor, so new schema entries are not created by default. We can turn it on by creating BeanPostProcessor that fixes this:

package com.example.test.spring;

import java.util.List;

import org.apache.directory.server.core.interceptor.Interceptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.security.ldap.server.ApacheDSContainer;

import static org.springframework.util.CollectionUtils.isEmpty;

public class ApacheDSContainerConfigurer implements BeanPostProcessor {

    private List<Interceptor> interceptors;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof ApacheDSContainer){
            ApacheDSContainer dsContainer = ((ApacheDSContainer) bean);
            setInterceptorsIfPresent(dsContainer);
        }
        return bean;
    }

    private void setInterceptorsIfPresent(ApacheDSContainer container) {
        if (!isEmpty(interceptors)) {
            container.getService().setInterceptors(interceptors);
        }
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    public void setInterceptors(List<Interceptor> interceptors) {
        this.interceptors = interceptors;
    }

}

We have to register and configure bean in application context:

<bean class="com.example.test.spring.ApacheDSContainerConfigurer">
    <property name="interceptors">
        <list>
            <bean class="org.apache.directory.server.core.normalization.NormalizationInterceptor"/>
            <bean class="org.apache.directory.server.core.authn.AuthenticationInterceptor"/>
            <bean class="org.apache.directory.server.core.referral.ReferralInterceptor"/>
            <!--<bean class="org.apache.directory.server.core.authz.AciAuthorizationInterceptor"/>-->
            <!--<bean class="org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor"/>-->
            <bean class="org.apache.directory.server.core.exception.ExceptionInterceptor"/>
            <!--<bean class="org.apache.directory.server.core.changelog.ChangeLogInterceptor"/>-->
            <bean class="org.apache.directory.server.core.operational.OperationalAttributeInterceptor"/>
            <bean class="org.apache.directory.server.core.schema.SchemaInterceptor"/>
            <bean class="org.apache.directory.server.core.subtree.SubentryInterceptor"/>
            <!--<bean class="org.apache.directory.server.core.collective.CollectiveAttributeInterceptor"/>-->
            <!--<bean class="org.apache.directory.server.core.event.EventInterceptor"/>-->
            <!--<bean class="org.apache.directory.server.core.trigger.TriggerInterceptor"/>-->
            <!--<bean class="org.apache.directory.server.core.journal.JournalInterceptor"/>-->
        </list>
    </property>
</bean>

It should be working now.

OTHER TIPS

I also had the same problem and tried the solution given by @Karol, but it didn't work for me. I was using the LdapTemplate provided by Spring Framework for accessing the Ldap Server.

The problem was that the embedded ldap server (it was ApacheDS in my case) doesn't support certain attributes like sAMAccountName. As a solution for testing, I made these attribute names in my code configurable from properties file and replaced the attribute names to the names available in ApacheDS embedded server in test environment's properties file. And it worked like a charm.

For example, in actual environment the search by LdapTemplate is based on sAMAccountName attribute, but in test environment the search happens with uid attribute.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top