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”:
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:
- 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 undercn=config
. - Line 2 specifies the
changetype
; if the attribute exists, it should bemodify
, as in this case. - 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.
- 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.