RJ Systems
Linux System Administration
Home Tech Linux Links Consulting







Valid XHTML 1.0!

Valid CSS!

IPv6 test

OpenLDAP consumer on Debian lenny

Introduction

This page describes how to set up an OpenLDAP consumer server with the LDAP Sync Replication engine (syncrepl) for integration in a network with a previously installed OpenLDAP provider server, called ldaps1.example.com. Hosts such as these were previously referred to as master and slave servers, but these terms were depricated after the roles of these systems became more flexible.

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 consumer with a copy of the DIT from the provider.

Before the actual OpenLDAP installation process can begin, it will first be necessary to install Debian lenny on a new host called ldaps2.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. 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 master server can begin:


1. Package installation

On the new host, ldaps2.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 contortrix, although it will be temporary:

Administrator password: contortrix
Confirm password: contortrix

Run the following command to test if the OpenLDAP server is actually running:

~# nmap ldaps2.example.com

This should be among the results:

PORT	STATE SERVICE
389/tcp open  ldap

Perform a quick test by generating an LDIF dump of the contents of a the (temporary) local database:

~# slapcat
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: example.com
dc: example
structuralObjectClass: organization
entryUUID: a2c24128-7547-102e-8bd7-41184906bd68
creatorsName:
createTimestamp: 20091204173853Z
entryCSN: 20091204173853.745401Z#000000#000#000000
modifiersName:
modifyTimestamp: 20091204173853Z

dn: cn=admin,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e2NyeXB0fWNlTlNMeFNxRmgzNFU=
structuralObjectClass: organizationalRole
entryUUID: a2c2d6ba-7547-102e-8bd8-41184906bd68
creatorsName:
createTimestamp: 20091204173853Z
entryCSN: 20091204173853.749560Z#000000#000#000000
modifiersName:
modifyTimestamp: 20091204173853Z

~# _

If the output looks something like the above, continue with the next step.


2. ldap.conf

Edit /etc/ldap/ldap.conf and add these two lines to the end of the file:

BASE    dc=example,dc=com
URI     ldap://ldaps2.example.com/

This configuration file is used to set system-wide defaults for LDAP clients.


3. Syncprov

First, over on the provider server, ldaps1.example.com, create an LDIF file, called ~/ldaps2.ldif, with which to create a new organizationalRole object, and add this information to it:

dn: cn=ldaps2,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: ldaps2
description: LDAP server2 replicator
userPassword: bilineatus

Add it to the DIT with this command:

root@ldaps1:~# ldapadd -cxWD cn=admin,dc=example,dc=com -f ~/ldaps2.ldif
Enter LDAP Password: piscivorus
adding new entry "cn=ldaps2,dc=example,dc=com"

root@ldaps1:~# _

This new DN, cn=ldaps2,dc=example,dc=com, along with its matching password, will be used to authenticate the new consumer server when it attempts to synchronize its copy of the DIT.

Still on ldaps1, edit /etc/ldap/slapd.conf and make three changes to it. First, add a single line to the following ACL:

access to attrs=userPassword,shadowLastChange
        by dn="cn=admin,dc=example,dc=com" write
        by dn="cn=ldaps2,dc=example,dc=com" read
        by anonymous auth
        by self write
        by * none

This will authorize the new consumer to read the entire DIT, including all passwords, when it attempts to synchronize with the provider.

Second, add these four lines to the end of the file to load, activate and configure the Sync Provider overlay:

moduleload      syncprov

overlay         syncprov

syncprov-checkpoint 100 10
syncprov-sessionlog 100

The module for it, syncprov, is dynamically loaded into the active slapd process (since it was not compiled statically into /usr/sbin/slapd) and then activated with the overlay directive to enable provider-side support for syncrepl replication. It adds a contextCSN attribute to the root entry of the DIT and can be used with any database backend that maintains entryCSN and entryUUID attributes for all its entries, but works best when the bdb or hdb backend is used. Two syncprov options are configured:

syncprov–checkpoint After a write operation has succeeded, write the current contextCSN value to the underlying database if, in this case, either 100 write operations or more than 10 minutes have passed since the last checkpoint. Used to minimize recovery times after unclean shutdowns, this option is disabled by default.
syncprov–sessionlog Specifies that a session log be maintained for recording information about operations written to the database. Here, the log may record a maximum of 100 operations. All LDAP Write operations (except Adds) are recorded in the log. Used to speed up LDAP Sync searches within the database.

