Building an Address Book with OpenLDAP
by Dustin Puryear03/27/2003
LDAP Comes to the Rescue, Again
There has been a lot of buzz in the past few years about using the Lightweight Directory Access Protocol (LDAP) for centralizing system and network information, providing cross-platform user account databases, and even for creating a single repository of printer definitions and configuration information. All of these uses are truly incredible, and they only go to show you the level of flexibility available with LDAP. Most of these examples neglect an important and obvious example--using LDAP for a company-wide address book.
Why is a centralized address book important, and how can it be used? For starters, I think just about every consultant has walked onto a site--even a large one--where everyone has contact information stored locally in their contact management software. What's wrong with that? Nothing, if you don't mind losing the ability to update contact information effortlessly across the entire company.
The only requirement here is for contact software or email clients that support LDAP. Most email software does, including UNIX- and Linux-based software, such as Netscape Mail and Evolution, and Windows clients, such as Outlook. The trick is usually not in finding the right software, but in ensuring that you use the right attributes that will be supported universally by those clients. This article will suggest appropriate attributes for your address book and will provide examples of configuring your email clients to support your LDAP-based directory.
You must also have a working LDAP server for this project. I will be using OpenLDAP 2.0.25 under FreeBSD for the examples, although any LDAP server should do. (For information on the license governing OpenLDAP--the OpenLDAP Public License--please refer to the OpenLDAP web site.)
Please note that this article is not an in-depth review of LDAP, nor does it
cover OpenLDAP configuration extensively. For that, I would suggest you read "An Introduction
to LDAP," by Luke Kanies, and Aeleen
Frisch's LDAP article in "Top Five Open Source Packages for System
Administrators." To ensure common ground, I assume you have
slapd.conf configured similar to the following:
include /usr/local/etc/openldap/schema/core.schema
include /usr/local/etc/openldap/schema/cosine.schema
include /usr/local/etc/openldap/schema/inetorgperson.schema
pidfile /var/run/slapd.pid
argsfile /var/run/slapd.args
database ldbm
suffix "dc=example, dc=com"
rootdn "dc=example, dc=com"
rootpw secret
directory /var/db/openldap-ldbm
index objectClass eq
This configuration includes cosine.schema (the core schema used by OpenLDAP) and inetorgperson.schema, which
include attribute definitions needed by our directory. All of these files are
included with OpenLDAP version 2--when writing this article, I took pains to
ensure that you do not need to create any custom schemas for use with OpenLDAP.
While custom schemas make LDAP highly extensible, they're unnecessary for a
basic address book.
|
Related Reading
LDAP System Administration |
Creating the Directory Layout for an Address Book
Our first goal is to create our base Distinguished Name (DN), the root of our address book's subtree. Our example will use domain components to establish a (hopefully) globally unique base DN for our company. Ensuring uniqueness across organizations isn't actually necessary unless you will later need to integrate your directory with another, or if the directory will be available globally via some referral service, but it's nice to go ahead and plan these things out properly.
Our sample company, Conglomo, Inc., has purchased the domain
example.com to be used for all operations, much as IBM uses
ibm.com. Notice that we already defined this base DN using the
suffix keyword in slapd.conf:
suffix "dc=example, dc=com"
We need to create an actual entry for this in the LDAP directory itself
using an LDIF-formatted file and ldapadd. Create a file named
directory.ldif containing:
dn: dc=example, dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
dc: example
o: Conglomo, Inc.
Be sure to not leave any trailing spaces, as they may confuse
ldapadd.
Pretty simple so far. Next, create an organizational unit in the directory
under dc=example, dc=com to serve as a container for our address
book entries:
dn: ou=addressbook, dc=example, dc=com
objectClass: top
objectClass: organizationalUnit
ou: addressbook
Many people create an organizational unit named people rather
than addressbook, but addressbook will work fine for
our purposes.
This is as far as we need to go in defining our directory layout. Note, however, that the layout is actually a bit simplistic. In many situations, you may find that you want to create individual entries for departments and then create address books below those departmental organizational units:
dn: ou=addressbook, ou=accounting, dc=example, dc=com
objectClass: top
objectClass: organizationalUnit
ou: addressbook
Alternatively, you could do the opposite and create a central address book that contains each of your departments as organizational units:
dn: ou=accounting, ou=addressbook, dc=example, dc=com
objectClass: top
objectClass: organizationalUnit
ou: accounting
This last method has the advantage that the organizational unit definition
actually matches the department rather than being addressbook.
Most LDAP clients will consider the ou as the department, so this
may be important for you.
How you eventually create the directory structure really depends on the various services you will be supporting with LDAP, and not just the address book. For now, the layout presented will be more than sufficient to support a simple address book.
Now that you have the directory layout in directory.ldif,
import the LDIF entries into the directory using ldapadd:
$ ldapadd -D 'dc=example, dc=com' -f directory.ldif -W
Enter LDAP Password: secret
Assuming everything went well, OpenLDAP should now have imported the
entries. To verify this did indeed occur, use ldapsearch to dump
your directory by specifying objectclass=*:
# ldapsearch -b 'dc=example, dc=com' 'objectclass=*'
version: 2
#
# filter: objectclass=*
# requesting: ALL
#
# example, com
dn: dc=example, dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
dc: example
o: Conglomo, Inc.
# addressbook, example, com
dn: ou=addressbook, dc=example, dc=com
objectClass: top
objectClass: organizationalUnit
ou: addressbook
# search result
search: 2
result: 0 Success
# numResponses: 3
# numEntries: 2
At this point, you are ready to roll. You have imported your directory layout and are now ready to add contact information to the directory. Before you do that, we need to discuss the attributes you will use for the contact entries in the directory.