ApacheLDAPAndActiveDirectory

April 26, 2008


Recently at my gig, we made the switch to Subversion (just in time to find all the cool kids had vacated the premises for the latest hip club). I got wrapped up in setting the thing up, and when it came to authentication, our IT dudes reasonably requested we use the company's Active Directory setup.

It didn't sound too difficult, but turns out getting Apache's LDAP mod to talk to Active Directory can require a bit of arbitration.

Apache's doc for mod_authnz_ldap (2.2) covers the basic directives:
AuthLDAPBindDN
AuthLDAPBindPassword
AuthLDAPUrl
The first two are needed if you can't anonymously bind to the LDAP database (which you can't by default with Active Directory). The URL has a special format, detailed in RFC 2255. One destined for Active Directory probably looks like this:

ldap://adserver.fooco.com:389/DC=fooco,DC=com?sAMAccountName?sub?(objectClass=*)

This essentially means, “search the ldap (ldap://) server on adserver.fooco.com, port 389, starting at the root (DC=fooco,DC=com), comparing the search term against the value in the sAMAccountName attribute, recursively (sub), querying all objectClass types (objectClass=*).

(The SAM Account Name is essentially the user's domain login name. More details here. It will be unique within a domain. If your Active Directory has more than one domain in it, and both domains have the same SAM Account Name in it -- well, I guess you'll need to get a bit inventive with your LDAP searches. The search will return more than one result and Apache's LDAP mod won't be able to authenticate the login).

And we've now hit our first hiccup: referrals.

This long thread helped get me on the right track. This Technet doc (search for the LDAP Referrals section) explains:
When a requested object exists in the directory but is not present on the contacted domain controller, resolution of the object name depends on information that is stored on that domain controller about how the directory is partitioned. In a partitioned directory, by definition, the entire directory is not always available on any one domain controller.

... When an operation in Active Directory requires action on objects that might exist in the forest but that are not located in the particular domain that is stored on a domain controller, that domain controller must send the client a message that describes where to continue this action — that is, the client is “referred” to a domain controller that is presumed to hold the requested object.

... Active Directory returns referrals in accordance with RFC 2251.
(Other text I didn't quote in that article indicates that Active Directory will only respond with referrals when necessary. In my recent (and limited) experience, it seemed to always return referrals with a root search, though it seems logical to always be necessary with a root search).

Apparently, Apache's mod won't follow the referrals. A bug report has been filed on the problem, with a fix already committed that'll be there in the next release. But there's good news in the meantime.

First off, if you don't need a directory-wide search, you can restrict your search URL to a specific OU or other path, and referrals won't be needed. For example, if you only need to authenticate against users in an OU named bar, change the URL to:

ldap://adserver.fooco.com:389/OU=bar,DC=fooco,DC=com?sAMAccountName?sub?(objectClass=*)


If you do need a directory-wide search, you can use Active Directory's Global Catalog. Global catalogs are typically hosted on port 3268. From the prior Technet article, search for “Global Catalog Searches”:
The global catalog enables searches for Active Directory objects in any domain in the forest, without the need for subordinate referrals. Users can find an object of interest quickly without having to know which domain holds the object.
NOTE: I tried going to the global catalog early on in my configuration attempts and still had problems. I didn't find out why, but I did come up with a workaround - switching to another AD server. Use ipconfig to show your DNS servers, and ping the ip addresses - those will probably be AD servers on your network.

[I intend to cover some more material in this article, but I've got to sign off for tonight. Coming topics: using mod_authn_alias to search multiple directories, or multiple query locations in the same directory, mixing LDAP authentication with other types, and restricting Directory entries to certain ldap groups, etc.]

tags: ComputersAndTechnology