The Lightweight Directory Access Protocol (LDAP) is the protocol[138] for accessing the preeminent directory services deployed in the world today. Over time, system administrators are likely to find themselves dealing with LDAP servers and clients in a number of contexts. For example, Active Directory and Mac OS X Open Directory are both LDAP-based. This tutorial will give you an introduction to the LDAP nomenclature and concepts you’ll need when using the material in Chapter 9, Directory Services.
This excerpt is from Automating System Administration with Perl, Second Edition . Thoroughly updated and expanded in its second edition to cover the latest operating systems, technologies, and Perl modules, Automating System Administration with Perl will help you perform your job with less effort. The second edition not only offers you the right tools for your job, but also suggests the best way to approach particular problems and securely automate pressing tasks.
The action in LDAP takes place around a data structure known as an entry. Figure C.1, “The LDAP entry data structure” is a picture to keep in mind as we look at an entry’s component parts.
Figure C.1. The LDAP entry data structure
An entry has a set of named component parts called attributes that hold the data for that entry. To use database terms, they are like the fields in a database record. In Chapter 9, Directory Services we use Perl to keep a list of machines in an LDAP directory. Each machine entry will have attributes like name
, model
, location
, owner
, etc.
Besides
its name, an attribute consists of a type and the value for the
attribute. The value has to be of the type defined for the attribute.
For example, if you are storing employee information, your entry might
have a phone
attribute that has a type oftelephoneNumber
.
The value of this attribute might be that employee’s phone number. A
type also has a syntax that dictates what kind of data can be used
(strings, numbers, etc.), how it is sorted, and how it is used in a
search (is it case-sensitive, etc.?). To accommodate multiple values,
you can store multiple attributes of the same name in a single entry. An
example of this would be a group entry where you would have multiple
member attributes in the entry, each holding a group member.
An
entry’s contents and structure are defined by its object class. The
object class (along with server and user settings) specifies which
attributes must and may exist in that particular entry. Each entry can
be in multiple object classes, in which case the specifications are
essentially merged. The object class (or classes) of an entry is
recorded in that entry in a special attribute named objectClass
.
Let’s look a little closer at the objectClass
attribute,
because it illustrates some of the important qualities of LDAP and
allows us to pick off the rest of the jargon we haven’t encountered yet.
If we consider the objectClass
attribute, we notice the following:
Each value in an objectClass
attribute
is the name of an object class. As mentioned earlier, these classes
either define the set of attributes that can or must be in an entry, or
expand on the definitions inherited from another class.
Let’s look at an example. Suppose the objectClass
in an entry contains the string residentialPerson
. RFC 2256, which has the daunting title of “A Summary of the X.500(96) User Schema for Use with LDAPv3,” defines the residentialPerson
object class like this:
residentialPerson ( 2.5.6.10 NAME 'residentialPerson' SUP person STRUCTURAL MUST l MAY ( businessCategory $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ preferredDeliveryMethod $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ st $ l ) )
This definition says that an entry of object class residentialPerson
must have a l
attribute (short for locality) and may have a whole other set of attributes (registeredAddress
, postOfficeBox
, etc.). The key part of the specification is theSUP person
string. It says that the superior class (the one from which residentialPerson
inherits its attributes) is theperson
object class. That class’s definition looks like this:
person ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn ) MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
So, an entry with object class of residentialPerson
must have sn
(surname), cn
(common name), and l
(locality) attributes and may have the other attributes listed in the MAY
sections of these two RFC excerpts. We also know thatperson
is the top of the object hierarchy for residentialPerson
, since its superior class is the special abstract class top
.
In
most cases, you can get away with using the predefined standard object
classes. If you need to construct entries with attributes not found in
an existing object class, it is usually good form to locate the closest
existing object class and build upon it, like residentialPerson
builds upon person
.
A second quality we see in objectClass
is LDAP’s database roots. A collection of object classes that specify attributes for the entries in an LDAP server is called a schema.
The RFC I just quoted is one example of an LDAP schema specification.
We won’t be addressing the considerable issues surrounding schema in
this book. Like database design, schema design can be a book topic in
itself, but you should at least be familiar with the term “schema”
because it will pop up later.
There’s one last thing I should mention about objectClass
to help us move from our examination of a single entry to the larger picture. Our previous object class example specified top
at the top of the object hierarchy, but there’s another quasi-superclass worth mentioning: alias
. If alias
is specified, this entry is actually an alias for another entry (specified by the aliasedObjectName
attribute
in that entry). LDAP strongly encourages hierarchical tree structures,
but it doesn’t demand them. It’s important to keep this flexibility in
mind when you code to avoid making incorrect assumptions about the data
hierarchy on a server.
So far we’ve been focused on a single entry, but there’s very little call for a directory that contains only one entry. When we expand our focus and consider a directory populated with many entries, we are immediately faced with one important question: how do we find anything?
The stuff we’ve discussed so far all falls under what the LDAP specification calls its “information model.” This is the part that sets the rules for how information is represented. But for the answer to our question, we need to look to LDAP’s “naming model,” which dictates how information is organized.
If you refer back to Figure C.1, “The LDAP entry data structure”, you’ll see that we’ve discussed all of the parts of an entry except for its name. Each entry has a name, known as its distinguished name (DN). The DN consists of a string of relative distinguished names (RDNs). We’ll return to DNs in a moment, but first let’s concentrate on the RDN building blocks.
An RDN is composed of one or several attribute name/value pairs. For example, cn=Jay Sekora
(where cn
stands for “common name”) could be an RDN. The attribute name is cn
and the value is Jay Sekora
.
Neither the LDAP nor the X.500 specification dictates which attributes should be used to form an RDN. They do require RDNs to be unique at each level in a directory hierarchy, however. This restriction exists because LDAP has no inherent notion of “the third entry in the fourth branch of a directory tree,” so it must rely on unique names at each level to distinguish between individual entries at that level. Let’s see how this restriction plays out in practice.
Take, for instance, another example RDN: cn=Robert Smith
.
This is probably not a good RDN choice, since there may be more than
one Robert Smith in an organization of even moderate size. If you have a
large number of people in your organization and your LDAP hierarchy is
relatively flat, name collisions like this are to be expected. A
marginally better entry would combine two attributes: perhaps cn=Robert Smith + l=Boston
. (Attributes in RDNs are combined with a plus sign.)
Our
revised RDN, which appends a locality attribute, still has problems,
though. We may have postponed a name clash, but we haven’t eliminated
the possibility. Furthermore, if Smith moves to some other facility,
we’ll have to change both the RDN for the entry and the location
attribute in the entry. Perhaps the best RDN we could use would be one
with a unique and immutable user ID for this person. For example, we
could use the username component of the person’s email address, so the
RDN would beuid=rsmith
. This example should give you a taste of the decisions involved in the world of schemas.
Astute readers will notice that we’re not really expanding our focus; we’re still puttering around with a single entry. The RDN discussion was a prelude to this. Here’s the real jump: entries live in a tree-like[139] structure known as a directory information tree (DIT), or just a directory tree. The latter is probably the preferred term to use, because in X.500 nomenclature DIT usually refers to a single universal tree, similar to the global DNS hierarchy or the management information base (MIB) we’ll be seeing inAppendix G, The 20-Minute SNMP Tutorial when we discuss SNMP.
Let’s bring DNs back into the picture. Each entry in a directory tree can be located by its distinguished name. A DN is composed of an entry’s RDN followed by all of the RDNs (separated by commas or semicolons) found as you walk your way back up the tree toward the root entry. If we follow the arrows in Figure C.2, “Walking back up the tree to produce a DN” and accumulate RDNs as we go, we’ll construct DNs for each highlighted entry.
Figure C.2. Walking back up the tree to produce a DN
In the first picture, our DN would be:
cn=Robert Smith, l=main campus, ou=CCS, o=Hogwarts School, c=US
In the second, it is:
uid=rsmith, ou=system, ou=people, dc=ccs, dc=hogwarts, dc=edu
ou
is short for organizational unit, o
is short for organization, dc
stands for “domain component” à la DNS, and c
is for country (Sesame Street notwithstanding).
An analogy is often made between DNs and absolute pathnames in a filesystem, but DNs are more like postal addresses because they have a “most specific component first” ordering. In a postal address like this:
Doreen Hodgkins |
288 St. Bucky Avenue |
Anywhere, MA 02104 |
USA |
you start off with the most specific object (the person) and get more vague from there, eventually winding up at the least specific component (the country). So too it goes with DNs.
You can see this ordering in our DN examples. The very top of the directory tree is known as the directory’s suffix, since it is the end portion of every DN in that directory tree. Suffixes are important when constructing a hierarchical infrastructure using multiple delegated LDAP servers. Using an LDAPv3 concept known as a referral, it is possible to place an entry in the directory tree that essentially says, “for all entries with this suffix, go ask that server instead.” Referrals are specified using an LDAP URL, which looks similar to your run-of-the-mill web URL except that it references a particular DN or other LDAP-specific information. Here’s an example from RFC 2255, the RFC that specifies the LDAP URL format:
ldap://ldap.itd.umich.edu/o=University+of+Michigan,c=US?postalAddress
The other place directory suffixes come into play is in the client/server authentication process, since a client usually is connecting to access a single directory tree on the server: it “binds” to the server using this suffix. We’ll see this process and details on querying an LDAP server in Chapter 9, Directory Services.
By now you have some idea of how data is organized and specified in LDAP terms. With that grounding, the discussion of the manipulation of this data in Chapter 9, Directory Services should be much clearer.
[138] Just to stress this point: LDAP is a protocol. It is not a relational database; it is the protocol through which you can communicate with a database-like directory service. More on the difference between databases and directory services can be found in Chapter 9, Directory Services.
[139] I say “tree-like” rather than just “tree” because the alias
object
class I mentioned earlier allows you to create a directory structure
that is not strictly a tree (at least from a computer-science,
directed-acyclic-graph perspective).
If you enjoyed this excerpt, buy a copy of Automating System Administration with Perl, Second Edition .