|Linux System Administration|
OpenLDAP provider on Debian lenny
Back in the mid 1980s, before the Internet and its TCP/IP protocol suite became popular, two standards organizations, the ITU-T (then known as the CCITT) and the ISO, were busy developing their own standards for network communications. They had already produced the OSI Transport service, which was an advance in network communications, and also X.400; a collection of data communication standards for what was basically an e-mail service. However, more standards needed to be defined before any of this could be used as part of a global communications system.
The two organizations were looking for solutions. The ITU-T was hoping to develop a white pages service that would return either people's phone numbers or X.400 O/R addresses, while the ISO mostly wanted a name server service for OSI applications. Not wanting to duplicate each other's efforts, they decided to pool their resources. Together they produced a set of networking standards in 1988, called X.500, for what was described as a directory service.
X.500 is an elaborate collection of protocols, specifications and definitions centered around the concept of a single, distributed, replicated, global Directory Information Tree (DIT), capable of storing all kinds of information that would be accessible via the Directory Access Protocol (DAP). The whole system would take off as soon as organizations everywhere started to publish their own directory information, or subsets thereof, in the global DIT. Unfortunately, this never happened, perhaps because most organizations considered their own directory information to be too valuable, or too confidential, to be made available to the world at large in the form of an X.500 directory sub-tree.
However, the concept of a private DIT, and a DAP with which to access it, was regarded as worthy enough in its own right. It just needed to be simplified somewhat. To this end, the Lightweight Directory Access Protocol (LDAP) was defined in 1993 (RFC-1487), giving clients access to an X.500-based DIT via TCP/IP without incurring the costly resource requirements associated with the X.500 DAP. The third and current version of LDAP was published in 1997 (RFC-2251), with a technical specification (RFC-3377) following in 2002.
First released 1998, OpenLDAP is the popular open source implementation of LDAP. With it, anyone can create their own DIT and, unfettered by vendor limitations, decide for themselves what to use it for. All kinds of information can be stored in it − anything from host configuration data to names and addresses − and accessed from anywhere using the many different LDAP-compatible applications.
A DIT is a hierarchically organized collection of entries, each identified by a Distinguished Name (DN); a unique, comma-separated list of components that provide the path to an entry from the top of the tree. For instance, the DN of the root of a DIT for a company called Example Corp. might be dc=example,dc=com, while the DN of someone employed there might be cn=JoeSmith,ou=People,dc=example,dc=com. Notice how each DN consists of multiple key=value pairs. The keys in these example DNs stand for Common Name (cn), Organizational Unit (ou) and Domain Component (dc).
All LDAP entries are typed, meaning that each DN belongs to an objectClass that identifies the type of information it represents. In turn, each entry consists of multiple attributes that also consist of key=value pairs, each of which is defined by a certain attributeType. These objectClasses and attributeTypes are defined in schema files. This allows an LDAP administrator to decide which schema files to include, based on the needs of the applications that will be using the DIT.
In this example, OpenLDAP is installed on a host running Debian 5.0 (lenny). If followed properly, the step-by-step process should produce a provider server with a new DIT. Actually, OpenLDAP used to refer to master and slave servers, but this has been depricated in favor of, respectively, provider and consumer servers, since the differences between them are not as distinct as they once were. This is because some consumers may now also act as providers for other LDAP hosts.
Before the actual OpenLDAP installation process can begin, it will first be necessary to install Debian lenny on a new host called ldaps1.example.com. A DNS server must also be available on the network with a zone file to which forward and reverse mappings can be added for this host, as well as an alias for it called ldaps.example.com. After the initial installation of the operating system, make sure these packages are installed on the system as well:
~# apt-get install ssh nmap
Now the installation process for the OpenLDAP provider server can begin:
1. Package installation
On the new host, ldaps1.example.com, start by installing these two packages:
~# apt-get install slapd ldap-utils
A total of ten packages are installed as a result, including eight dependencies:
ldap-utils 2.4.11-1 OpenLDAP utilities libdb4.2 4.2.52+dfsg-5 Berkeley v4.2 Database Libraries [runtime] libltdl3 1.5.26-4 A system independent dlopen wrapper for GNU libtool libperl5.10 5.10.0-19lenny2 Shared Perl library libsasl2-modules 2.1.22.dfsg1-23+lenny1 Cyrus SASL - pluggable authentication modules libslp1 1.2.1-7.5 OpenSLP libraries odbcinst1debian1 2.2.11-16 Support library and helper program for accessing odbc ini file psmisc 22.6-1 Utilities that use the proc filesystem slapd 2.4.11-1 OpenLDAP server (slapd) unixodbc 2.2.11-16 ODBC tools libraries
During the install process, an administrator password will be requested for slapd. Use piscivorus:
Administrator password: piscivorus Confirm password: piscivorus
Run the following command to test if the OpenLDAP server is actually running:
~# nmap ldaps1.example.com
This should be among the results:
PORT STATE SERVICE 389/tcp open ldap
The ldap service is made available by the Standalone LDAP Daemon (slapd). To be sure, the LDAP v3 technical specification (RFC-3377) does not mention anything about a backend solution in which to store the database; it is only a description of the network protocol itself. The daemon, slapd, the way it stores its data and the various utilities it comes with are unique to OpenLDAP.
Perform a quick test by generating an LDIF dump of the contents of a the database:
~# slapcat dn: dc=example,dc=com objectClass: top objectClass: dcObject objectClass: organization o: example.com dc: example structuralObjectClass: organization entryUUID: 6d22e2e8-6e30-102e-9761-05effbdceeba creatorsName: createTimestamp: 20091125170507Z entryCSN: 20091125170507.217451Z#000000#000#000000 modifiersName: modifyTimestamp: 20091125170507Z dn: cn=admin,dc=example,dc=com objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator userPassword:: e2NyeXB0fU1TVXFoNlFiZlp0MXM= structuralObjectClass: organizationalRole entryUUID: 6d237c58-6e30-102e-9762-05effbdceeba creatorsName: createTimestamp: 20091125170507Z entryCSN: 20091125170507.221751Z#000000#000#000000 modifiersName: modifyTimestamp: 20091125170507Z ~# _
If the output looks something like the above, continue with the next step.
Edit /etc/ldap/ldap.conf and add these two lines to the end of the file:
BASE dc=example,dc=com URI ldap://ldaps1.example.com/
This configuration file is used to set system-wide defaults for LDAP clients.
The daemon for the OpenLDAP stand-alone LDAP server is called slapd. Edit its configuration file, /etc/ldap/slapd.conf, and make two changes to it. The first, in the Global directives section, is to comment out the line that prevents anything being written to the logs:
This allows slapd to use the default loglevel, which is 256 (stats). Basically, the value for loglevel is set to an integer (1, 2, 4, 8, 16, etc.), all of which are additive and cause slapd to log different kinds of information. However, certain keywords that represent the different values, can also be used instead (see man slapd.conf).
Second, search for its only existing equality (eq) index directive and add a second one below it:
index objectClass eq index uid eq
This is how slapd is instructed to maintain indexes for certain attributes in order to optimize directory searches. The new index will speed up searches for entries based on exact matches of the uid attribute. At the moment it is not strictly necessary to add any extra indexes, since the directory contains almost no data, but it is recommended for the uid attribute, which is used for storing user account names. Later on, as the DIT grows in size, this setting may significantly decrease the time it takes for users to log in.
After saving the configuration file, restart slapd to activate the changes:
~# /etc/init.d/slapd restart Stopping OpenLDAP: slapd. Starting OpenLDAP: slapd. ~# _
4. Basic tree
Create a basic tree structure. First create a file, ~/tree.ldif, with the following content:
dn: ou=people,dc=example,dc=com ou: people objectClass: organizationalUnit dn: ou=groups,dc=example,dc=com ou: groups objectClass: organizationalUnit
Add this information to the LDAP database with the ldapadd command:
~# ldapadd -cxWD cn=admin,dc=example,dc=com -f ~/tree.ldif Enter LDAP Password: piscivorus adding new entry "ou=people,dc=example,dc=com" adding new entry "ou=groups,dc=example,dc=com" ~# _
Five different options are used for this ldapadd command:
Perform a test. Run an ldapsearch with an anonymous bind (no DN specified) to check that the new organizational units have indeed been added to the database. Check that the output looks like the following and does not contain any obvious errors:
~# ldapsearch -xLLL dn: dc=example,dc=com objectClass: top objectClass: dcObject objectClass: organization o: example.com dc: example dn: cn=admin,dc=example,dc=com objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator dn: ou=people,dc=example,dc=com ou: people objectClass: organizationalUnit dn: ou=groups,dc=example,dc=com ou: groups objectClass: organizationalUnit ~# _
The -L option used here causes the results to be displayed in LDAP Data Interchange Format (LDIF). A second -L will disable comments, while a third one will prevent the LDIF version from being printed. The default is to use extended LDIF.
5. User account
Create a new user account, called ccolumbus. First create a file, ~/ccolumbus.ldif, with the following contents:
dn: cn=ccolumbus,ou=groups,dc=example,dc=com cn: ccolumbus gidNumber: 20000 objectClass: top objectClass: posixGroup dn: uid=ccolumbus,ou=people,dc=example,dc=com uid: ccolumbus uidNumber: 20000 gidNumber: 20000 cn: Christopher sn: Columbus objectClass: top objectClass: person objectClass: posixAccount objectClass: shadowAccount loginShell: /bin/bash homeDirectory: /home/ccolumbus userPassword: NewWorld
Add this information to the DIT with the ldapadd command:
~# ldapadd -cxWD cn=admin,dc=example,dc=com -f ~/ccolumbus.ldif Enter LDAP Password: piscivorus adding new entry "cn=ccolumbus,ou=groups,dc=example,dc=com" adding new entry "uid=ccolumbus,ou=people,dc=example,dc=com" ~# _
Run an ldapsearch for the new ccolumbus entry to check if the response seems reasonable and does not contain any errors. The output should look like this:
~# ldapsearch -xLLL uid=ccolumbus dn: uid=ccolumbus,ou=people,dc=example,dc=com uid: ccolumbus uidNumber: 20000 gidNumber: 20000 cn: Christopher sn: Columbus objectClass: top objectClass: person objectClass: posixAccount objectClass: shadowAccount loginShell: /bin/bash homeDirectory: /home/ccolumbus ~# _
It is possible to test authentication for an LDAP account with the ldapwhoami command:
~# ldapwhoami -xD uid=ccolumbus,ou=people,dc=example,dc=com \ -w NewWorld dn:uid=ccolumbus,ou=people,dc=example,dc=com ~$ _
This is also an example of a password that is specified on the command line using the -w option.
Anyway, when using only simple authentication, a DN to bind to and a password must be included or else the binding will be anonymous:
~# ldapwhoami -x anonymous ~# _
The same applies to ldapsearch when using simple authentication. In all such cases the principle is the same: authentication and authorization must take place before any such single commands are processed.
6. See also
7. Further reading