Here there is a spring-security example, ldap-xml, which runs a ldap server and imports a LDIF file for testing:
[...]
<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>
[...]
[...]
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 ldifde
command. 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?
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.