OpenLDAP

From SaruWiki
Jump to navigation Jump to search

Note: if you need information on the OpenLDAP version from Debian 5.0, see this page: OpenLDAP 2.4.11

OpenLDAP installation

Note: we're going to install OpenLDAP on our server as the local directory service, without replication, referrals or other advanced features. Under Debian Squeeze, this is OpenLDAP 2.4.23.

Standard installation

Installing OpenLDAP on your Debian server is ridiculously simple. Just make sure your server is up-to-date (sudo apt-get update followed by sudo apt-get upgrade), and then install the two main components for your OpenLDAP server. First off: the LDAP client and utilities

sudo apt-get install ldap-utils

This will result in the installation of as much as 8 different packages (ldap-utils, libgcrypt11, libgnutls26, libgpg-error0, libldap-2.4-2, libsasl2-2, libsasl2-modules, and libtasn1-3). Next the main component of an LDAP server installation, the stand-alone LDAP daemon "slapd"

sudo apt-get install slapd

This may also install up to 8 packages (slapd, libltdl7, libperl5.10, libslp1, odbcinst, odbcinst1debian2, psmisc and unixodbc).

The Debian configuration script will ask you for only one single thing: an administrator password. As always: generate a strong password! After you've provided the password, the LDAP database is created with the administrator name "admin" and as a base directory, something based on your DNS name. Suppose your internal domain is "amber.lan", then the script will generate suffix "dc=amber,dc=lan"<ref>Should you see a third, empty, domain component (dc=) then this is caused by a trailing dot in your particular DNS name: the DNS root. You might have specified your domain as "amber.lan.". You should change your domain name to a name without the DNS root, and you must regenerate your LDAP directory.</ref>. The above method of configuring yields you an LDAP database with only two objects in it. Suppose your DNS name is "easton2.amber.lan", then the two objects are:

  • a single Organization (o="amber.lan") with Distinguished Name dn="dc=amber,dc=lan"
  • a single administrator with Common Name cn="admin", and dn="cn=admin,dc=amber,dc=lan"

Note, however, that there's also a second LDAP database, "cn=config", which on your server is located under /etc/ldap/slapd.d. We'll cover what's in it further on. <references/>

Testing the installation

After installation of the package, it should automatically have been started, and should now be operational. This can be checked with a utility like nmap:

root@easton2:~# nmap -p 389 localhost

