RawStuff

April 16, 2008
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The prior URL

If you only need to authenticate against a specific OU or container, than the following AuthLDAPURL should be fine:

AuthLDAPURL "ldap://eiadserver1.einstruction.com:389/OU=AppDev,DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"


(See http://www.faqs.org/rfcs/rfc2255.html for a breakdown of the ldap url)

If you need to authenticate against different OUs, then there are two options. Ideally, simply changing the ldap url to work from the root should work:

AuthLDAPURL "ldap://eiadserver1.einstruction.com:389/DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"


However, against Active Directory this doesn't seem to work, because in addition to the search results, it will also return referrals to other directory partitions, and Apache can't grok these or somesuch. A bug has been filed for this, and the report includes a patch.

But, if your Active Directory has a Global Directory configured, typically on port 3268, then you might be able to get the query you need to work:

AuthLDAPURL "ldap://eiadserver1.einstruction.com:3268/DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"


(This option threw me for a bit, though, because while both eiserver8 and eiadserver1 have ports 389 and 3268 open, neither port seems to work for root searches on eiserver8, and both ports seem to work on eiadserver1)

So ... with that said, here's a starter config that should get the job done:

<Directory />
Options FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all

AuthType Basic
AuthName "eInstruction Domain"
AuthBasicProvider ldap

AuthLDAPBindDN "CN=Test Test,OU=QA,DC=einstruction,DC=com"
AuthLDAPBindPassword ****
AuthLDAPURL "ldap://eiadserver1.einstruction.com:3268/DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"

Require valid-user
</Directory>


Tangent: I got it to work against port 389, querying from the root, what's wrong with that?
I got it to work on port 389, eiadserver1, for logins in two Denton locale groups, eInstruction domain - but it wouldn't authenticate anyone in the Scottsdale domain. This goes back to the comment from the 2.3/2.4 Apache docs: “Querying the Global Catalog allows all the domains to be queried in a single query, without the query spanning servers over potentially slow links.” So, perhaps you don't need to use the Global Catalog if you don't have multiple domains -- although I still had no success querying the root on one of the ldap servers.


To Do:
- Multiple ldaps
- limiting to groups (alias method and the require ldap-group
- mixing authentication types



The full snippet, hopefully will remind us:

<AuthnProviderAlias ldap ldap-appdev>
# Active Directory requires an authenticating DN to access records
AuthLDAPBindDN "CN=Test Test,OU=QA,DC=einstruction,DC=com"

# This is the password for the AuthLDAPBindDN user in Active Directory
AuthLDAPBindPassword test

# The LDAP query URL
## Softerra LDAP Browser 2.5.3 was very handy in figuring this path out... MS Active Directory MMC plugin
## doesn't give you this sort of URL. sysinternals also has an AD Explorer
AuthLDAPURL "ldap://eiadserver1.einstruction.com:3268/OU=AppDev,DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"
</AuthnProviderAlias>

<AuthnProviderAlias ldap ldap-qa>
AuthLDAPBindDN "CN=Test Test,OU=QA,DC=einstruction,DC=com"
AuthLDAPBindPassword test
AuthLDAPURL "ldap://eiadserver1.einstruction.com:389/OU=QA,DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"
</AuthnProviderAlias>

<AuthnProviderAlias ldap ldap-scottsdale>
AuthLDAPBindDN "CN=LDAP test,CN=Users,DC=scottsdale,DC=einstruction,DC=com"
AuthLDAPBindPassword Sc0ttsdale
AuthLDAPURL "ldap://eiadserver1.einstruction.com:3268/CN=Users,DC=scottsdale,DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"
</AuthnProviderAlias>

#
# Each directory to which Apache has access can be configured with respect
# to which services and features are allowed and/or disabled in that
# directory (and its subdirectories).
#
# First, we configure the "default" to be a very restrictive set of
# features.
#
<Directory />
Options FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all

# Do basic password authentication in the clear (but we're covered in this case with SSL)
AuthType Basic

# The name of the protected area or "realm"
AuthName "eInstruction Domain"

#AuthBasicProvider file ldap-appdev ldap-qa ldap-scottsdale
AuthBasicProvider file ldap

AuthLDAPBindDN "CN=Test Test,OU=QA,DC=einstruction,DC=com"
AuthLDAPBindPassword test
AuthLDAPURL "ldap://eiadserver1.einstruction.com:3268/DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"


# _______File__________ #

AuthBasicAuthoritative Off

AuthUserFile "C:/Program Files/Apache Software Foundation/Apache2.2/conf/users"

# _______LDAP__________ #

AuthzLDAPAuthoritative off

Require valid-user
</Directory>

<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/cps">
AuthGroupFile "C:/Program Files/Apache Software Foundation/Apache2.2/conf/groups"
AuthzGroupFileAuthoritative off
Require group cps

AuthLDAPBindDN "CN=Test Test,OU=QA,DC=einstruction,DC=com"
AuthLDAPBindPassword test
AuthLDAPURL "ldap://eiadserver1.einstruction.com:3268/DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"
AuthzLDAPAuthoritative off
#Require valid-user # this means ANY plain text user, too, right? Right. Bleh. I need valid-ldap-user
# This ldap-filter should be effectively the same as the non-existant "Require valid-ldap-user"
Require ldap-filter (sAMAccountName=*)
</Directory>

<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/rsdk">
AuthGroupFile "C:/Program Files/Apache Software Foundation/Apache2.2/conf/groups"
AuthzGroupFileAuthoritative off
Require group rsdk

AuthLDAPBindDN "CN=Test Test,OU=QA,DC=einstruction,DC=com"
AuthLDAPBindPassword test
AuthLDAPURL "ldap://eiadserver1.einstruction.com:3268/DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"
AuthzLDAPAuthoritative off
Require ldap-filter (sAMAccountName=*)
</Directory>

<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/foo">
AuthLDAPBindDN "CN=Test Test,OU=QA,DC=einstruction,DC=com"
AuthLDAPBindPassword test
AuthLDAPURL "ldap://eiadserver1.einstruction.com:3268/DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"
AuthzLDAPAuthoritative off

Require ldap-group CN=R&D Group,OU=AppDev,DC=einstruction,DC=com
Require ldap-group CN=QA Group,OU=QA,DC=einstruction,DC=com
</Directory>

<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/bar">
AuthLDAPBindDN "CN=Test Test,OU=QA,DC=einstruction,DC=com"
AuthLDAPBindPassword test
AuthLDAPURL "ldap://eiadserver1.einstruction.com:3268/DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)"
AuthzLDAPAuthoritative off

# this doesn't work, it's not really a group, with 'member' attributes like the other groups
Require ldap-group CN=Users,DC=scottsdale,DC=einstruction,DC=com
Require ldap-group CN=QA Group,OU=QA,DC=einstruction,DC=com
</Directory>






The following is all misc. unordered, unedited notes while trying to learn myself some stuff.


Leads:
From the Apache 2.3 docs on Active Directory, “Querying the Global Catalog allows all the domains to be queried in a single query, without the query spanning servers over potentially slow links.” - changing to port 3268 on eiadserver1 - it found my ldaptest (new account Lapio created for me in the scottsdale portion) account - woot, holla.

sysinternals Active Directory Explorer, cannot find MPFEFFER doing a search either - AND, when browsing the AD, DOES NOT show DC=scottsdale as a sub-node underneath DC=einstruction,DC=com.

Watching the ADExplorer search with ADInsight, does not reveal anything - just that the search for MPFEFFER returned no results.

Softerra LDAP Browser 2.5 will show the DC=scottsdale node, can even search CN=Users,DC=scottsdale,DC=einstruction,DC=com and lists all the users inside, including pfeffer (doesn't seem to have a way to do a specific query a la Apache and ADExplorer) -- but, while browsing the AD, it occasionally does report:
00000000: LdapErr: DSID-0C090627, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, vece
[ERROR 1] Operations error
...which is the same error message (well, “Operations error”) we're getting from Apache when MPFEFFER tries to login.



Apache's LDAP module (2.2 or earlier) seems to have trouble with querying Active Directory.
Weird - I fixed this by referencing eiadserver1 instead of eiserver8. i.e. this works:
AuthLDAPURL “ldap://eiadserver1.einstruction.com:389/DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)”
but this doesn't:
AuthLDAPURL “ldap://eiserver8.einstruction.com:389/DC=einstruction,DC=com?sAMAccountName?sub?(objectClass=user)”

That was true yesterday - 4/14/08, but today, neither of the above urls is working. Well ... eiadserver1.einstruction.com wasn't resolving for a while on appdev.einstruction.com - hardcoding the ip address worked, and eiserver8 resolved (but the ldap didn't work). Now it's back - and working for chris.morris AND the test account - but not for MPFEFFER. BLARGH!!!! Error log says No Such Object.

(Maybe eiadserver1 is configured as a global catalog? or was...? In the Apache bug report, it says global cat should be a workaround because it doesn't have the referral problem the normal one does.)

Here's the Apache HTTPD bug report for all this - it includes a patch.

see this for example of Require ldap-group which maybe will work for different groups ... ?
see also examples in the docs - check out filters as well as the ldap-group -- looks like something should be made to work with these options.

There's an alias module which will allow multiple urls to be searched, apparently, but it won't help when needing to restrict users per ldap-group in sub Directory sections.

This long thread is exactly the problem I've been running into, and it offers a bit of insight:
Hi,

I experienced the same problem as the one described here, and it turned
out to be the LDAP referrals being sent by Active Directory.

If you bind to cn=3DUsers,dc=3Dad,dc=3Dcompany,dc=3Dcom, then you are =
binding to
a container within Active Directory, and everything works fine.

However, if you bind to the root of your domain, i.e. just
dc=3Dad,dc=3Dcompany,dc=3Dcom, then Active Directory, in addition to the
search results you expected, will also return referrals to the other
directory partitions.

It seems that the referrals that Active Directory returns are causing
the authentication to be rejected.

There are two possible solutions that I know of:

1. Create an organisational unit called something like “All Users” and
make sure all your user accounts are inside this container - that way
you can use ou=3Dall users,dc=3Dad,dc=3Dcompany,dc=3Dcom as your LDAP =
path.

2. Disabling referral chasing got the Netscape LDAP SDK to bind to the
root of an Active Directory domain - no idea if the same will be true of
OpenLDAP.

Hope this information helps someone.

Regards,

John

I believe there's some 2.3 apache docs which have more love for Active Directory specifically, but 2.3 hasn't been released yet. sigh.

Plus, I think the trick is the query must return only one result for the authentication to work.

URLs:
http://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html#examples
http://www.faqs.org/rfcs/rfc2255.html
http://www.faqs.org/rfcs/rfc2254.html



tags: ComputersAndTechnology ApacheLDAPAndActiveDirectory