The term metadirectory describes just about any solution that joins distinct, isolated data sources into a single logical volume. There are several popular metadirectory products on the market:
MaXware MetaCenter (http://www.maxware.com/)
Siemens DirXmetahub (http://www.siemens.ie/fixedoperators/CarrierNetworks/Meta/dirxmetahub.htm)
Sun Microsystems SunOne (http://wwws.sun.com/software/products/meta_directory/home_meta_dir.html)
Novell's eDirectory and DirXML combination (http://www.novell.com/products/edirectory/)
Microsoft Metadirectory Services (http://www.microsoft.com/windows2000/technologies/directory/MMS)
For the sake of this section, we'll assume that a metadirectory is any directory service that presents an alternate view of a data source. OpenLDAP's proxy backend provides a simple means of translating one directory server's schema into a different view, suitable for particular client applications. There is no replication or synchronization of data because the proxy provides only an alternate view of the target directory; the OpenLDAP server providing the proxy doesn't actually store the data.
Imagine an email client that expects a directory service to provide an email address using the mail attribute type. Now consider that every user in an Active Directory domain is automatically assigned a Kerberos principal name of the form username@domain. If the email domain is configured so that each user's email address and Kerberos principal name (userPrincipalName) are synchronized (perhaps using an LDAP proxy service), then it makes no sense to duplicate this information just to provide a directory-based address book for a picky email application.
Before you can successfully create a proxy server, the Active Directory domain must meet the following requirements:
The Active Directory domain must be configured for the DNS domain ad.plainjoe.org.
The DNS name ad.plainjoe.org must resolve to the IP address of an Active Directory domain controller for that domain.
An account named ldap-proxy must be created in the Active Directory domain for use by the proxy server when binding to a Windows domain controller.
The OpenLDAP proxy feature isn't enabled by default; it must be enabled at compile time by specifying the ?enable-ldap and ?enable-rewrite options to the configure script for slapd:
$ configure --enable-ldap --enable-rewrite
After compiling and installing the new slapd executable, create the new LDAP database in slapd.conf. Remember that a partition in slapd.conf begins with the database directive and continues until the next database section or the end of the file. The new proxy section begins with the declaration:
## Proxy backend to access Active Directory. database ldap
This declaration tells slapd to acquire its data from another LDAP server, allowing it to act as a proxy for that server. If OpenLDAP complains that ldap is not a valid database type, verify that ?enable-ldap and ?enable-rewrite were actually used when compiling the server. Even though OpenLDAP will not store any actual data for this partition, slapd must still be given the naming context of the database (ou=windows,dc=plainjoe,dc=org) using the standard suffix paramete:.
This is an arbitrary suffix; it does not correspond to the DN of users' container in Active Directory. The uri and suffixmassage parameters tell slapd about the target directory (the directory being proxied) and the request rewrite rules. Your server must replace the suffix ou=windows,dc=plainjoe,dc=org with cn=users,dc=ad,dc=plainjoe,dc=org before passing any request to the target server. If no rewriting should be performed, the suffixmassage directive can be omitted.
uri ldap://ad.plainjoe.org/ suffixmassage ou=windows,dc=plainjoe,dc=org cn=users,dc=ad,dc=plainjoe,dc=org
The binddn and bindpw parameters provide a means of specifying the credentials to use when contacting the remote LDAP directory. Here you use a simple bind. If your proxy server and remote server existed on opposite sites on an insecure, or hostile, network, it would be prudent to modify the uri parameter to use LDAPS:
## Active Directory also allows the userPrincipalName value to be used in LDAP binds, ## so this could be email@example.com. binddn cn=ldap-proxy,cn=users,dc=ad,dc=plainjoe,dc=org bindpw proxy-secret
OpenLDAP's proxy code only provides a way to map attributes and object classes defined by its local schema to those stored in the target directory. The syntax for defining a mapping is:
map attribute|objectclass [local_name|*] foreign_name|*
A map must define whether it applies to an attribute or an objectclass. The name of the local attribute or object class is optional, but remote names are required. The asterisk (*) character can be used to match any name. Your proxy server should map Active Directory's sAMAccountName, name, and userPrincipalName attributes to the locally defined uid, cn, and mail attributes. You also need to map the local account object class to the target user object class. Here are the map statements that perform the mapping:
## Map these. map attribute uid sAMAccountName map attribute cn name map attribute mail userPrincipalName map objectclass account user
The proxy server can filter out any remaining attributes by mapping any remaining remote attributes to nothing:
## Remove the rest. map attribute *
To see the results of this mapping, compare the entry returned by querying Active Directory directly to the result obtained by going through the OpenLDAP proxy. Here's what happens when you query Active Directory; the items that will be provided by the proxy server are shown in bold:
$ ldapsearch -H ldap://ad.plainjoe.org -x \ -D firstname.lastname@example.org -w proxy-secret -x \ -b "cn=users,dc=ad,dc=plainjoe,dc=org" -LLL \ "(sAMAccountName=kristi)" dn: CN=Kristi Carter,CN=Users,DC=ad,DC=plainjoe,DC=org accountExpires: 9223372036854775807 badPasswordTime: 0 badPwdCount: 0 codePage: 0 cn: Kristi Carter countryCode: 0 displayName: Kristi Carter givenName: Joe instanceType: 4 lastLogoff: 0 lastLogon: 0 logonCount: 0 distinguishedName: CN=Kristi Carter,CN=Users,DC=ad,DC=plainjoe,DC=org objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=plainjoe,DC=org objectClass: top objectClass: person objectClass: organizationalPerson objectClass: user objectGUID:: NDHKI8oYFkqN8da3Gl9a5Q= = objectSid:: AQUAAAAAAAUVAAAAEcNfczJiHypDFwoyUwQAAA= = primaryGroupID: 513 pwdLastSet: 126784120014273696 name: Kristi Carter sAMAccountName: kristi sAMAccountType: 805306368 sn: Carter userAccountControl: 66048 userPrincipalName: email@example.com uSNChanged: 2963 uSNCreated: 2957 whenChanged: 20021006210839.0Z whenCreated: 20021006210637.0Z
Now, issue a similar query to the proxy server?except that you'll look up a uid rather than an Active Directory sAMAccountName, and the root of your search will be the DN that you've assigned to the proxy. This time, the search can be done anonymously. Here's the result:
$ ldapsearch -H ldap://ldap.plainjoe.org -x \ -b "ou=windows,dc=plainjoe,dc=org" -LLL "(uid=kristi)" dn: CN=Kristi Carter,ou=windows,dc=plainjoe,dc=org objectClass: top objectClass: person objectClass: organizationalPerson objectClass: account cn: Kristi Carter uid: kristi mail: firstname.lastname@example.org
When you compare the two results, you will see that:
objectClass: user name: Kristi Carter sAMAccountName: kristi userPrincipalName: email@example.com
has been mapped to:
objectClass: account cn: Kristi Carter uid: kristi mail: firstname.lastname@example.org
The proxy server returns something slightly different if you remove the directive that filters all the attributes that aren't explicitly mapped (map attribute *):
$ ldapsearch -H ldap://ldap.plainjoe.org -x \ -b "ou=windows,dc=plainjoe,dc=org" -LLL "(uid=kristi)" dn: CN=Kristi Carter,ou=windows,dc=plainjoe,dc=org cn: Kristi Carter displayName: Kristi Carter mail: email@example.com givenName: Kristi distinguishedName: CN=Kristi Carter,ou=windows,dc=plainjoe,dc=org objectClass: top objectClass: person objectClass: organizationalPerson objectClass: account cn: Kristi Carter uid: kristi sn: Carter
While this query returns more information than the previous one, it is obvious that slapd is still filtering some of the attributes from the target entry. This filtering occurs because the attributes returned by the query are still controlled by the local schema defined in slapd.conf. If the OpenLDAP installation does not understand a given attribute or object class (for example, userAccountControl), and it has not been mapped to a known local schema item, the unknown value is filtered out.
The LDAP proxy backend supports updating the target directory, should you require it. It also supports local ACLs in the LDAP database section; these ACLs can be used to control access to an LDAP proxy that presents a view of the company's internal directory services to external clients. The slapd-ldap(5) manpage has more details on both of these configuration possibilities.