LDAP & TLS

When authenticating to an OpenLDAP server it is best to do so using an encrypted session. This can be accomplished using Transport Layer Security (TLS).

Here, we will be our own Certificate Authority and then create and sign our LDAP server certificate as that CA. Since slapd is compiled using the gnutls library, we will use the certtool utility to complete these tasks.

Install the gnutls-bin and ssl-cert packages:

sudo apt install gnutls-bin ssl-cert

Create a private key for the Certificate Authority:

sudo sh -c "certtool --generate-privkey > /etc/ssl/private/cakey.pem"

Create the template/file /etc/ssl/ca.info to define the CA:

cn = Example Company
ca
cert_signing_key

Create the self-signed CA certificate:

sudo certtool --generate-self-signed \
--load-privkey /etc/ssl/private/cakey.pem \ 
--template /etc/ssl/ca.info \
--outfile /etc/ssl/certs/cacert.pem

Make a private key for the server:

sudo certtool --generate-privkey \
--bits 1024 \
--outfile /etc/ssl/private/ldap01_slapd_key.pem

Note

Replace ldap01 in the filename with your server’s hostname. Naming the certificate and key for the host and service that will be using them will help keep things clear.

Create the /etc/ssl/ldap01.info info file containing:

organization = Example Company
cn = ldap01.example.com
tls_www_server
encryption_key
signing_key
expiration_days = 3650

The above certificate is good for 10 years. Adjust accordingly.

Create the server’s certificate:

sudo certtool --generate-certificate \
--load-privkey /etc/ssl/private/ldap01_slapd_key.pem \
--load-ca-certificate /etc/ssl/certs/cacert.pem \
--load-ca-privkey /etc/ssl/private/cakey.pem \
--template /etc/ssl/ldap01.info \
--outfile /etc/ssl/certs/ldap01_slapd_cert.pem

Adjust permissions and ownership:

sudo chgrp openldap /etc/ssl/private/ldap01_slapd_key.pem
sudo chmod 0640 /etc/ssl/private/ldap01_slapd_key.pem
sudo gpasswd -a openldap ssl-cert

Now restart slapd, since we added the ‘openldap’ user to the ‘ssl-cert’ group:

sudo systemctl restart slapd.service

Your server is now ready to accept the new TLS configuration.

