Small LDAP Server Setup

This document assumes:

  • You have basic Unix sysadmin knowledge and can read manpages and similar documentation yourself.
  • You want to use LDAP to perform authorization (access rights, who has access to what) and/or authentication (looking up passwords when logging into a service).
  • This is for a small home or single office setup, not a big hierarchy of employees/customers/students. (Of course, its probably best to learn how to do it on a small scale before attempting that, so read on).
  • Your organisation is simple enough that you will not have to delegate modifications to parts of the system to other users (e.g. you have tech support call center staff and you want to give them the ability to change passwords, or you have enrolment/HR staff and you want to delegate the ability to create accounts to them. This is an excellent use case for LDAP, just beyond the scope of this page.

Note: Examples are for FreeBSD and may need minor changes for other OS.

LDAP Data Model Introduction

This is the most important thing to understand first as it affects how your database and directory are set up.

  • Everything stored in LDAP is stored in a hierarchical tree called the “Data Information Tree” or DIT (hence the “Directory” part of LDAP).
  • Each node may have one or more children; each non-root node has exactly one parent.
  • The root of the tree is also called the base or suffix in some places.
  • Nodes of the tree are called entries; each is of a particular Object Class.
  • Each Object Class (and thus each entry) has one or more attributes, including one or more naming attributes (usually just one). The naming attribute(s) of an entry are unique amongst all other entries with the same parent.
  • Common naming attributes are “Organisational Unit Name” (OU), “Domain Component” (DC - part of a DNS domain) and “Common Name” (CN). These will be discussed in more detail later.
  • The distinguished name (DN) is a unique, absolute identifier for a node. It consists of the naming attribute for that node followed by the naming attribute for each parent (see examples below).

How to format entries (LDIF) - Part 1

LDIF is the LDAP Data Interchange Format, and is generally how LDAP entries are inserted into and exported from the system (regardless of how they are stored internally). It consists of three parts:

  1. The distinguished name of an LDAP entry is written by naming each node in its hierarchy, from the leaf on the left up to the root on the right (like DNS).
  2. The object class of the entry.
  3. Each attribute is written in the form [attribute-abbreviation]=[value].

e.g.: User Dylan, part of organisational unit students, at the foobar Australian university at foobar.edu.au:

# Suffix / Root / Base:
# DC = Domain Component = DNS
rootdn: dc=foobar,dc=edu,dc=au

# The student group:
dn: ou=student,dc=foobar,dc=edu,dc=au
ObjectClass: organizationalUnit
cn: student

# The staff group:
dn: ou=staff,dc=foobar,dc=edu,dc=au
ObjectClass: organizationalUnit
ou: staff

# My entry:
dn: cn=Dylan,ou=students,dc=foobar,dc=edu,dc=au
ObjectClass: person
cn: Dylan
sn: Leigh
userPassword: secret
telephoneNumber: 01234567

Things to note about the example:

  • IMPORTANT: The “cn”/”ou”/”dc” in the distinguished name are NOT the names of the classes. They are the names of the naming attributes.
  • Each entry in the hierarchy has other attributes which we don’t see here; for example, the “Dylan” entry could have password, home directory location, etc. The “Students” and “Staff” entries could have some access control lists. The naming attribute is the only one used in the name.
  • Note the use of "dn: [...]" to identify a distinguished name for each object we are describing - including the new naming attribute.
  • Note the root entry is composed of multiple naming attributes, in order.

Structure of your tree (DIT)

Root/Suffix

There are three common methods to choose a root:

1. The most common, RFC 2247 way: use your registered domain name as the suffix. (See the example above). This has the advantage of being as unique everywhere as DNS is, and can make lookups easier.

2. The ITU, X.500 way: use a suffix in the form of “ou=organisation name,c=country code” - for example, “ou=foobar,c=au”. Note that the ou (“Organisational Unit”) attribute is used by X.500 for the organisation name, not the “Organisation” attribute (see below).

3. Some prefer to use a simple organisation name name for their root, e.g. “ou=foobaruniversity”. This is adequate if your server will not need to communicate with others.

Directory Structure/Hierarchy

Note the use of the “staff” and “student” organisational units in the example above.

The directory structure can be as simple or complex as you wish, but it is often best to go with a simpler (i.e. flatter) structure, and put details such as the department or school in an attribute of the entry. A flatter structure is easier to search, write queries for, and maintain in general.

You will often want to perform a search on all users. With a complex hierarchy, a recursive search on a large chunk of the tree to find all users is more complex and risks missing some by getting the query wrong. On the other hand, if all users are in one group or unit, the search is simple. The opposite problem (performing a query on just one department or school) is easily accomplished in a flat hierarchy by filtering on an attribute such as “school=science”.

A modification example: When Alice changes major from Science to Engineering you can just change the “school” or “department” attribute. If the schools were seperated in the hierarchy, you have to move her entry in the tree. This is a more complex operation, and involves changing the canonical name of her entry, possibly breaking something which depended on that name, and possibly causing a name clash.

For these reasons, most organisations are best served by a very flat hierarchy - the structure below is common:

Suffix / Root / Base: dc=xyzzy,dc=org
The people group, with everyone: ou=people,dc=xyzzy,dc=org
Everyone's DN: cn=[username],ou=people,dc=xyzzy,dc=org

A hierarchical structure is most important when you have multiple servers and are delegating some of the work to others (beyond the scope of this document). Also, where entries have significantly different requirements, such as between staff and students, or employees and customers, these should generally be seperated in the hierarchy. But don’t put things like school, office, or department in the hierarchy - these should be attributes.

One particular use of a hierarchy with OrganisationalUnit is where you want to create a shared account on a service accessible to all users in that group. Look at the OrganisationalUnit and OrganisationalRole Object Classes below for more details.

Choosing ObjectClasses

This should be easy, but its not. LDAP comes with schemas of many classes, most of which almost (but not quite) do what you want, but include lots of other stuff you don’t care about.

Note that classes themselves have a hierarchy like OOP classes; some inherit from others, and inherit the compulsory and noncompulsory attributes of their parent class.

Some Person Classes

person
Must have sn (surname) and cn (common name) - optionally may have userPassword, telephoneNumber, seeAlso, description. As this isn’t much, subclasses of person are usually used.
organizationalPerson
Inherits from person; no more required attributes, but includes many optional ones such as postal address, and lots of obsolete junk like teletexTerminalIdentifier.
inetOrgPerson
The most common class used to represent a person in an organisation. Inherits from organizationalPerson; no extra required attributes; many useful optional attributes including employeeNumber, givenName, mobile, uid, mail… even jpegPhoto.

Account Classes

account
Must have a userid; may have description, organizationalUnitName, host and a few others.
posixAccount

For Unix/Posix account details. Could be used as an alternative to one of the person classes above in some situations.

Compulsory: cn, uid, uidNumber, gidNumber, homeDirectory.

Optional: userPassword, loginShell, gecos, description…

Other Common Classes

dcObject
Used for DNS components (see examples above), this has one required attribute (DC), and no others.
organizationalUnit

Used to represent organisational units or groups at any level or scale, up to an including the organisation itself.

ou” (organisational unit name) is the only required attribute; optional ones include userPassword (for shared account passwords), description, many forms of address and phone/fax numbers.

organizationalRole

Often used to set up Roles which may be filled by one or more users, like “WebAdmin”, “TechSupport”, “Postmaster”, “SecurityOfficer” “etc.

Similar structure to organizationalUnit, but requires “cn” (common name) instead of “ou” and has no userPassword attribute.

Less Common Classes

organisation

Requires “o” (organisation name); similar in structure to organizationalUnit, even includes userPassword.

In practice, organizationalUnit is usually used for the organization.

device
Requires “cn”, optional attributes include serialNumber, owner, “ou” and “o”

Using LDAP as a contact directory

As can be seen from the attributes above, a lot more can be stored in LDAP than just usernames, passwords and access rights. You can store address and other contact details of your organisation, other organisations you work with, device inventory….

The disadvantage of putting everything in LDAP is that it means merging your authorization (and probably authentication) database and your contact database. You may not want to expose the same system you use to store passwords and determine access rights to use as a general purpose phone directory. It is best for security to keep your security systems free from other tasks.

That said, there are some hardware devices which do their authentication and authroization and contact information lookups all via LDAP. If you’re working with those, to make use of their capabilities you will need to store contact details in LDAP and make sure the access control is set so they have access to contact attributes but not secret attributes (like userPassword!)

Work in Progress

TODO: Installation and choosing backends, Slapd configuration, the bad-security defaults, etc.