Ever the sucker for punishment, I decided to pick three difficult things and stick them all together: LDAP, SSL and replication. Here's how to make it go on Debian and Ubuntu.
The problem
You want LDAP replication to happen over the internet, and you want it to happen securely.
The caveat
I'm not going to tell you how to set up your LDAP from scratch here: I'm assuming you've reached a solution you're happy with and want to replicate it.
The solution
We're going to set up a replicating slave LDAP server, which communicates with the master
over the internet via an SSL-protected connection.
Enabling replication
First up, the master LDAP server needs to be configured to permit replication.
The key lines to add to your
slapd.conf include:
moduleload syncprov
index entryCSN,entryUUID eq
overlay syncprov
syncprov-checkpoint 100 10
syncprov-sessionlog 200
These load up the synchronization module, add indices which make sync go faster, and enable sync.
For more detail see the OpenLDAP site.
Next you need to add a replicator user to your LDAP database, give your replicator user access to passwords as well as general read access. To create the replicator user, I made this simple LDIF file and fed it to
ldapadd.
dn: cn=replicator,dc=mydomain,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: replicator
description: LDAP replicator
userPassword: TOPSEKRIT
Once this user is in your LDAP database, you should give it read access to passwords (I assume you've already given read access to authenticated users.) I have this in my
slapd.conf:
access to attrs=userPassword,sambaNTPassword,sambaLMPassword
...
by dn="cn=replicator,dc=mydomain,dc=com" read
To check that this works, try using
ldapsearch to check that the passwords are returned:
ldapsearch -x -D cn=replicator,dc=mydomain,dc=com \
-W grep -i password
Enter the replicator password when prompted, and you should see the encrypted passwords from your LDAP database.
Securing access
Now you've got replication enabled on the master, you will want to ensure it is available on the internet only via TLS or SSL. Here's what I added to
slapd.conf to enable this:
TLSCertificateFile /etc/ssl/certs/ldapserver_crt.pem
TLSCertificateKeyFile /etc/ssl/private/ldapserver_key.pem
TLSCACertificateFile /etc/ssl/certs/myCA.pem
TLSVerifyClient demand
As you will guess from the configuration, the first two lines set the SSL key and certificate the master uses (see "A little twist" below for an important note on key permissions.) The third line tells
slapd where to find my site-local certificate authority (CA), and the fourth line says slapd must require any connecting client to have a valid SSL certificate signed by the site-local CA. This is important, as it provides a second layer of access control: a replicating client must connect using a certificate you signed, plus the replicator password.
Before this enables TLS access, we must tell slapd which network interfaces to listen on. To do this, edit the
SLAPD_SERVICES variable in
/etc/default/slapd. Here's my configuration:
SLAPD_SERVICES="ldap://127.0.0.1/ ldap://192.168.0.1/ ldaps:///"
This enables regular LDAP on the loopback and intranet network interfaces, and LDAP/SSL on all interfaces, including the public internet.
So, with
slapd restarted we are at this situation: connections are now possible from the internet, as long as they are made over SSL with a certificate signed by our site-local CA.
(In fact, you can make much finer-grained access restrictions in your configuration than I have done. Using LDAPS rather than TLS over regular LDAP is a rather broad precaution.
As explained on the OpenLDAP site, the
ssf= parameter can be used to require a certain level of secure connectivity on a per-user or client basis.)
Setting up the replicating server
Your slave server should have the same configuration as the master, except you can leave out the bits enabling replication.
Firstly, you'll need add to
slapd.conf the replication configuration:
syncrepl rid=123
provider=ldaps://ldapmaster.mydomain.com/
type=refreshAndPersist
searchbase="dc=mydomain,dc=com"
filter="(objectClass=*)"
scope=sub
attrs="*"
schemachecking=off
bindmethod=simple
binddn="cn=replicator,dc=mydomain,dc=com"
credentials=TOPSEKRIT
Most of this I took as boilerplate from the OpenLDAP documentation. Items to note include:
- the rid is a unique 3-digit integer per slave, used to maintain sync state
- the credentials should be the password you gave the replicator user
- the type can either be refreshAndPersist, or refresh. The latter institutes a simple polling replication, whose interval you can vary with the interval parameter. In our case, we do a poll and then keep the replication search open: our client gets notified immediately when there's any new data matching the replicating search.
- the searchbase is an LDAP search matching the data we wish to be replicated.
And here's the
/etc/default/slapd configuration:
SLAPD_SERVICES="ldap://127.0.0.1/"
The slave
slapd exists only in this case to serve the local machine.
Finally, there's the tricky bit! You need to configure
slapd to connect to the master server using a certificate. I'll assume you've created and signed a key and certificate pair for your slave server (see my post
Low-tech SSL certificate maintenance for more on this.)
Awkwardly, the TLS configuration in
slapd.conf is for the server only. Replication works as a client, and thus needs separate configuration. Furthermore, you cannot configure this globally on your machine, as the SSL certificate is a per-user only parameter (see
man ldap.conf for more information on this.)
Instead, we must set it in
slapd's environment. Add these two lines to the end of
/etc/default/slapd:
export LDAPTLS_CERT=/etc/ssl/certs/slapd.crt
export LDAPTLS_KEY=/etc/ssl/private/slapd.key
This file is sourced as a shell script by slapd's init script. Amend the path to your certificate and keys as required. Use
/etc/init.d/slapd restart and you should be good to go.
Finally, we want the slave server to be certain it's talking to the real master. So we also configure client connections to verify the SSL certificate of the peer, in
ldap.conf again:
TLS_CACERT /etc/ssl/certs/myCA.crt
TLS_REQCERT demand
A little twist
One gotcha to notice with both client and server is that
slapd runs as the
openldap user by default on Debian. Also by default SSL keys are readable only by the
ssl-cert group. You'll need add the
openldap user to this group, otherwise it won't be able to access
/etc/ssl/private.
Related articles on this site:
Join the conversation about this post