See also man slapo-syncprov for more options.

Third, add two new eq index entries:

index           objectClass eq
index           uid         eq
index           entryUUID   eq
index           entryCSN    eq

Regarding these two additions, using the syncprov-sessionlog option requires searching for the entryUUID attribute. While not a requirement, setting an eq index for it on the provider can improve the performance of the session log considerably. For the same reason, setting an eq index for the entryCSN attribute when using the syncprov-checkpoint option is also recommended.

Having committed these changes to the slapd.conf file on ldaps1, it becomes necessary to reindex the database. Since it is best to run the appropriate command as the openldap user, first make this possible by altering the following line (that may not have the same UID and GID numbers) in the /etc/passwd file:

openldap:x:105:107:OpenLDAP Server Account,,,:/var/lib/ldap:/bin/sh

Now stop the LDAP service, regenerate the database indices as the openldap user, and restart the LDAP service:

root@ldaps1:~# /etc/init.d/slapd stop
Stopping OpenLDAP: slapd.
root@ldaps1:~# su -c /usr/sbin/slapindex openldap
root@ldaps1:~# /etc/init.d/slapd start
Starting OpenLDAP: slapd.
root@ldaps1:~# _

Because there are existing entries in the database that include the attribute for which the new eq indices have been added, it is necessary to regenerate the indices in order to maintain database consistency. This procedure is unnecessary when there are not yet any entries that include the relevant attributes.


4. Syncrepl

Now, back on ldaps2, edit its /etc/ldap/slapd.conf file as well, making a series of changes to it. The first modification is to comment out the line that prevents anything being written to the logs:

#loglevel        none

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).

Then, specify a root DN:

# rootdn          "cn=admin,dc=example,dc=com"

rootdn          "cn=manager"

The name used here for rootdn is completely arbitrary, since there is no need for it to be part of the directory, but the setting is mandatory for an OpenLDAP consumer in order to allow it to store anything in the database that it receives, regardless of how the ACLs are set.

Next, add eq indices for three more attributes:

index           objectClass eq
index           uid         eq
index           entryCSN    eq
index           entryUUID   eq

Setting an eq index on the uid attribute speeds up the authentication process, while doing the same for entryCSN and entryUUID will speed up the replication process.

Then, modify the ACLs to reflect the fact that the replicated database is strictly read-only. The ACLs should end up looking like this:

access to attrs=userPassword,shadowLastChange
        by anonymous auth
        by * none

access to dn.base="" by * read

access to *
        by * read

Should any clients attempt to write to this database replica, these ACLs will be bypassed and the clients will instead be given a referral to the OpenLDAP provider, the method for which is described below.

Now add the following stanza for the LDAP Sync Replication engine to the end of the first database section:

syncrepl rid=123
        provider=ldap://ldaps.example.com:389/
        type=refreshAndPersist
        retry="60 30 300 +"
        searchbase="dc=example,dc=com"
        bindmethod=simple
        binddn="cn=ldaps2,dc=example,dc=com"
        credentials=bilineatus

The syncrepl directive indicates that the current database is a replica. Indeed, it is strictly a database option and applies to the database for which it is defined. This directive has many different options of its own, a number of which are used here:

rid The replica ID of the current syncrepl directive on the consumer. Must be a non-negative three-digit integer. The choice here, 123, is arbitrary.
provider The provider with master content to replicate with. Written with an LDAP URI followed by a port number if necessary. Here, the alias is used that refers to the current provider server.
type The operation type. This can be either refreshOnly, which is polling pull-based synchronization, or refreshAndPersist, which is persistent push-based synchronization. If the latter type is used, the retry option is required.
retry In case of replication errors, this setting determines both the amount of time in seconds to wait before the consumer attempts to reconnect to the provider, as well as the number of retries. Specified as a set of one or more interval-retry pairs, separated by spaces. A "+" indicates an indefinite number of retries. The setting used here means that, if a replication error occurs, the consumer will attempt to reconnect with the provider once every 60 seconds with 30 retries, and then once every 300 seconds for an indefinite (+) number of retries.
interval The replication interval is specified as dd:hh:mm:ss. Limited to use with refreshOnly synchronization. The default is one day. Limited to use with refreshOnly synchronization (see below).
searchbase The search base to use for replication, written as a DN. Has no default and must always be specified.
bindmethod The security method to be used for authentication. This can be either simple or sasl. Since the first method are used here, the options binddn and credentials are required.
binddn The DN that the consumer will use to authenticate with the provider.
credentials The password that the consumer will use to authenticate with the provider. Because the bindmethod simple is used, the password must be in clear text.

