LDAP (Lightweight Directory Access Protocol) is a network protocol for querying and updating structured data. This data is built from the following components:
- attributes -- key-value pairs of data consisting of an attribute name and a value. For example, an attribute called ipAddress and an associated value of 203.0.113.64. Attributes also have an associated syntax, which in this example you might expect to restrict valid values to be four dotted octets. Many LDAP directory servers can impose further restrictions and access controls on individual attributes.
- objects -- collections of attributes to represent a higher level entity. Things like user accounts or people or network hosts. The attributes that make up a given object are defined by the schema, which defines which attributes MAY be present on an object of a given class, and which attributes MUST be present, as well as whether multiple values are allowed. An object may be made up of multiple object classes. As an example, it might be possible to have a single object that is made up of the attributes for a user account object class and a person object class.
- tree structured -- LDAP directories present these collections of objects and attributes in a tree-like structure, which is extensible just as with the objects and attributes described above. However, where objects and attributes are often defined by applications and defacto standards, the structure of the directory is generally up to the administrator and their business needs. All branches and nodes in an LDAP directory are LDAP objects as defined above. Any object can contain child objects.
The way to identify a particular object within an LDAP directory tree is by the full path the object from the root. This is known as the object's distinguishedName, or dn. In a filesystem, a file's absolute pathname describes the location of the file from the root directory and includes every subdirectory to traverse to find the file. LDAP DNs are functionally the same, but the order is reversed and the root is depicted on the right-hand side of the DN. We'll see a complete example shortly.
When importing or exporting LDAP objects or attributes, the LDIF data format is most-often used. We'll use LDIF format extensively throughout to give examples as we go. In its most basic form (we're going to skip the part of LDIF that deals with modifications for now), the LDIF format is simply a textual representation of one or more LDAP objects (separated by a blank line) as a collection of attribute names and their values separated by a colon character.
This is an example of an LDAP object represented in LDIF form:
dn: dc=incomplete, dc=io objectClass: dcObject objectClass: top objectClass: organization dc: incomplete o: Incomplete I/O description: The place where bytes get bit.
Here's a few things to note about the above example:
- The dn attribute represents the distinguished name of, or the path to, the object. In this case, the path is dc=incomplete,dc=io
- This object is made up of three different classes of object: a dcObject, an organization, and something called top. The latter is a basic object that many other objects inherit from.
- The dcObject object class requires that an attribute called dc is present, which we see here.
- Finally, the organization object class requires that an o attribute exists to represent the organisation, and allows a description attribute to be present. This object's LDIF definition is terminated by a blank line.
In this particular example, this is a representation of the root of an LDAP directory for incomplete.io. The dc attributes refer to domain components in the domain name.
Extending on the above, we'll take a look at another example of LDIF:
dn: ou=People, dc=incomplete, dc=io objectClass: organizationalUnit ou: People description: An LDAP container to store People objects dn: ou=Groups, dc=incomplete, dc=io objectClass: organizationalUnit ou: Groups description: An LDAP container to store Group objects dn: cn=Alice McCracken, ou=People, dc=incomplete, dc=io objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson cn: Alice McCracken sn: McCracken givenName: Alice mail: firstname.lastname@example.org preferredLanguage: en-gb labeledURI: http://incomplete.io incomplete.io mobile: +1 408 555 0123
- We're representing two more container objects -- generic organizationalUnit objects. These could be use to organise a company's LDAP objects in whichever fashion meets their business needs. Another commonly-cited example is to separate objects by business function -- Sales, Marketing, Operations, etc. These can be nested.
- We have an object under the People container to represent a person. This person inherits from the person, organizationalPerson and inetOrgPerson object classes.
- Looking at the schema for these object classes, we'd see that we're required to include the sn (surname) and cn (commonName) attributes and are allowed to include the rest, with many allowed attributes not being specified here.
- The above representation of Alice is generally enough to back something like a corporate addressbook to be consumed by many LDAP-capable email clients.