Secure LDAPS Communication with 389-ds and CentOS 8
In this blogs we look at creating secure LDAPS con 389-ds LDAP server using CentOS 8
Of course, installing something like an LDAP server we might expect to be able to connect to it via both LDAP and LDAPS without any issues. Of course, you’ve been in the business long enough to know that this is not going to be the case whilst we will be able to communicate via LDAPS we will have to ignore some of the security features, and this is not desirable. We are going to step you through the process of installing the 389 directory service on CentOS eight, once it’s installed we can see how we can communicate through the existing protocols. Having identified the errors that we get, we will then proceed to create our own certificate authority and issue correctly signed openSSL certificates to the server.
Having secure LDAPS communication to the 389-ds instance is important as user password for CentOS and other OSs may be stored in LDAP. We need this to be encrypted on the wrie to ensure secure and safe transmission.
The Installation of 389-DS
To install the 389-DS LDAP and secure LDAPS server, we will add the EPEL repository to our CentOS 8.2 System. Using the default profile for the module, we will also install the Cockpit wen interface front-end that can be used to manage the openLDAP directory behind 389-ds
# yum install -y epel-release # yum update -y epel-release # yum module install -y 389-directory-server:stable/default
Configure a 389-DS Directory Instance on CentOS
Having installed the package, we still need to configure and instance of an openLDAP directory. One server can host multiple Directory trees if required. The 389-ds instance can be configured using the command dscreate. We can run it interactively and answer questions using:
# dscreate interactive
We can use and answer file:
# dscreate from-file <nameoffile>
Lastly, we can create a template and edit. This option is goo to learn the options that we can set.
# dscreate create-template t1.conf
We can edit the template file as required. We leave the file so it looks as in the following:
[general] config_version = 2 selinux = True [slapd] instance_name = localhost root_dn = cn=Directory Manager root_password = Password1 [backend-userroot] sample_entries = yes suffix = dc=example,dc=com
- config_version: The file format that we are using. This is the default value of 2 that we use.
- selinux: We are using CentOS 8 where SELinux is enabled, so we will use SELinux, there is no reason not to
- instance_name: localhost is the default instance name, we can keep this, but it DOES NOT mean that we only listen on the localhost interface
- root_dn: This is the account name that is used to manage the Directory
- root_password: This is the password that will be used to manage directory entries for the root dn above
- sample_entries: We create entries in the tree. Useful for testing and we always delete them later
- suffix: This is the root entry or top of the directory tree that we create. All entries will have this as their entry suffix.
Creating 389-ds Instance and Testing with LDAP and Secure LDAPS on CentOS
Having created the template, we can now create the 389-ds directory instance:
# dscreate from-file t1.conf # ss -ntl
The output of the ss command will show that the system is now listening on TCP ports 389 (LDAP) and 636 (LDAPS). From this we may think that the system is working. To a degree it is, but the SSL/TLS certificates are self-signed and not acceptable to the system. We can test this using openssl.
# openssl s_client -connect localhost:636
The final line of output will indicate an error 19 and self-signed certificate in tree. It is not just openssl that will fail, using utilities such as ldapserach will also fail on TLS:
# ldapsearch -H ldap://localhost:389 -D 'cn=Directory Manager' -W -Z -b 'dc=example,dc=com' -x
Even though we connect with LDAP, we can still ask for LDAPS using the option -Z (StartTLS). The connect fails because of the self-signed certificate. We can prove that we can connect without TLS, by removing the option -Z so we use LDAP not LDAPS:
# ldapsearch -H ldap://localhost:389 -D 'cn=Directory Manager' -W -b 'dc=example,dc=com' -x
The connection now is OK. TLS and LDAPS is the problem and the use of self-signed certificates. We need to correct this issue if we want secure LDAP with the 389-ds. We can see that we can yse secure LDAPS but only if we ignore the server authentication. This is not OK and notx want we want. We need to have LDAPS really secure on 389-ds on CentOS by setting up our own CA.
Create Secure OpenSSL Certificate Authority
We can spend a lot of time and effort in creating an OpenSSL Certificate Authority; however, we can create a cut down CA quite easily if we choose. Long term, we may prefer to create a better CA, but, for simplicity this smaller version works, needing much less configuration.
# cd # mkdir ca # cd ca # openssl genrsa -des -out myca.key 4096 # openssl req -x509 -new -nodes -key myca.key -sha256 -days 3650 -out myca.pem
The last command will prompt for the certificate details. We add GB as the country, England and the state, Peterborough as the city and The Urban Penguin as the organization. We don’t add the OU and we use a CN of MyCA. That my fried is a simple openSSL CA with minimal configuration. The CA’s public key needs to be trusted by all clients. We will test just with this single host and will add in the trust relationship:
# cp myca.pem /etc/pki/ca-trust/source/anchors/ # update-ca-trust extract
The location used is correct for CentOS 8 as is the command. You will need to check with your own OS is using another distribution or OS.
Create Secure Server Key and CSR
We now need a private key for the server and a certificate signing request. The CSR will be sent to the CA to sign creating the trust to the OS.
# openssl genrsa -out server.key 2048 # openssl req -new -key server.key -out server.csr # echo "127.0.0.2 www.example.com" >> /etc/hosts
In the CSR we are prompted for the certificate details. The CN is most important as it must match the FQDN that clients will use to access the server. We use www.example.com and create a local host record to match. Ideally, this would be in DNS so all clints could resolve the name.
To sign the CSR we must have access to the CA’s private key and certificate and know the password of the CA’s private key.
# openssl x509 -req -in server.csr -CA myca.pem -CAkey myca.key -CAcreateserial -out server.pem -days 365 -sha256
This creates the server’s signed public key. We now have a usable public key and private key pair for the server.
Export Server Key and Certificate
The 389-DS using the NSS database to store keys and certificates. The Server key and certificate need to be in a single P12 file to be imported to the database. OpenSSL can export the files:
# openssl pkcs12 -export -inkey /root/ca/server.key -in /root/ca/server.pem -out /tmp/crt.p12 -nodes -name Server-Cert
With that last step, we are finished with the /root/ca directory for the moment. We can move on to concentrate and adding these files to 389-ds for use with LDAPS.
Configure LDAPS on 389-DS Running on CentOS 8
We mode to the instance directory.
# cd /etc/dirsrv/slapd-localhost
We use the certutil command to list certificates:
# certutil -L -d .
That is -L to list and -d for the directory which we reference as period for the current directory.
We remove the current entries for the self-signed CA and and Server-Cert:
# certutil -D -d . -n Server-Cert # certutil -D -d . -n Self-Signed-CA
Importing date to the NSS database will require the PIN or Password. We get this from the pin.txt file. Copy the PIN to your clipboard, the pin starts after the colon.
# cat pin.txt # certutil -d . -A -n "MyCA" -t CT,, -a -i /root/ca/myca.pem # pk12util -i /tmp/crt.p12 -d . # systemctl restart email@example.com
The CA public key is imported directory from the /root/ca directory. The server key pair comes from the exported P12 file. We then restart the instance if the LDAP 389-ds server.
The CA is trusted by the OS. It is not self-signed. The server has a signed certificate from the trusted CA so we are ready to go:
# openssl s_client -connect 127.0.0.1:636 -showcerts # ldapsearch -H ldap://www.example.com -D 'cn=Directory Manager' -W -Z -b 'dc=example,dc=com'
Both commands work! The video follows: