diff --git a/content/post/2021-10-22-setting-up-let-s-encrypt-certificates-for-the-389-ds-ldap-server.md b/content/post/2021-10-22-setting-up-let-s-encrypt-certificates-for-the-389-ds-ldap-server.md new file mode 100644 index 0000000..441816b --- /dev/null +++ b/content/post/2021-10-22-setting-up-let-s-encrypt-certificates-for-the-389-ds-ldap-server.md @@ -0,0 +1,143 @@ +--- +categories: +- General +- openSUSE +comments: true +date: '2021-10-22 21:04:52+02:00' +disable_share: true +draft: false +featured_image: /images/banner.jpg +omit_header_text: true +tags: +- opensuse +- ldap +- 389-ds +title: Setting up Let's Encrypt certificates for the 389-ds LDAP server +--- + +In the past months I've set up LDAP at home, to avoid having different user accounts for the services that I run on my home hardware. Rather than the venerable [OpenLDAP](https://www.openldap.org/) I settled for [389 Directory Server](https://directory.fedoraproject.org/), commercially known as Red Hat Directory Server, mainly because I was more familiar with it. Rather than describing how to set that up ([Red Hat's own documentation](https://access.redhat.com/documentation/en-us/red_hat_directory_server/11/html/administration_guide/index) is excellent on that regard), this post will focus on the steps required to enable encryption using [Let's Encrypt](https://letsencrypt.org) certificates. + +## The problem + +Even the LDAP server (they're actually two, but for the purpose of this post it does not matter) was just operating in my LAN, I wanted to reduce the amount of information going around in clear, including LDAP queries. That meant setting up encryption, of course. + +The problem was that Red Hat's docs only cover the "traditional" way of obtaining certificates, that is obtaining a Certificate Authority (CA) certificate, request a server certificate, obtain it and set it up in the server. There is (obviously) no mention of Let's Encrypt *anywhere*. I've found [some](https://gist.github.com/plembo/e69720a116f06c3b73452d4e0a9da0e0) [guides](https://possiblelossofprecision.net/?p=2586), but they were either too complicated (lots of fuzzing around with `certutil`) or they weren't clear for some steps. Hence, this post. + +**NOTE**: I've focused on 389-ds version 2.0 and above, which has a different CLI set of commands than the venerable 1.3 series. All of the steps shown here can also be carried out via the [Cockpit](https://cockpit-project.org) Web interface as well, if your distribution carries it (spoiler: openSUSE doesn't). + +## Importing the CA + +This is arguably one of the most important steps of the process. 389-ds needs also to store the CA for your certificates. As you may (or may not) know, Let's Encrypt's CA certificates are two: + +- The actual "root" certificate, by Internet Security Research Group (ISRG); +- An intermediate certificate, signed by the above root, called "R3". + +Let's Encrypt certificates, like the one powering this website, are signed by R3. But since you have to follow a "chain of trust", to validate the certificate you follow these steps (excuse me, security people; this is probably a bad semplification): + +1. Check the actual certificate (e.g. the one on dennogumi.org) +2. The certificate is signed by "R3", so move up the chain and check the R3 certificate +3. The R3 certificate is signed by the ISRG root certificate, so move up the chain and check the ISRG root +4. The ISRG certificate is trusted by the OS / application using it, so everything stops there. + +If any of the steps fails, the whole validation fails. + +This long winding explanation is to tell you that 389-ds needs the *whole certificate chain* for its CA (so ISRG root + R3) in order to properly validate the Let's Encrypt certificate you'll use. If you don't do that, chances are that some software which uses the system CA will work (for example `ldapsearch`) but others, like SSSD will fail with "Unknown CA" errors (buried deep into debug logs, so at the practical level they'll just fail and you won't know why). + +Let's get to business. Access [the Chain of Trust page](https://letsencrypt.org/certificates/) for Let's Encrypt and download the relevant certificates. I'm not sure if 389-ds supports ECDSA certificates, so I downloaded the RSA ones: ISRG Root X1 and Let's Encrypt R3 (both in PEM format). Put them somewhere in your server. Then, as root, import the two CA certificates into 389-ds (substitute `LDAP_ADDRESS` with the LDAP URI of your server): + +``` +# ISRG Root + +dsconf -v -D "cn=Directory Manager" LDAP_ADDRESS security ca-certificate \ + add --file /path/to/certificate --name "ISRG" + +# Let's Encrypt R3 + +dsconf -v -D "cn=Directory Manager" LDAP_ADDRESS security ca-certificate \ + add --file /path/to/certificate --name "R3" +``` + +**NOTE**: This step may not be necessary if you use Let's Encrypt's "full chain" certificates, but I did not test that. + +## Importing the certificates + +Then, you have to import a Let's Encrypt certificate, which means you have to obtain one. There are hundreds of guides and clients that can do the job nicely, so I won't cover that part. If you use `certbot`, Let's Encrypt's official client, you will have the certificate and the private key for it in `/etc/letsencrypt/live/YOURDOMAIN/fullchain.pem` and `/etc/letsencrypt/live/YOURDOMAIN/privkey.pem`. + +You need to import the private key first (substitute `LDAP_ADDRESS` and `DOMAIN` with the LDAP URI of your server and the Let's Encrypt domain, respectively): + +``` +dsctl LDAP_ADDRESS tls import-server-key-cert \ + /etc/letsencrypt/live/DOMAIN/fullchain.pem \ + /etc/letsencrypt/live/DOMAIN/privkey.pem +``` + +Note that you pass the certificate as well as the key to import it (in doubt, [check's Red Hat documentation](https://access.redhat.com/documentation/en-us/red_hat_directory_server/11/html/administration_guide/managing_the_nss_database_used_by_directory_server#installing_a_server_certiticate_using_the_command_line)). + +Once the key is done, it is time to import the actual certificate: + +``` +dsconf -v -D "cn=Directory Manager" LDAP_ADDRESS security certificate add \ + --file /etc/letsencrypt/live/DOMAIN/fullchain.pem \ + --primary-cert \ + --name "LE" +``` + +`--primary-cert` sets the certificate as the server's primary certificate. + +Then, we switch on TLS in the server: + +``` +dsconf -v -D "cn=Directory Manager" LDAP_ADDRESS config replace \ + nsslapd-securePort=636 nsslapd-security=on +``` + +And finally, we restart our instance (replace `INSTANCE` with your configured instance name): + +``` +systemctl restart dirsrv@INSTANCE +``` + +## Testing everything out + +You can use `ldapsearch` to check whether the SSL connection is OK (I've used `Directory Manager`, but you can use any user you want): + +``` + +# STARTTLS + +ldapsearch -H ldap://your.ldap.hostname -W -x -D "cn=Directory Manager" -ZZ "search filter here" + +# TLS + +ldapsearch -H ldaps://your.ldap.hostname -W -x -D "cn=Directory Manager" "search filter here" + +``` + +If everything is OK, you should get a result: otherwise, you'll get an error like "Can't contact the LDAP server". + +Alternatively, you can use `openssl`: + +``` +openssl s_client -connect your.ldap.hostname:636 +[...] +--- +SSL handshake has read 5188 bytes and written 438 bytes +Verification: OK +``` + +Don't forget to adjust your applications to connect via `ldaps` rather than `ldap` after everything is done. + +## Renewing the certificates + +To renew the certificates you repeat the steps outlined above for the certificates (without the CA part, of course). Make sure you always import your private key: if there is a mismatch between it and the certificate, 389-ds will refuse to start. + +If you use `certbot` you can use a post-renewal hook to trigger the import of the certificate into 389-ds. [This is what I've been using](https://git.dennogumi.org/einar/scripts/src/branch/master/sysadmin/le_lan_reload_services.sh): bear in mind it's customized to my setup and does a few more things than needed. Also it does only import the certificate, and not the full chain. + + +## I messed up and 389-ds won't start! What do I do? + +You can disable encryption by editing `/etc/dirsrv/slapd-INSTANCE/dse.ldif` and changing `nsslapd-security` to `off`, then start 389-ds again. Then you can review everything and see what went wrong. But if you can, I recommend the Cockpit Web UI: it makes the first-time setup a breeze. + +## Wrap up + +Importing the certificates is surprisingly simple, but my Internet searches have been frustrating because at least half of what I found was either not applicable, incomplete, or did not work. I hope this small tutorial can be useful for those who want a bit more security in their LDAP setup.