The above syncrepl configuration uses persistent push-based synchronization in which the provider keeps track of the consumer, sending it the necessary updates whenever its own database is modified. This is often desirable when modifications are frequent, but if not, use the refreshOnly operation type instead:

syncrepl rid=123
        provider=ldap://ldaps.example.com:389/
        type=refreshOnly
        interval=00:00:05:00
        searchbase="dc=example,dc=com"
        bindmethod=simple
        binddn="cn=ldaps2,dc=example,dc=com"
        credentials=bilineatus

This alternative configuration features the polling, pull-based refreshOnly operation type. The interval setting used here, 00:00:05:00, means that replication will occur once every five minutes.


5. Referrals

LDAP Sync Replication does present one important problem for LDAP clients: the resultant database is always read-only. To allow clients to make modifications to it, the consumer server must somehow inform them that this is only done via the provider. This can be arranged by adding the following line to the end of /etc/ldap/slapd.conf, below the syncrepl stanza:

updateref	ldap://ldaps.example.com:389/

The updateref directive is a referral that a consumer passes back to clients when slapd is asked to modify the replicated local database, e.g. to change a password. Unfortunately, although this is the preferred solution to the problem, not all LDAP clients understand referrals, which is why it is also a good idea to use the chain overlay.

The chain overlay (see man slapo-chain), which is built into the back_ldap module, (see man slapd-ldap) allows slapd to automatically chase referrals on behalf of clients. So, for the last change, add the following lines to the global section of slapd.conf, before any database definitions:

moduleload      	back_ldap
overlay         	chain

chain-uri               ldap://ldaps.example.com:389/
chain-rebind-as-user    TRUE
chain-idassert-bind     bindmethod=simple
                        binddn="cn=ldaps2,dc=example,dc=com"
                        credentials=bilineatus
                        mode=self
chain-return-error      TRUE

Having saved all of the previous changes to /etc/slapd.conf, stop the LDAP service, delete the now-redundant local database, and restart the service. This will cause the consumer to synchronize its database with the provider for the first time:

~# /etc/init.d/slapd stop
Stopping OpenLDAP: slapd.
~# rm /var/lib/ldap/*
~# /etc/init.d/slapd start
Starting OpenLDAP: slapd.
~# _

If the original copy of the local database is not deleted, its existing entries, for the domain component and the administrative user, will not be replaced with those of the provider, even though the rest of the DIT will be synchronized. As a result the operation will only appear successful. For instance, on this consumer system the administrative password will still be contortrix, as opposed to piscivorus as it is on the provider.


6. Replication test

Now that slapd has been restarted, if everything has gone as planned, replication with the provider, ldaps1, wil have taken place for the first time. Verify this with a simple ldapsearch command:

~# ldapsearch -x -LLL
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

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

dn: cn=ldaps2,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: ldaps2
description: LDAP server2 replicator

~# _

Obviously, success should look like this, since all of the entries after the first two were created on the OpenLDAP provider server. A more precise way to check that everything has worked as expected, is to run the slapcat command on both the consumer and the provider; in both cases the output in exactly the same.


7. Proxy authorization

Before the chaining configuration added in step 5 will work, a few more changes will have to be made, one of them to the OpenLDAP provider server, ldaps1.example.com. What is required is something called proxy authorization. With this mechanism, it is possible to allow an authenticated user, such as the consumer server in this example, to assume the identities of other users and use that to relay their write requests on to the provider server. The ability to assume another user's identity is important, as it would otherwise not be possible to enforce existing access rules.

