Configuring N-Way Multimaster Replication.

Introduction

In the last post, we covered how to set up basic LDAP hosts with StartTLS enabled. We’ll continue to configure our LDAP setup to enable replication between two hosts. This can be achieved through a variety of methods, but each works towards the same end result: redundancy. OpenLDAP replicates per directory information tree or DIT fragment. Each host uses a replication engine called syncrepl (short for Sync Replication). In this tutorial, we’ll configure two hosts to function both as providers and consumers. OpenLDAP refers to this configuration as N-Way Multimaster Replication.

OpenLDAP trials and tribulations

So far we’ve managed to avoid configuring our OpenLDAP server directly. To recap, we’ve only directly interacted with our server by starting it and performing a search against it.

When I first installed OpenLDAP, I (naively) expected the configuration process to take place via editing static configuration files with a text editor. Confusion mounted as I browsed the official documentation and its “Quick-Start Guide”:

  1. Edit the configuration file. Use your favorite editor to edit the provided slapd.ldif example (usually installed as /usr/local/etc/openldap/slapd.ldif) to contain a MDB database definition of the form:

    dn: olcDatabase=mdb,cn=config . . .

I had no idea what an LDIF file was, so I assumed (again in ignorance) that perhaps this was just an idiosyncratic way of referring to a configuration file, so I went searching for slapd.ldif. No luck. I thought to myself, “surely they have some sort of .conf file somewhere?” And so I searched for other sources. After some time, I began to form some sort of aggregate consensus drawn from popular sources such as the Gentoo wiki, ArchWiki, CentOS documentation, and a smattering of blogs. The indication seemed to point towards configuration via slapd.conf. “Alright, then. Let’s give it an edit!” Off I went to make some edits. To my chagrin, there was no such file. At this point, confusion transformed into consternation and frustration. I began to curse OpenLDAP and its documentation.

After some more time and research, I began to understand that slapd.conf had been deprecated long ago. The documentation made no mention of this. It did not explain its new alternative. I found it difficult to find a terse and concise explanation of the proper method for configuring OpenLDAP. Ultimately I referred to documentation found on www.zytrax.com. I’d used this source for learning DNS and found that the authors have a deep understanding and do their best to infuse levity wherever possible.

How OpenLDAP handles configuration

I’d like to make an attempt at providing what I couldn’t find when I started to learn OpenLDAP: a concise explanation of OpenLDAP’s preferred method of configuration. Generally, you’ll find that the configuration of OpenLDAP is referred to broadly using multiple terms: On-Line Configuration (OLC), cn=config, and slapd.d configuration. I prefer OLC because all configuration entries contain this acronym in their names. OpenLDAP deprecated slapd.conf to implement OLC’s primary benefit—On-Line configuration. Previously, if a change was made to OpenLDAP’s configuaration, the server would likely need to be restarted for the change to take effect. Now, OpenLDAP expects changes to configuration the same way it expects changes and additions to a DIT: via ldapadd and ldapmodify. Instead of a flat config file, OpenLDAP stores its configuration details in a configuration directory, /etc/openldap/slapd.d/cn=config.

This is all well and good, but this leaves many questions unanswered. How do you actually make changes? How do you browse current configuration entries? I found it beneficial to first understand how to search and browse the configuration database. Other guides might recommend the installation of a browser based LDAP client such as phpLDAPadmin. In any case, beginning to understand the intricacies of configuration is important and will take time. Once you know what to configure, you may begin to understand LDAP’s idiosyncratic expectations.

How to browse and change configuration entries

My preferred method for browsing cn=config is anything but elegant—search the entire thing at once:

$ sudo ldapsearch -H ldapi:/// -Y EXTERNAL -b "cn=config" -LLL | less

Expect a pretty volumonous output. Using less, you can utilize / to search for entries and attributes. After verifying the entry that needs changing, an LDIF file can be created. LDIF files are sent to an LDAP server to make changes, facilitating local and remote modifications (this is the whole point of LDAP). Using olcSuffix as an example, the following is generally what you’d expect from an LDIF file:

dn: olcDatabase={2}bdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=internal,dc=tminor,dc=io

At first, this format appears quite cumbersome. Examining the contents presented here might help to better understand the function of these files:

  1. Line one tells OpenLDAP where to look for the entry that needs to be changed. In this case, we’re telling it to look under olcDatabase={2}bdb which itself resides under cn=config.
  2. Line 2 specifies the changetype; if the attribute exists, it should be modify, as in this case.
  3. Line 3 indicates the entry to be modified and the action to be taken upon it; “replace” if the entry already exists with a value or “add” if an entry is to be newly created.
  4. Line 4 tells OpenLDAP what the new attribute-value assignment should be for the entry.

