Concepts and architecture
This section covers material for topic 301.1 for the Senior Level Linux Professional (LPIC-3) exam 301. This topic has a weight of 3.
In this section, learn about:
- LDAP and X.500 technical specification
- Attribute definitions
- Directory namespaces
- Distinguished names
- LDAP Data Interchange Format
- Changetype operations
Most of the LPIC-3 exam focuses on the use of the Lightweight Directory Access Protocol (LDAP). Accordingly, the first objective involves understanding what LDAP is, what it does, and some of the basic terminology behind the concept. When you understand this, you will be able to move on to designing your directory and integrating your applications with the directory.
Before talking about LDAP, let's review the concept of directories. The classic example of a directory is the phone book, where people are listed in alphabetical order along with their phone numbers and addresses. Each person (or family) represents an object, and the phone number and address are attributes of that object. Though not always obvious at a glance, some objects are businesses instead of people, and these may include fax numbers or hours of operation.
Unlike its printed counterpart, a computer directory is hierarchical in nature, allowing for objects to be placed under other objects to indicate a parent-child relationship. For instance, the phone directory could be extended to have objects representing areas of the city, each with the people and business objects falling into their respective area objects. These area objects would then fall under a city object, which might further fall under a state or province object, and so forth, much like Figure 1. This would make a printed copy much harder to use because you would need to know the name and geographical location, but computers are made to sort information and search various parts of the directory, so this is not a problem.
Figure 1. A sample directory
Looking at Figure 1, knowing where the Simpson's record is tells you more than just the address and phone number. You also know they are in the East end in the town of Springfield. This structure is called a tree. Here, the root of the tree is the Springfield object, and the various objects represent further levels of branching.
This directory-based approach to storing data is quite different than the relational databases that you may be familiar with. To compare the two models, Figure 2 shows what the telephone data might look like if modeled as a relational database.
Figure 2. Directory data modeled in relational form
In the relational model, each type of data is a separate table that allows different types of information to be held. Each table also has a link to its parent table so that the relationships between the objects can be held. Note that the tables would have to be altered to add more information fields.
Remember that nothing about the directory model places any restrictions on how the data may be stored on disk. In fact, OpenLDAP supports many back ends including flat files and Structured Query Language (SQL) databases. The mechanics of laying out the tables on disk are largely hidden from you. For instance, Active Directory provides an LDAP interface to its proprietary back end.
LDAP was conceived in Request for Comments (RFC) 1487 as a lightweight way to access an X.500 directory instead of the more complex Directory Access Protocol. (See the Resources section for links to this and related RFCs.) X.500 is a standard (and a family of standards) from the International Telecommunication Union (ITU, formerly the CCITT) that specifies how directories are to be implemented. You may be familiar with the X.509 standard that forms the core of most Public Key Infrastructure (PKI) and Secure Sockets Layer (SSL) certificates. LDAP has since evolved to version 3 and is defined in RFC 4511.
Connecting to an X.500 database initially required the use of the Open Systems Interconnection (OSI) suite of protocols and, in true ITU fashion, required understanding of thick stacks of protocol documentation. LDAP allowed Internet Protocol (IP)-based networks to connect to the same directory with far fewer development cycles than using OSI protocols. Eventually the popularity of IP networks led to the creation of LDAP servers that support only as many X.500 concepts as necessary.
Despite the triumph of LDAP and IP over X.500 and OSI, the underlying organization of the directory data is still X.500-ish. Concepts that you will learn over the course of this tutorial, such as Distinguished Names and Object Identifiers, are brought up from X.500.
X.500 was intended as a way to create a global directory system, mostly to assist with the X.400 series of standards for e-mail. LDAP can be used as a global directory with some effort, but it is mostly used within an enterprise.
In the LDAP world, names are important. Names let you access and search records, and often the name gives an indication of where the record is within the LDAP tree. Figure 3 shows a typical LDAP tree.
Figure 3. A typical LDAP tree showing a user
At the top, or root, of the tree is an entity called
dc is short for domain component.
ertw is under the
.com top-level domain, the two are
separated into two different units. Components of a name are
concatenated with a comma when using the X.500 nomenclature, with the
new components being added to the left. Nothing technically prevents
you from referring to the root as
dc=ertw.com, though in the interest of
future interoperability it is best to have the domain components
separate (in fact, RFC 2247 recommends the separate domain
dc=ertw,dc=com is a way to uniquely
identify that entity in the tree. In X.500 parlance, this is called
the distinguished name, or the DN. The DN is much like a
primary key in the relational-database world because there can be only
one entity with a given DN within the tree. The DN of the topmost
entry is called the Root DN.
Under the root DN is an object with the DN of
ou means organizational unit, and
you can be sure it falls under the root DN because the
ou appears immediately to the left of the
root DN. You can also call
relative distinguished name, or RDN, because it is
unique within its level. Put in recursive terms, the DN of an entity
is the entity's RDN plus the DN of the parent. Most LDAP browsers show
only the RDN because it eliminates redundancy.
Moving down the tree to
you find the record for a person.
common name. For the first time, though, a record has some
additional information in the form of attributes. Attributes
provide additional information about the entity. In fact, you'll see
the leftmost component of the DN is duplicated; in this case, it's the
cn attribute. Put another way, the RDN of
an entity is composed of one (or more) attributes of the entity.
description are easy enough to understand,
objectClass is not as obvious. An object
class is a group of attributes that correspond to a particular entity
type. One object class may contain attributes for people and another
for UNIX accounts. By applying the two object classes to an entity,
both sets of attributes are available to be stored.
Each object class is assigned an object identifier (OID) that uniquely identifies it. The object class also specifies the attributes, and which ones are mandatory and which are optional. Mandatory attributes must have some data for the entity to be saved. The object class also identifies the type of data held and whether multiple attributes of the same name are allowed. For instance, a person might have only one employee number but multiple first names (for example, Bob, Robert, and Rob).
The bottom-level objects are not the only ones to have object classes
associated with them. These objects, called containers, also
have object classes and attributes. The
people ou is of type
organizationalUnit and has a description
attribute along with
ou=people to create
the RDN. The root of the tree is of type
organization. Knowing which object classes
to assign an object depends on what is being held in the object and
under it. Refer to the Schemas section for
The root DN also defines the namespace of the tree or, to be
more technical, the Directory Information Tree (DIT). Something
dc=ibm,dc=com would fall outside
of the namespace from Figure 3, whereas the record
Sean Walberg falls within the
namespace. With that in mind, though, it is possible that one LDAP
server contains multiple namespaces. A somewhat abstract item called
the Root DSE contains the information about all the namespaces
available on the server. DSE means the DSA-Specific Entry, and DSA
means Directory System Agent (that is, the LDAP server).
Figure 4 summarizes the terminology associated with the LDAP tree.
Figure 4. Summary of LDAP terminology
Finally, an LDAP tree can be synchronized with other trees or data sources. For instance, one branch of the tree could come from a security system, another from a customer database, and the rest could be stored in the LDAP server. This is called a meta-directory and is intended to be a single source of data for applications such as single sign-on.
Data can get into an LDAP server in one of two ways. Either it can be loaded in over the network, using the LDAP protocol, or it can be imported from the server through a file in the LDAP Data Interchange Format (LDIF). LDIF can be used at any time, such as to create the initial tree, and to perform a bulk add or modify of the data some time later. The output of a search can also be in LDIF for easy parsing or import to another server. The full specification for LDIF is in RFC 2849 (see Resources for a link).
The LDIF that generated the tree from Figure 3 is shown in Listing 1.
Listing 1. A simple LDIF file to populate a tree
# This is a comment dn: dc=ertw,dc=com dc: ertw description: This is my company the description continues on the next line indented by one space objectClass: dcObject objectClass: organization o: ERTW.COM dn: ou=people,dc=ertw,dc=com ou: people description: Container for users objectclass: organizationalunit dn: cn=Sean Walberg,ou=people,dc=ertw,dc=com objectclass: inetOrgPerson cn: Sean Walberg cn: Sean A. Walberg sn: Walberg homephone: 555-111-2222 mail: firstname.lastname@example.org description: Watch out for this guy ou: Engineering
Before delving into the details of the LDIF file, note that the
attribute names are case insensitive. That is,
objectclass is the same as both
OBJECTCLASS. Many people choose to
capitalize the first letter of each word except the first, such as
The first line of the LDIF shows a UNIX-style comment, which is prefixed by a hash sign (#), otherwise known as a pound sign or an octothorpe. LDIF is a standard ASCII file and can be edited by humans, so comments can be helpful. Comments are ignored by the LDAP server, though.
Records in the LDIF file are separated by a blank line and contain a
list of attributes and values separated by a colon (:). Records begin
dn attribute, which identifies the
distinguished name of the record. Figure 1,
therefore, shows three records: the
cn=Sean Walberg RDNs, respectively.
Looking back at Figure 1, you can see the first record defined is the root of the tree. The distinguished name comes first. Next comes a list of all the attributes and values, separated by a colon. Colons within the value do not need any special treatment. The LDAP tools understand that the first colon separates the attribute from the value. If you need to define two values for an attribute, then simply list them as two separate lines. For example, the root object defines two object classes.
Each record must define at least one object class. The object class, in
turn, may require that certain attributes be present. In the case of
the root object, the
dcObject object class
requires that a domain component, or
dc, be defined, and the
organization object class requires that an
organization attribute, or
defined. Because an object must have an attribute and value
corresponding to the RDN, the
object class is required to import the
attribute. Defining an
o attribute is not
required to create a valid record.
description is also used on the root
object to describe the company. The purpose here is to demonstrate the
comment format. If your value needs to span multiple lines, start each
new line with a leading space instead of a value. Remember that
attribute: value pairs
defines multiple instances of the attribute.
The second record in Figure 1 defines an
organizationalUnit, which is a container
for people objects in this case. The third defines a user of type
inetOrgPerson, which provides common
attributes for defining people within an organization. Note that two
cn attributes are defined; one is also used
in the DN of the record. The second, with the middle initial, will
help for searching, but it is the first that is required to satisfy
the condition that the RDN be defined.
In the user record there is also an
does not correspond to the
organizationalUnit the user is in. The
container the user object belongs to can always be found by parsing
the DN. This
ou attribute refers to
something defined by the user, in this case a department. No
referential integrity is imposed by the server, though the application
may be looking for a valid DN such as
The only other restriction placed on LDIF files that add records is
that the tree must be built in order, from the root.
Figure 1 shows the root object being built, then
ou, then a user within that
ou. Now that the structure is built, users
can be added directly to the
container, but if a new container is to be used, it must be created
The LDIF behind adding objects is quite easy. The format gets more
complex when objects must be changed or deleted. LDIF defines a
changetype, which can be one of the
addadds an item (default).
deletedeletes the item specified by the DN.
modrdnrenames the specified object within the current container, or moves the object to another part of the tree.
moddnis synonymous with
modifymakes changes to attributes within the current DN.
Deleting an item is the simplest case, only requiring the
changetype. Listing 2 shows a user being
Listing 2. Deleting a user with LDIF
dn: cn=Fred Smith,ou=people,dc=ertw,dc=com changetype: delete
Manipulating the DN of the object is slightly more complex. Despite the
fact that there are two commands,
modrdn, they do the same thing! The
operation consists of three separate parts:
- Specify the new RDN (leftmost component of the DN).
- Determine if the old RDN should be replaced by the new RDN within the record, or if it should be left.
- Optionally, move the record to a new part of the tree by specifying a new parent DN.
Consider Jane Smith, who changes her name to Jane Doe. The first thing
to do is change her
cn attribute to reflect
the name change. Because the new name is the primary way she wishes to
be referred to, and the common name forms part of the DN, the
moddn operation is appropriate. (If the
common name weren't part of the DN, this would be an attribute change,
which is covered in the next section.) The second choice is to
determine if the
cn: Jane Smith should stay
in addition to
cn: Jane Doe, which allows
people to search for her under either name. Listing 3 shows the LDIF
that performs the change.
Listing 3. LDIF to change a user's RDN
# Specify the record to operate on dn: cn=Jane Smith,ou=people,dc=ertw,dc=com changetype: moddn # Specify the new RDN, including the attribute newrdn: cn=Jane Doe # Should the old RDN (cn=Jane Smith) be deleted? 1/0, Default = 1 (yes) deleteoldrdn: 0
Listing 3 begins by identifying Jane's record, then the
moddn operator. The new RDN is specified,
continuing to use a common name type but with the new name. Finally,
deleteoldrdn directs the server to keep the
old name. Note that while
newrdn is the
only necessary option to the
changetype, if you omit
action is to delete the old RDN. According to RFC 2849,
deleteoldrdn is a required element.
Should the new Mrs. Jane Doe be sent to a new part of the tree, such as
a move to
LDIF must specify the new part of the tree somehow, such as in Listing
Listing 4. Moving a record to a new part of the tree
dn: cn=Jane Doe,ou=people,dc=ertw,dc=com changetype: modrdn newrdn: cn=Jane Doe deleteoldrdn: 0 newsuperior: ou=managers,dc=ertw,dc=com
Curiously, a new RDN must be specified even though it is identical to
the old one, and the OpenLDAP parser now requires that
deleteoldrdn is present despite it being
meaningless when the RDN stays the same.
newsuperior follows, which is the DN of the
new parent in the tree.
One final note on the
modrdn operation is
that the order matters, unlike most other LDIF formats. After the
changetype comes the
newrdn, followed by
deleteoldrdn, and, optionally,
modify, which is used to modify attributes
of a record. Based on the earlier discussion of
moddn, it should be clear that
modify does not apply to the DN or the RDN
of a record.
Listing 5 shows several modifications made to a single record.
Listing 5. Modifying a record through LDIF
dn: cn=Sean Walberg,dc=ertw,dc=com changetype: modify replace: homePhone homePhone: 555-222-3333 - changetype: modify add: title title: network guy - changetype: modify delete: mail -
The LDIF for the
modify operation looks
similar to the others. It begins with the DN of the record, then the
changetype. After that comes either
delete:, followed by the attribute. For
delete, this is enough information. The
others require the attribute:value pair. Each change is followed by a
dash (-) on a blank line, including the final change.
LDIF has an easy-to-read format, both for humans and computers. For bulk import and export of data, LDIF is a useful tool.