Two changes are required to enable proxy authorization. First, the existing LDAP entry for the consumer server, ldaps2, must be modified to include an authzTo attribute, so that it will be allowed to act as an authorization proxy for certain users. Second, an authz-policy directive must be added to the slapd.conf on the provider server, so that it will accept such proxy requests.

To modify the LDAP entry for the consumer server, cn=ldaps2,dc=example,dc=com, first create a new file, called ~/ldaps2-authzto.ldif, on the provider, ldaps1, and give it the following contents:

dn: cn=ldaps2,dc=example,dc=com
changetype: modify
add: authzTo
authzTo: dn.regex:^uid=[^,]+,ou=people,dc=example,dc=com$
authzTo: dn.exact:cn=admin,dc=example,dc=com
-

NB: Make sure ldaps2-authzto.ldif does not contain any DOS-style carriage return and line feed pairs (^M characters)! If it does, ldapmodify will interpret the contents as one long destinguished name and consequently declare it invalid.

The authzTo attribute is a source rule, used here to determine those for whom ldaps2 may proxy. It can also be multivalued. Here, the first value is a regular expression that matches all users in ou=people. The second one is an exact match for the administrative user.

To apply the modification, run this command:

root@ldaps1:~# ldapmodify -x -D "cn=admin,dc=example,dc=com" \
               -w piscivorus -f ~/ldaps2-authzto.ldif
modifying entry "cn=ldaps2,dc=example,dc=com"

root@ldaps1:~# _

Next, on the provider server, ldaps1, edit /etc/ldap/slapd.conf and add this line to the end of the Global directives section:

tool-threads 1

authz-policy    to

This statement enables proxy authorization using rules associated with the authzTo attribute of the authentication DN (in this case cn=ldaps2). Without this, the provider would otherwise ignore all authzTo attributes, such as the one added to the cn=ldaps2 entry.

Having committed the above change to slapd.conf, restart the provider's LDAP service:

root@ldaps1:~# /etc/init.d/slapd restart
Stopping OpenLDAP: slapd.
Starting OpenLDAP: slapd.
root@ldaps1:~# _

8. Proxy auth test

This last step will test whether the proxy authorization actually works. This is easily done on the consumer server using the ldapadd command. If it works, the changes will be immediately available on the consumer server (or within five minutes if refreshOnly replication is used). First, create a file, called ~/ldaps2-desc.ldif, and add this information to it:

dn: cn=ldaps2,dc=example,dc=com
changetype: modify
replace: description
description: LDAP consumer
-

Then apply this change with the ldapmodify command:

~# ldapmodify -x -D "cn=admin,dc=example,dc=com" \
   -w piscivorus -f ~/ldaps2-desc.ldif
modifying entry "cn=ldaps2,dc=example,dc=com"

~# _

That was a success. Afterwards, a search for cn=ldaps2 should show that this change has been replicated to the consumer database:

~# ldapsearch -x -LLL cn=ldaps2
dn: cn=ldaps2,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: ldaps2
description: LDAP consumer

~# _

9. See also
10. Further reading
  • Eastlake D, Panitz A. 1999. RFC2606 − Reserved Top Level DNS Names. The Internet Society. HTML at the Internet FAQ Archives.
  • Hodges J, Morgan R. 2002. RFC3377 − Lightweight Directory Access Protocol (v3): Technical Specification. The Internet Society. HTML at the Internet FAQ Archives.
  • Wahl M, Howes T, Kille S. 1997. RFC2251 − Lightweight Directory Access Protocol (v3). The Internet Society. HTML at the Internet FAQ Archives.
  • Yeong W, Howes T, Kille S. 1993. RFC1487 − X.500 Lightweight Directory Access Protocol. The Internet Society. HTML at the Internet FAQ Archives.

11. Sources
  • Carter G. 2003. LDAP System Administration. O'Reilly & Associates, Inc. ISBN 1-56592-491-6. 294 pp.
  • OpenLDAP Project. 2009. OpenLDAP Software 2.4 Administrator's Guide. HTML at OpenLDAP.


Last modified: 2010-11-16, 1:57

©2003-2014 RJ Systems. Permission is granted to copy, distribute and/or modify the
content of this page under the terms of the OpenContent License, version 1.0.