Create the file certinfo.ldif with the following contents (adjust accordingly, our example assumes we created certs using https://www.cacert.org):

dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/certs/cacert.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/ldap01_slapd_cert.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/ldap01_slapd_key.pem

Use the ldapmodify command to tell slapd about our TLS work via the slapd-config database:

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

Contratry to popular belief, you do not need ldaps:// in /etc/default/slapd in order to use encryption. You should have just:

SLAPD_SERVICES="ldap:/// ldapi:///"

Note

LDAP over TLS/SSL (ldaps://) is deprecated in favour of StartTLS. The latter refers to an existing LDAP session (listening on TCP port 389) becoming protected by TLS/SSL whereas LDAPS, like HTTPS, is a distinct encrypted-from-the-start protocol that operates over TCP port 636.

Replication and TLS

If you have set up replication between servers, it is common practice to encrypt (StartTLS) the replication traffic to prevent evesdropping. This is distinct from using encryption with authentication as we did above. In this section we will build on that TLS-authentication work.

The assumption here is that you have set up replication between Provider and Consumer according to Replication and have configured TLS for authentication on the Provider by following TLS.

As previously stated, the objective (for us) with replication is high availablity for the LDAP service. Since we have TLS for authentication on the Provider we will require the same on the Consumer. In addition to this, however, we want to encrypt replication traffic. What remains to be done is to create a key and certificate for the Consumer and then configure accordingly. We will generate the key/certificate on the Provider, to avoid having to create another CA certificate, and then transfer the necessary material over to the Consumer.

On the Provider,

Create a holding directory (which will be used for the eventual transfer) and then the Consumer’s private key:

mkdir ldap02-ssl
cd ldap02-ssl
sudo certtool --generate-privkey \
--bits 1024 \
--outfile ldap02_slapd_key.pem

Create an info file, ldap02.info, for the Consumer server, adjusting its values accordingly:

organization = Example Company
cn = ldap02.example.com
tls_www_server
encryption_key
signing_key
expiration_days = 3650

Create the Consumer’s certificate:

sudo certtool --generate-certificate \
--load-privkey ldap02_slapd_key.pem \
--load-ca-certificate /etc/ssl/certs/cacert.pem \
--load-ca-privkey /etc/ssl/private/cakey.pem \
--template ldap02.info \
--outfile ldap02_slapd_cert.pem

Get a copy of the CA certificate:

cp /etc/ssl/certs/cacert.pem .

We’re done. Now transfer the ldap02-ssl directory to the Consumer. Here we use scp (adjust accordingly):

cd ..
scp -r ldap02-ssl user@consumer:

On the Consumer,

Configure TLS authentication:

sudo apt install ssl-cert
sudo gpasswd -a openldap ssl-cert
sudo cp ldap02_slapd_cert.pem cacert.pem /etc/ssl/certs
sudo cp ldap02_slapd_key.pem /etc/ssl/private
sudo chgrp openldap /etc/ssl/private/ldap02_slapd_key.pem
sudo chmod 0640 /etc/ssl/private/ldap02_slapd_key.pem
sudo systemctl restart slapd.service

Create the file /etc/ssl/certinfo.ldif with the following contents (adjust accordingly):

dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/certs/cacert.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/ldap02_slapd_cert.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/ldap02_slapd_key.pem

Configure the slapd-config database:

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

Configure /etc/default/slapd as on the Provider (SLAPD_SERVICES).

On the Consumer,

Configure TLS for Consumer-side replication. Modify the existing olcSyncrepl attribute by tacking on some TLS options. In so doing, we will see, for the first time, how to change an attribute’s value(s).

Create the file consumer_sync_tls.ldif with the following contents:

dn: olcDatabase={1}mdb,cn=config
replace: olcSyncRepl
olcSyncRepl: rid=0 provider=ldap://ldap01.example.com bindmethod=simple
 binddn="cn=admin,dc=example,dc=com" credentials=secret searchbase="dc=example,dc=com"
 logbase="cn=accesslog" logfilter="(&(objectClass=auditWriteObject)(reqResult=0))"
 schemachecking=on type=refreshAndPersist retry="60 +" syncdata=accesslog
 starttls=critical tls_reqcert=demand

The extra options specify, respectively, that the consumer must use StartTLS and that the CA certificate is required to verify the Provider’s identity. Also note the LDIF syntax for changing the values of an attribute (‘replace’).

Implement these changes:

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

And restart slapd:

sudo systemctl restart slapd.service

On the Provider,

Check to see that a TLS session has been established. In /var/log/syslog, providing you have ‘conns’-level logging set up, you should see messages similar to:

slapd[3620]: conn=1047 fd=20 ACCEPT from IP=10.153.107.229:57922 (IP=0.0.0.0:389)
slapd[3620]: conn=1047 op=0 EXT oid=1.3.6.1.4.1.1466.20037
slapd[3620]: conn=1047 op=0 STARTTLS
slapd[3620]: conn=1047 op=0 RESULT oid= err=0 text=
slapd[3620]: conn=1047 fd=20 TLS established tls_ssf=128 ssf=128
slapd[3620]: conn=1047 op=1 BIND dn="cn=admin,dc=example,dc=com" method=128
slapd[3620]: conn=1047 op=1 BIND dn="cn=admin,dc=example,dc=com" mech=SIMPLE ssf=0
slapd[3620]: conn=1047 op=1 RESULT tag=97 err=0 text

Last updated 5 months ago. Help improve this document in the forum.