This commit is contained in:
		
					parent
					
						
							
								b3d2cddb33
							
						
					
				
			
			
				commit
				
					
						ba3b32a0c7
					
				
			
		
					 1 changed files with 143 additions and 0 deletions
				
			
		|  | @ -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. | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue