LDAP (Lightweight Directory Access Protocol) has a reputation for being complicated, but I hope to dispel that myth and explain exactly how LDAP works in this simple introduction of some of the basic concepts..
LDAP is a lightweight protocol for accessing directory servers. Okay, so what is a directory server? It’s a hierarchical object orientated database. If that makes you want to run away screaming, don’t worry, it’ll get worse before it gets better.
Only joking. This guide should make learning LDAP easy. Let’s go through that description bit by bit, starting at the end. It’s a database, which means we can store data in it. If you’ve used relational databases, like mysql, then it won’t look like anything you’re used to, but like a relational database, it allows you to store your data in a user defined structural way.
The second part of our description was object orientated. In LDAP our database is a collection of objects. Like in OO programming, objects are instances of a particular class. A class defines the set of attributes that an object may contain. Classes can inherit from other classes to add additional attributes. LDAP has some differences from the usual OO semantics, which will be explained in the next section.
The final part of our description was hierarchical. Every object in LDAP can contain one or more sub-objects. The result is a tree with the trunk being the root of the directory and the branches and leaves being the objects in the directory. In this way we can build up our database into an easy to navigate, structured database.
Lightweight? Lightweight? What crack are you on?
Sometimes you wonder how anyone could describe this complicated mess as lightweight. The lightweight is in reference to the previous leading standard for directory services, called X.500. The problem with X.500 was that it required the use of the OSI network stack and couldn’t use TCP/IP. It was also rather more complicated. LDAP only uses 9 of the operations that X.500 supported, and can use the simpler TCP/IP networking stack.
As I mentioned, data stored in LDAP is stored in objects. These objects contain a number of attributes, which are basically a set of key/value pairs. Because data in LDAP is structured, objects can only contain valid keys, and which keys are valid is dependant on what class the object is. Classes in LDAP can define mandatory attributes and optional attributes and their type.
To confuse matters (and this is where LDAP deviates from most OO systems) objects can have more than one class and there are several types of class.
The first type is the structural class. An object must have one and only one structural class. Structural classes tend to map to physical objects like a person or a network. Once an object has been created the structural class can not be changed without destroying the object and creating it again.
Auxiliary classes define additional attributes to complement structural classes. Objects may have many auxiliary classes and can be added and removed after the object has been created.
Finally there are abstract classes, which can not be used directly by objects, but can be used by other classes through inheritance.
Classes are assigned to objects using the objectClass attribute. LDAP defines some basic classes, types and comparison methods by default, but you are free to define your own.
It’s well and good me telling you all this, but it probably won’t make sense until I show you some examples. A common use for LDAP is an address book, so you could use the personclass, which is structural. It defines sn and cn as mandatory attributes and userPassword,telephoneNumber, seeAlso and description as optional fields. A couple of those attributes probably need explaining. sn is surname and cn is common name, which we can use to store the person’s full name. The dashed line in the image marks the mandatory and optional attributes.
But what if we wanted to store addresses in the object too? Well if we had used theorganizationalPerson, which inherits from the person class, but adds title, street,postalAddress and postalCode. The class adds several more attributes too. Because it inherits from person we still have sn and cn. There is an even more comprehensive class called inetOrgPerson.
Another common use for LDAP is authentication of user accounts. For this, we can use theposixAccount class. This is an auxiliary class and adds cn, uid, uidNumber, gidNumber andhomeDirectory mandatory attributes and userPassword, loginShell, gecos and description as optional attributes. Because posixAccount is auxiliary, we can add it to our person object for people we want to be able to authenticate.
One very important aspect I have omitted to mention is the dn or distinguished name. This is a unique name used to refer to a particular object in the tree. It’s made up from the dn of the parent object and a unique key/value pair from the sub-objects. For example if you stored your address book under ou=People,dc=example,dc=com, a common location, my details would have a dn of cn=David Pashley,ou=People,dc=example,dc=com and Bill Gates would have a dn of cn=Bill Gates,ou=People,dc=example,dc=com. As you can see each level in the hierarchy is separated by commas. It is possible to have multi-attribute distinguished names by putting a + between the attributes. Distinguished names are not actually attributes of objects.
I should explain that ou is an organizational unit and dc is domain component. In our database we are storing all our objects below dc=example,dc=com and is called the base dn because it is the base of our database. While you don’t need to use a unique base dn for your database, it is common practice to do so and is more important if you intend to make your database publicly available. Originally databases used to be based on your location (o=Catnip,l=Brighton,st=Sussex,c=uk), but it is much more common now to use a DNS domain that you own as the basedn (dc=catnip,dc=org,dc=uk).
Earlier we used ou in a dn. This is merely a class for grouping our data into sections for administrative ease. There are no rules that force you to organise your database in any particular way, but there are several common ways of laying out databases. The actual layout of the directory tends to not be that important to applications using the directory as they can do recursive queries for the objects they are interested in. We could have our address book in ou=People,dc=example,dc=com and a list of computers inou=Computers,dc=example,dc=com. If we had a very simple database we could easily mix both into one location and have people and computers as sub-objects of dc=example,dc=com. Alternatively, if we had a very large authentication database, we could go the other way and split the people into several organizational units mirroring their departments, so we could have the sales department in ou=Sales,dc=example,dc=com and marketing inou=marketing,dc=example,dc=com. Using this scheme you could delegate control for the sales tree to the Sales Manager and the marketing tree to the Marketing Manager, which may not be possible with other schemes.