Starting Nmap 5.00 ( http://nmap.org ) at 2011-04-13 21:19 CEST
Interesting ports on localhost (127.0.0.1):
PORT    STATE SERVICE
389/tcp open  ldap  

Nmap done: 1 IP address (1 host up) scanned in 0.40 seconds
root@easton2:~#_

Another way to test if the LDAP server is functional, is by querying it with the ldapsearch utility, part of the package ldap-utils. Let's see if we can find the naming context of the LDAP server:

root@easton2:~# ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts
# extended LDIF
#
# LDAPv3
# base <> with scope baseObject
# filter: (objectclass=*)
# requesting: namingContexts
#

#
dn:
namingContexts: dc=amber,dc=lan

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1
root@easton2:~# _

With this command, we do a search using

  • basic authentication (instead of one encrypted with SASL),
  • searching within the LDAP tree from base '' (meaning the absolute root of the tree),
  • looking for base object only (instead of a one-level search, a subtree search, or a children-search),
  • filtering for objects of any class,
  • asking for the naming context of the result.

The output shows that the server responds; two objects have been considered, but none match the filter (that the object should have an objectClass).

Let's now do the same but with authentication, to see if we can bind to the LDAP server. We'll first use an incorrect password, then the correct one:

root@easton2:~# ldapsearch -W -D "cn=admin,dc=amber,dc=lan"
Enter LDAP Password:
ldap_bind: Invalid credentials (49)
root@easton2:~# ldapsearch -W -D "cn=admin,dc=amber,dc=lan"
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# search result
search: 2
result: 32 No such object

# numResponses: 1
root@easton2:~# _

Finally, you could simply install and run a graphical management tool for LDAP servers, like Apache Directory Studio. Note however that if this check fails, then this could also mean problems with firewalls, network connections et cetera.

Post-install reconfiguration

Since the default configuration with the server's DNS domain as LDAP base might not always be the most convenient configuration, you could run the configuration again using dpkg-reconfigure slapd. However, following this procedure is only necessary if you want to change any of the default installation values like the backend database type or DNS domain name; things like the organization name can be edited with other means, as will be shown later on.

To be able to reconfigure the LDAP service, you can run the reconfiguration command sudo dpkg-reconfigure slapd. Contrary to some older versions of Debian, you do not need to manually stop the slapd daemon, and you don't need to manually remove the old configuration or database (in fact, if you do, then the slapd package will break, so you cannot easily remove it with APT tools). Interestingly enough, this reconfiguration asks you many more questions. The answers could look like this:

omit OpenLDAP config:  no
DNS domain name:       saruman.biz
Organization name:     Saruman
Administrator passwd:  wEt3udes
Database backend:      HDB
DB remove after purge: yes
Move old DB:           yes
Allow LDAPv2:          no

As you can see, the reconfiguration yields much more configuration options than plain installation - although really you'll probably answer most questions with their default values anyway. The above method of configuring yields you an LDAP database with only two objects in it:

  • a single Organization (o="Saruman") with Distinguished Name dn="dc=saruman,dc=biz"
  • a single administrator with Common Name cn="admin", and dn="cn=admin,dc=saruman,dc=biz"

Also note that the reconfiguration creates a backup of the "old" LDAP database in a directory with a name like /var/backup/unknown-2.4.23-7.ldapdb; if you just reconfigured after installation, then you probably don't need this backup, so you can remove it.

The database that your OpenLDAP server uses is a standard Berkeley DB (BDB/HDB) database. Now we most likely will require some other databases as well in our server setup, something modern like PostgreSQL or MySQL - so why don't we configure our OpenLDAP to use this same database as well? For the answer, see here - in short, the LDAP tree structure does not lend itself very well to inclusion in a modern relational database. Thus, we advise to stick with the Berkeley database provided with OpenLDAP. Now, for the database backend, we have the choice between two almost identical flavours:

  • the bdb backend used to be the recommended primary backend for a normal slapd database. It uses the Oracle Berkeley DB package, referred to as BDB, to store data. It makes extensive use of indexing and caching to speed data access.
  • the hdb backend is a variant of the bdb backend that uses a hierarchical database layout which supports subtree renames. It is otherwise identical to the bdb behavior, and all the same configuration options apply.

In Debian 6.0 "Squeeze" with OpenLDAP 2.4.23, HDB is the default backend.

OpenLDAP server configuration

(text from http://www.rjsystems.nl/en/2100-d6-openldap-provider.php) As of OpenLDAP 2.4.23-3, the slapd runtime configuration is fully LDAP-enabled. The default is to manage it using the standard LDAP operations with data in LDIF. The old slapd.conf format is still supported, but since that file must now be converted to the new slapd-config format to allow runtime changes to be saved, it seems likely that the developers will eventually phase it out. Therefore, we'll focus only on the new configuration method, the main advantage of which is that any changes made are immediately active, so it is no longer necessary to restart slapd after making configuration changes.

The new configuration format uses a slapd backend database that is found in the /etc/ldap/slapd.d/ directory. The configuration is stored as a special LDAP directory with a predefined schema and DIT, the root of which is called cn=config. If you go look there, you'll find that most parts of this LDAP directory consist of editable flat files.

Check the current LDAP configuration

From the command line, there really are several ways to check the current LDAP configuration:

  • from the server itself, you can use the trusty ldapsearch command, running under root: this'll authenticate with user ID 0. Filtering only for distinguished names:
root@easton2:/etc/ldap# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: cn=config

dn: cn=module{0},cn=config

dn: cn=schema,cn=config

dn: cn={0}core,cn=schema,cn=config

dn: cn={1}cosine,cn=schema,cn=config

dn: cn={2}nis,cn=schema,cn=config

dn: cn={3}inetorgperson,cn=schema,cn=config

dn: olcBackend={0}hdb,cn=config

dn: olcDatabase={-1}frontend,cn=config

dn: olcDatabase={0}config,cn=config

dn: olcDatabase={1}hdb,cn=config

root@easton2:/etc/ldap# _
  • to get an idea of what the cn=config database looks like within LDAP itself, you can run this command:
root@easton2:/etc/ldap# slapcat -b cn=config
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/slapd/slapd.args
olcLogLevel: none
olcPidFile: /var/run/slapd/slapd.pid
olcToolThreads: 1
(more LDIF texts)
entryUUID: f2a8f568-fa40-102f-8b9d-5d4cbccf32a9
creatorsName: cn=admin,cn=config
createTimestamp: 20110413174103Z
entryCSN: 20110413174103.641065Z#000000#000#000000
modifiersName: cn=admin,cn=config
modifyTimestamp: 20110413174103Z
root@easton2:/etc/ldap# _
As you can see, this generates a pretty large LDIF dump of the contents of the cn=config directory. Much of it consists of schema information. The LDAP configuration directives are attributes of the directory entries (objects) and most them start with the prefix "olc" (OpenLDAP Configuration). Also, some of the objects have names with numbers between curly brackets. This is to compensate for the fact that LDAP databases do not store their contents in any particular order; they are inherently unordered. The numbers constitute a numeric index to ensure a consistent order in the configuration database and thereby preserve all ordering dependencies. The index numbers, however, are generated automatically in the order they are created and usually do not have to be provided.
  • you can see the configuration by browsing through all the plain-text flat files in /etc/ldap/slapd.d/ and its subdirectories.

Note that by default there is no way to do this remotely. If you'd like to browse this configuration using a GUI tool like apache directory studio, don't bother. Debian sets the cn=config part of the database with a root user of cn=admin,cn=config, but without a password, so you cannot bind to the cn=config database as anything else than the local root user. Thus you cannot access the cn=config database by GUI.

Adding or modifying the cn=config admin password

To add a password to the config RootDN, we first must generate one; for this we can use the slappasswd command. By default it'll create an SSHA password, but by specifying MD5 as hash (using -h {MD5}) it will create an MD5 encrypted password. The command interactively asks you for the password, and won't show you what you've typed, so be precise:

root@easton2:/etc/ldap# slappasswd -h {MD5}
New password:
Re-enter new password:
{MD5}d5axCh6gYGjhfK4PGs09us==
root@easton2:/etc/ldap# _

Now we determine the DN (Distinguished Name) for the database that contains the RootDN password. We'll also check if there isn't a password in place already. To do this we used the following LDAP search command.

root@easton2:/etc/ldap# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b  cn=config olcRootDN=cn=admin,cn=config dn olcRootDN olcRootPW
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: olcDatabase={0}config,cn=config
olcRootDN: cn=admin,cn=config

root@easton2:/etc/ldap# _

Note the olcDatabase line, as it's the result we were looking for; it'll be needed for the ldapmodify command. Furthermore, note the absence of an olcRootPW entry; this is the starting point for a Debian OpenLDAP server.
Now we can stick in a new password. If no password is present, you can use this interactive procedure:

root@easton2:/etc/ldap# ldapmodify -Y EXTERNAL -H ldapi:///
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: olcDatabase={0}config,cn=config
add: olcRootPW
olcRootPW: {MD5}d5axCh6gYGjhfK4PGs09us==

modifying entry "olcDatabase={0}config,cn=config"

root@easton2:/etc/ldap# _

Note the following points:

  • we use the olcDatabase location as found with the previous ldapsearch command;
  • we input the MD5 password that we've generated previously;
  • as soon as you put in an empty line, the entry gets added;
  • you have to use CTRL-D to end this interactive mode;
  • if a password was already in place, we could still use the above, but we'd interactively feed the second line as replace: olcRootPW.

We could also put the password in an ldif file, and feed that to the server. To this end, we'd create an ldif file with the following content:

dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {MD5}d5axCh6gYGjhfK4PGs09us==

If this file is called addpassword.ldif and is created in /tmp, then the addition can be executed using

root@easton2:/etc/ldap# ldapmodify -Y EXTERNAL -H ldapi:/// -f /tmp/addpassword.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={0}config,cn=config"

root@easton2:/tmp# _

Adding or modifying (configuration) information

The simple way of changing anything in the database goes like this:

Method 1: interactive CLI tool

As an example, let's add an index to the configuration. We'll start by seeing which indices already exist, then interactively add two indices. Finally, we check that the indices are there:

root@easton2:/tmp# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config olcDatabase={1}hdb olcDbIndex
dn: olcDatabase={1}hdb,cn=config
olcDbIndex: objectClass eq

root@easton2:/tmp# ldapmodify -Y EXTERNAL -H ldapi:///
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: olcDatabase={1}hdb,cn=config
add: olcDbIndex
olcDbIndex: cn eq
olcDbIndex: uid eq

modifying entry "olcDatabase={1}hdb,cn=config"

root@easton2:/tmp# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config olcDatabase={1}hdb olcDbIndex
dn: olcDatabase={1}hdb,cn=config
olcDbIndex: objectClass eq
olcDbIndex: cn eq
olcDbIndex: uid eq

root@easton2:/tmp# _

(And ofcourse we press ctrl-D to end interactive mode).
Note: we can /modify multiple attributes in one stanza, but we can also add multiple objects/attributes in one ldapmodify session:

  • If you input an empty line, you can start another dn: line, and perform another action;
  • If you input a minus sign by itself on a line, then OpenLDAP will assume you'll be performing another action in/on the same object.

Modifying works almost the same; we only need keyword replace instead of add:

root@easton2:/tmp# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config -s base olcLogLevel
dn: cn=config
olcLogLevel: none
root@easton2:/tmp# ldapmodify -Y EXTERNAL -H ldapi:///
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: stats

modifying entry "cn=config"

root@easton2:/tmp# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config -s base olcLogLevel
dn: cn=config
olcLogLevel: stats

root@easton2:/tmp# _

Note the -s base option that limits the search for the olcLogLevel attribute to the cn=config container.

Deleting information from an LDAP tree rarely ever happens, because once an attribute is used for anything, you aren't allowed to delete it, only modify it. However, if you want to delete anything, you can use the changetype "modify" with action "delete":

root@easton2:/tmp# ldapmodify -Y EXTERNAL -H ldapi:///
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: olcDatabase={0}config,cn=config
changetype: modify
delete: olcRootPW

modifying entry "olcDatabase={0}config,cn=config"

root@easton2:/tmp# _

Method 2: use an ldif file

Method 3: use an LDAP browser

With this method, you just use your LDAP browser for the addition or modification, according to its specific usage instructions. In the back, the tool will communicate with the LDAP server as you would in the previous methods. Note however, that this method relies on a bind account in the configuration database, which is a serious security risk.

Adding schemas

A major task in LDAP maintenance is the addition of LDAP schemas. By default, only 4 schemas will be present in your LDAP server: core, cosine, nis and inetorgperson. Any other schema, -- say, for Samba -- would need to be added.

Checking existing schemas

Let's first check which schemas are already installed. Let's try two different methods, and see what they'll show out of the box:

root@easton2:/tmp# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=schema,cn=config "(objectClass=olcSchemaConfig)" dn
dn: cn=schema,cn=config

dn: cn={0}core,cn=schema,cn=config

dn: cn={1}cosine,cn=schema,cn=config

dn: cn={2}nis,cn=schema,cn=config

dn: cn={3}inetorgperson,cn=schema,cn=config

root@easton2:/tmp# ls -l /etc/ldap/slapd.d/cn=config/cn=schema
total 40
-rw------- 1 openldap openldap 15474 Jun 13 17:39 cn={0}core.ldif
-rw------- 1 openldap openldap 11308 Jun 13 17:39 cn={1}cosine.ldif
-rw------- 1 openldap openldap  6438 Jun 13 17:39 cn={2}nis.ldif
-rw------- 1 openldap openldap  2802 Jun 13 17:39 cn={3}inetorgperson.ldif
root@easton2:/tmp# _

Creating a suitable LDIF file for the schema

To add a schema, you need a schema in LDIF format, which you can then add to the LDAP database using the ldapadd command. Suppose you have a schema file samba.schema which you've copied to the /etc/ldap/schema directory. You'd first have to convert this to a suitable LDIF file. This can be done using slaptest, however slaptest requires access to the other schemas that your new schema is building on. So we now do this:

  • We create a file schema_convert.conf with the content shown below. Note that we're including the schema files of all the schemas that are already in our LDAP server. Furthermore, because we may need it again with the next schema addition, it makes sense to save this file under /etc/ldap/schema:
include /etc/ldap/schema/core.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/nis.schema
include /etc/ldap/schema/inetorgperson.schema
include /etc/ldap/schema/samba.schema
  • now we create a working directory where slaptest can put our new LDIF file, and have slaptest create the configuration:
root@easton2:/tmp# mkdir /tmp/ldif_output
root@easton2:/tmp# slaptest -f /etc/ldap/schema/schema_convert.conf -F /tmp/ldif_output
config file testing succeeded
root@easton2:/tmp# _
  • The previous step has created a directory structure under /tmp/ldif_output that actually mirrors the config directory /etc/ldap/slapd.d/cn=config/cn=schema, but it contains a shiny new cn={4}samba.ldif file. We need to edit this file a bit before we can actually feed it to the LDAP server. Thus we'll edit it using (note the extra backslashes to escape the equal-sign and curly brackets):
root@easton2:/tmp# vi /tmp/ldif_output/cn\=config/cn\=schema/cn\=\{4\}samba.ldif
  • We need to change and edit some parts of cn={4}samba.ldif:
    • Near the top we find dn: cn={4}samba. We'll change this to the correct distinguished name dn: cn=samba,cn=schema,cn=config
    • Also near the top: cn: {4}samba. We'll change this to cn: samba
    • The last seven lines look like the bit below - we need to remove these lines:
structuralObjectClass: olcSchemaConfig
entryUUID: f19250ba-1057-1031-88b7-8301a25f1d46
creatorsName: cn=config
createTimestamp: 20120401150603Z
entryCSN: 20120401150603.478495Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20120401150603Z
  • We'll store the cleaned up LDIF file in /etc/ldap/schema with the originating schema file
root@easton2:/tmp# mv /tmp/ldif_output/cn\=config/cn\=schema/cn\=\{4\}samba.ldif /etc/ldap/schema/samba.ldif

root@easton2:/tmp# _

Inserting the LDIF file in the LDAP server

Time to actually invoke ldapadd which can put this schema in our LDAP server.

root@easton2:/tmp# ldapadd -QY EXTERNAL -H ldapi:/// -f /etc/ldap/schema/samba.ldif
adding new entry "cn=samba,cn=schema,cn=config"
root@easton2:/tmp# _