After creating the file, it can be sent to the OpenLDAP server via ldapadd:

sudo ldapadd -H ldapi:/// -Y EXTERNAL -f <filename>.ldif

Basic DIT

Before setting up replication, we need a DIT to replicate. Before actually creating the DIT, we need to specify some information in cn=config: olcSuffix, olcRootDN, olcRootPW, and olcAccess. Before continuing, a password will need to be generated using slappasswd. OpenLDAP stores passwords unencrypted by default; slappasswd accepts an input and provides a hashed output.

Open a file—naming it root.ldif—and enter the following, changing entries where necessary:

dn: olcDatabase={2}bdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=example,dc=com

dn: olcDatabase={2}bdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=example,dc=com

dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}rTy9d6kXWfku6CRso8e9YmCzlZzk2woj

dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange by
  dn="cn=Manager,dc=example,dc=com" write by anonymous auth by self write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by dn="cn=Manager,dc=example,dc=com" write by * read

The above ACL has the general effect of restricting configuration to the root user on the host itself. For more information on formulating ACLs, see the OpenLDAP Administrator’s Guide. Next, we’ll populate the DIT with some very basic information:

dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectclass: organization
o: Homelab
dc: example

dn: cn=Manager,dc=example,dc=com
objectClass: organizationalRole
cn: Manager
description: Directory Manager

dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People

dn: ou=Group,dc=example,dc=com
objectClass: organizationalUnit
ou: Group

Now the DIT is ready for replication.

Configure the LDAP hosts for replication

Open a file with your favorite text editor; call the file mod_syncprov.ldif. Enter the following contents:

dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
olcModulePath: /usr/lib64/openldap
olcModuleLoad: syncprov.la

This file will load the module that allows syncrepl to provide updates during the replication process. Depending on your OS and the method you chose to install OpenLDAP, it may be necessary to change the olcModulePath. Load the file:

$ sudo ldapadd -H ldapi:// -Y EXTERNAL -f mod_syncprov.ldif

Next, create a file called syncprov.ldif with the following contents:

dn: olcOverlay=syncprov,olcDatabase={2}bdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov

Add the file:

$ sudo ldapadd -H ldapi:/// -Y EXTERNAL -f syncprov.ldif

For a better understanding of overlays and their functions, you can start here.

Next, we’ll concoct an LDIF file to configure the host as a provider:

dn: cn=config
changetype: modify
add: olcServerID
olcServerID: 1 $URL1
olcServerID: 2 $URL2

dn: olcDatabase={2}bdb,cn=config
changetype: modify
add: olcSyncRepl
olcSyncRepl:
  rid=001
  provider=$URL1
  binddn="cn=Manager,dc=example,dc=com"
  bindmethod=simple
  credentials=<password>
  searchbase="dc=example,dc=com"
  type=refreshAndPersist
  retry="5 5 300 5"
  timeout=1
  interval=00:00:00:10
olcSyncRepl:
  rid=002
  provider=$URL2
  binddn="cn=Manager,dc=example,dc=com""
  bindmethod=simple
  credentials=<password>
  searchbase="dc=example,dc=com"
  type=refreshAndPersist
  retry="5 5 300 5"
  timeout=1
  interval=00:00:00:10
-
add: olcMirrorMode
olcMirrorMode: TRUE

Save the file and send it:

$ sudo ldapmodify -H ldapi:/// -Y EXTERNAL -f provider.ldif

For more information about replication types and how to configure them, see the Administrator’s Guide.

At this point the two LDAP servers should be replicating the DIT; to verify that everything is functioning properly, logging needs to be enabled. Create another LDIF file and enter the following information:

dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: stats sync

Load the file with ldapmodify. Next, configure rsyslog to write the logs to the desired location. Open /etc/rsyslog.conf and append the following line to the end of the file:

local4.*	/var/log/sldapd.log

Restart rsyslog:

$ sudo service rsyslog restart

OpenLDAP is now configured for replication.

Securing LDAP

One thing to be wary of with the above setup is that replication between the two hosts is not secured; authentication takes place in the clear. syncrepl does allow for StartTLS using the simple bind method but I could not get it to work with Mozilla NSS (perhaps user error). As an alternative I’ve decided instead to use Kerberos and GSSAPI based encryption. In the next post I’ll go over securing OpenLDAP.