9.4 Distributed, Multivendor Directories

Standard protocols go a long way to promote interoperability. While the schema for representing an LDAP referral can vary from vendor to vendor, the method of returning referral information to clients is defined as part of the core LDAPv3 protocol. This means that LDAP servers from various vendors can be linked into a single, logical, distributed directory.

But why go through all the trouble of building a multivendor directory? Why not settle on a single LDAP vendor, who has no doubt made it easy to build distributed directories by developing schemas to represent referrals and solving other problems that aren't addressed by the standards? And, as I've said elsewhere, we shouldn't use technologies just because they're there; if LDAP doesn't make life easier for us as administrators, and for the users of our systems, there's little point going through the effort of setting up an LDAP directory at all, let alone a distributed, multivendor directory.

However, sooner or later a single-vendor directory will force you to make decisions that you're uncomfortable with. Let's assume that you're adding a new application server, such as a calendaring system, at your site. This server is backed by an LDAP directory and requires certain protocol extensions from the directory. Naturally, the vendor has tested the application server with a particular LDAP server in mind?perhaps the vendor even sells an LDAP product (which, of course, is guaranteed to work with the calendar server). But as fate would have it, you've already invested a lot of time and effort in building an LDAP directory, and the directory server that supports the calendar server is not the directory server you've spent so much effort deploying. In this case, there are three possible solutions:

  • Abandon the calendar server, since it is not supported by your existing LDAP server. However, you're probably installing the server because management wants you to do so; saying no probably isn't an option.

  • Replace the existing directory with one that supports the calendar service. This solution probably doesn't involve throwing out all the work you did getting your directory service running?but you will have to redo a lot of it. And what happens the next time you're told to install an application that talks to an LDAP server? Will it be compatible with the server you've installed for the sake of the calendar service? It's clear that this isn't really an option, unless you want to spend your career playing "musical servers."

  • Install a new LDAP server that supports the calendar application and include it as a subtree of your existing directory framework.

The last option is really the only option that makes sense. It allows you to augment, rather than replace, the directory infrastructure you've already built. Furthermore, sooner or later you will be forced to incorporate different LDAP servers into your network. The goal of standardization is to enable clients developed by one company to access servers developed by another; and even if this is presently a goal rather than a reality, your life will be easier if you work with this goal in mind.

The addition of a new vendor-dependent, LDAP-enabled application raises an important question: how is this solution any different than the myriad of application-specific directories of the past? The difference here is that there is a single access protocol for all clients and administration tools. The LDAP protocol is the unifying factor. While you still have applications that can talk only to a particular vendor's server, the common LDAP protocol allows you to integrate that LDAP server with the other servers on the network.

The remainder of this section explores this solution by presenting a scenario in which an OpenLDAP server is connected to an Active Directory installation. The goal is to create a virtual directory in which a user can search for an entry anywhere by querying either of the directory services, without regard for which directory holds the information. Figure 9-6 shows what we're trying to achieve.

Figure 9-6. Creating a single LDAP directory using a OpenLDAP and Active Directory

For this exercise, you can assume the following facts:

  • A working OpenLDAP has been configured with the naming context of dc=plainjoe,dc=org on the host ldap.plainjoe.org.

  • An Active Directory domain has been created for the DNS domain ad.plainjoe.org. Therefore, the Active Directory LDAP service will have a naming context of dc=ad,dc=plainjoe,dc=org.

You need to add two knowledge references to this system. The first will point from the Active Directory service to the OpenLDAP server; the second will refer client searches from the OpenLDAP directory to the Active Directory domain.

The ADSI Edit MMC snap-in is needed to add an LDAP referral to Active Directory. This low-level, directory-browsing utility is included in \SUPPORT\TOOLS on the Windows 2000 Advanced Server CD. Once the support tools have been installed (using setup.exe), the ADSI Edit icon should appear in the Start Menu (Start Programs Windows 2000 Support Tools Tools ADSI Edit).

The referral from the Active Directory domain to the OpenLDAP server must be created inside the cn=Partitions,cn=Configuration,dc=ad,dc=plainjoe,dc=org container. This directory entry is the root for all entries possessing referrals to subdomains in an Active Directory tree, as well as external referrals explicitly added by an administrator. After launching the ADSI Edit tool and navigating to the Partitions container, as illustrated in Figure 9-7, create a new crossRef object by right clicking within the list of existing entries and selecting the New Object . . . variable from the context menu.

Figure 9-7. Creating a new crossRef object in the Partitions container of an Active Directory domain

