I’m still shaky on the details of whether some of the LDAP lessons learned were specific to the way our Active Directory is configured, or if these are universal. Either way, they are worth documenting since many of them took a great deal of time to discover the exact cause given the very limited access to LDAP logs I had (i.e. none), and very little error messages returned from LDAP.
Import certs to your windows machine instead of JDK. I wasted a great deal of time trying to get the certs working with my JDK because that was the original way I was told to implement the SSL certs. After bashing my head against this wall, it became evident that there had to be a way that some of our Virtual Machines are communicating with the AD server, which had absolutely nothing to do with Java.
Simply download the cert to your local machine (assuming Windows), right click on the file, and install. There are a few different options for the install, so search the web for your situation.
ADSI Edit was difficult to get up and running, but worked fine until we switched to a new LDAP system that required SSL ports. I battled with ADSI for a while trying to get it to work with the secure ports. I thought I had the connection details wrong, or the system was configured wrong, but in the end SSL with ADSI Edit has a known issue when using SSL and does not work with secure ports.
Instead, I opted to use the free LDAP Admin, which overall I like much, much better then ADSI Edit. It allows for multiple connections to various LDAP servers at the same time, and values can be changed in-line, as opposed to a pop-up like ADSI Edit.
- 636 – requires SSL certs to be imported to JVM or the machine, similar to 3269
- 389 – Global Catalog (GC), which can create users, but WITHOUT passwords and userAccountControl set
- 3269 – secure connection, users can be created as desired
- 3268 – non-secure connection
Attributes & Errors
Attribute errors were the toughest to track down. When creating a user, there is a lot going on in the background within LDAP that I am not privy to. So when an InvalidAttributeValueException occurs, it was painful to nail down which Attribute was the culprit.
Having JUnit tests on my local machine made this process much, much easier to find the offending attribute, but it was still painful when there are scores of attributes.
LDAP much prefers null values verses empty Strings (at least in our environment)
When I tried to assign an attribute to an empty String, I would receive the error below. Simply assign the value to null instead.
2014-08-25 14:32:39,015 [INFO ] [WebContainer : 4] com.company.ldap.AppsLdapDao.createUser(99) – bind failed: org.springframework.ldap.InvalidAttributeValueException: [LDAP: error code 21 – 00000057: LdapErr: DSID-0C090B38, comment: Error in attribute conversion operation, data 0, vecex00]; nested exception is javax.naming.directory.InvalidAttributeValueException: [LDAP: error code 21 – 00000057: LdapErr: DSID-0C090B38, comment: Error in attribute conversion operation, data 0, vecex00]; Remaining name: ‘CN=userTest,OU=TEST_App,DC=Applications,DC=Company,DC=Com’
- required to be 512, or else it defaults to 536, which locks the users out
- setting this attribute requires SSL
userID is too long, and was limited to 20 chars
2014-07-09 09:56:19,996 [DEBUG] [main] com.company.ldap.AppsLdapDao.createUser(91) – bind failed: org.springframework.ldap.UncategorizedLdapException: Uncategorized exception occured during LDAP processing; nested exception is javax.naming.NamingException: [LDAP: error code 80 – 00000523: SysErr: DSID-031A0FB6, problem 22 (Invalid argument), data 080 LDAP_OTHER
Indicates an unknown error condition. This is the default value for NDS error codes which do not map to other LDAP error codes.
passwords – must be at least 7 characters long
This was difficult to find because of the way it was reported: passwords work when creating certain users, but not others. All of my JUnit tests worked fine for this scenario, and I could not reproduce their error. The developer using my RESTful service then said that they were using the usernames as passwords, and I instantly knew of a scenario I did not try: a very short password.
2014-08-26 11:48:06,975 [INFO ] [WebContainer : 8] com.company.ldap.AppsLdapDao.createUser(99) – bind failed: org.springframework.ldap.OperationNotSupportedException: [LDAP: error code 53 – 0000052D: SvcErr: DSID-031A0FC0, problem 5003 (WILL_NOT_PERFORM), data 0 x00]; nested exception is javax.naming.OperationNotSupportedException: [LDAP: error code 53 – 0000052D: SvcErr: DSID-031A0FC0, problem 5003 (WILL_NOT_PERFORM), data 0 x00]; Remaining name: ‘CN=userTest,OU=TEST_App,DC=Applications,DC=Company,DC=Com’
Hope this helps someone else get beyond some basic LDAP development issues.