Endie
Endie

Reputation: 63

Creating new users with Spring Data LdapRepository fails with LDAP error code 32

I am attempting to use Spring Data and the LdapRepository api to read, update and create user data in Ldap. I have been able to read and to update successfully, but whenever I attempt to insert a new record I get this error:

2017-07-25 17:31:01.966 ERROR 14404 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; 
nested exception is org.springframework.ldap.NameNotFoundException: 
[LDAP: error code 32 - The search base entry '[email protected],ou=people,ou=myou,dc=bar,dc=foo' does not exist]; 
nested exception is javax.naming.NameNotFoundException: 
[LDAP: error code 32 - The search base entry '[email protected],ou=people,ou=myou,dc=bar,dc=foo' does not exist]; remaining name '[email protected]'] 
with root cause
javax.naming.NameNotFoundException: [LDAP: error code 32 - The search base entry '[email protected],ou=people,ou=myou,dc=bar,dc=foo' does not exist]

My application.properties is:

user-api.ldap.contextSource.url=ldap://server.address.com:1389
user-api.ldap.contextSource.userDn=cn=manager role
user-api.ldap.contextSource.password=apasswordwashere
user-api.ldap.contextSource.base=ou=people,ou=myou,dc=bar,dc=foo

My repo interface, LdapUserRepository.java:

public interface LdapUserRepository extends LdapRepository<LdapUser>{

   LdapUser findByCn(String cn);

   LdapUser findBySn(String sn);

   LdapUser save(LdapUser ldapUser);
}

I get the same response whether or not I explicitly expose the save method.

My configuration is done in LdapConfiguration.java:

@Configuration
@EnableLdapRepositories(basePackages = "foo.bar.userapi.dao.ldap", ldapTemplateRef="userLdapTemplate")
public class LdapConfiguration {

    @Autowired
    Environment env;

    @Bean
    public LdapContextSource contextSource () {
        LdapContextSource contextSource= new LdapContextSource();
        contextSource.setUrl(env.getRequiredProperty("user-api.ldap.contextSource.url"));
        contextSource.setBase(env.getRequiredProperty("user-api.ldap.contextSource.base"));
        contextSource.setUserDn(env.getRequiredProperty("user-api.ldap.contextSource.userDn"));
        contextSource.setPassword(env.getRequiredProperty("user-api.ldap.contextSource.password"));
        return contextSource;
    }

    @Bean(name="userLdapTemplate")
    public LdapTemplate ldapTemplate() {
        return new LdapTemplate(contextSource());       
    }

}

And my test routine:

public void test() {
   LdapUser ldapUser =  new LdapUser();

   ldapUser.setCn("198777777");
   ldapUser.setCountry("United States");
   ldapUser.setGivenName("Hepsibah");
   ldapUser.setIsActive("true");
   ldapUser.setSn("Testerson91");
   ldapUser.setStatus("active");
   ldapUser.setUid(LdapUtils.newLdapName("[email protected]"));
   ldapUser.setUserModifyTimestamp("20160222145439Z");
   ldapUser.setUserPassword("Password-12345");
   ldapUser = ldapUserRepository.save(ldapUser);
}

To stress, the configuration works for everything except inserts, since if I do something like this, it works:

   public void test2() {
          LdapUser ldapUser =  ldapUserRepository.findBySn("Testerson");
          if ( ldapUser != null) {
                 System.out.println(ldapUser.getUid().toString());
                 System.out.println("result: " + ldapUser.toString());

                 ldapUser.setSn("Testerson2");
                 ldapUser.setUserPassword("Password-12345!");
                 ldapUser = ldapUserRepository.save(ldapUser);

                 ldapUser = ldapUserRepository.findBySn("Testerson2");
                 if ( ldapUser != null) {
                       System.out.println("result: " + ldapUser.toString());
                 }
          }
   }

I suspect that the answer may be to do with Ldap error code 32 while adding user to ldap but I am not explictly adding the dn during the save operation, and an update operation works fine.

Retrieving a record, changing the uid value and saving it gives the same error. Retrieving a record and inspecting the uid shows only the "[email protected]" part and not the "ou=people,ou=myou,dc=bar,dc=foo" part.

Upvotes: 6

Views: 3411

Answers (1)

turboemu
turboemu

Reputation: 184

Assuming the default implementation is being used (SimpleLdapRepository - you'll get this if you haven't implemented the repository interface yourself) then the problem is occurring when the SimpleLdapRepository tries to determine whether it should 'save' or 'update' your entity. From here that code in the SimpleLdapRepository looks like this:

 @Override
 public <S extends T> S More ...save(S entity) {
     Assert.notNull(entity, "Entity must not be null");
     Name declaredId = odm.getId(entity);

     if (isNew(entity, declaredId)) {
         ldapOperations.create(entity);
     } else {
         ldapOperations.update(entity);
     }

     return entity;
 }

To get the the error you are seeing it is likely your entity is not being determined to be new, this an update is performed which fails when the entity is found not to exist and can't be updated.

The isNew() method looks like this:

     private <S extends T> boolean More ...isNew(S entity, Name id) {
     if (entity instanceof Persistable) {
         Persistable<?> persistable = (Persistable<?>) entity;
         return persistable.isNew();
     } else {
         return id == null;
     }
 }

In your example it looks like you are required to set the ID. So the other option would be to implement the Persistable interface and the isNew() method to return whether your entity is new or not. If your entity is determined to be new (you can call e.g. ldapUser.setNew(true); before saving), it will be saved rather than updated.

Upvotes: 7

Related Questions