A Create Object wizard helps you fill in the information for the object class's mandatory attributes. The following LDIF excerpt shows what you're trying to accomplish: you need to add a node named OpenLDAP with an nCName attribute that has the value dc=plainjoe,dc=org, and a dnsRoot attribute that has the value ldap.plainjoe.org:

dn: cn=OpenLDAP,cn=Partitions,dc=Configuration,dc=ad,dc=plainjoe,dc=org
cn: OpenLDAP
nCName: dc=plainjoe,dc=org
dnsRoot: ldap.plainjoe.org

This new entry instructs the Active Directory server to return a referral of the form ldap://ldap.plainjoe.org/dc=plainjoe,dc=org to clients in response to an LDAP search.

Next, a corresponding knowledge reference must be added to the OpenLDAP server. This reference must point to the Active Directory domain. The following LDIF excerpt shows the reference you need to add to the OpenLDAP server:

dn: dc=ad,dc=plainjoe,dc=org
objectclass: referral
objectclass: dcObject
ref: ldap://ad.plainjoe.org/dc=ad,dc=plainjoe,dc=org
dc: ad

You can use ldapadd to add this entry. Assuming that the LDIF code is in the file ad-referral.ldif, the following command will do the trick:

$ ldapadd -D "cn=Manager,dc=plainjoe,dc=org" -w secret -x \
  -H ldap://ldap.plainjoe.org/ -f ad-referral.ldif

The ref attribute in the new entry requires that the ad.plainjoe.org DNS name resolve to a domain controller in the Active Directory domain. The AUXILIARY dcObject object class is included out of convention and due to a choice of RDN attributes for the entry.

The two directories are now linked in such a way that an LDAP query sent to one directory should be able to locate data stored in the other directory. To test this, start by sending an anonymous search to an Active Directory domain controller and looking for data that's stored in OpenLDAP. To do this, use OpenLDAP's ldapsearch command:

$ ldapsearch -H ldap://ad.plainjoe.org/ -x  \
  -b "ou=people,dc=plainjoe,dc=org" -LLL "(uid=jerry)"
Referral (10)
Additional information: 0000202B: RefErr: DSID-031005EE, data 0, 1 access points
        ref 1: 'ldap.plainjoe.org'
Referral: ldap://ldap.plainjoe.org/ou=people,dc=plainjoe,dc=org

You get a referral from the Active Directory server, but you don't get any actual results: this search does not follow the referral. To see the actual results, you can perform the same search, but use the -C option to instruct the LDAP client libraries to follow the referral and print out the final results:

$ ldapsearch -h ad.plainjoe.org -x -C \
  -b "ou=people,dc=plainjoe,dc=org" -LLL "(uid=jerry)"
dn: cn=Gerald Carter,ou=people,dc=plainjoe,dc=org
objectClass: posixAccount
objectClass: account
objectClass: sambaAccount
cn: Gerald Carter
uidNumber: 780
uid: jerry
gidNumber: 100
homeDirectory: /home/queso/jerry
loginShell: /bin/bash
rid: 2560
acctFlags: [UX         ]
pwdLastSet: 1018451245

What about making a search that goes in the other direction? Can you send a search to OpenLDAP looking for data stored in Active Directory? The answer is yes, but with the same caveat that was mentioned when using pam_ldap to authenticate services against an Active Directory domain. By default, Active Directory does not support searches using an anonymous bind, except for its rootDSE. Therefore, an attempt to locate a user named kristi in the Active Directory domain without using some valid credentials in the bind would return only a referral to the Active Directory server itself. Login names in Active Directory are stored under the sAMAccountName attribute.

$ ldapsearch -x -H ldap://ldap.plainjoe.org/ \
  -b "dc=ad,dc=plainjoe,dc=org" -LLL -C "(sAMAccountName=kristi)"
# refldap://ad.plainjoe.org/CN=Configuration,DC=ad,DC=plainjoe,DC=org

This referral was returned by the Active Directory server itself because you did not provide valid credentials for searching deeper in the directory tree. If you would like to convince yourself that the OpenLDAP server is returning the correct referral, simply rerun the search without the -C argument:

$ ldapsearch -H ldap://ldap.plainjoe.org/ -x \
  -b "dc=ad,dc=plainjoe,dc=org" -LLL "(sAMAccountName=kristi)"
Referral (10)
Matched DN: dc=ad,dc=plainjoe,dc=org
Referral: ldap://ad.plainjoe.org/dc=ad,dc=plainjoe,dc=org??sub

To search Active Directory fully, you must employ some type of trust mechanism (e.g., Kerberos cross-realm trusts) or single-signon solution between the two LDAP servers, or allow anonymous searches of portions of the Active Directory DIT. Since anonymous searches of Active Directory were covered in Section 9.3, I won't revisit that topic here.