ldapdock/INSTALL.md
2025-11-18 11:50:53 -05:00

13 KiB

ldapdock

a configurable secure openLDAP based container

Step by step approach on how to setup and run an openLDAP server on a systemd-less docker image container

1- Creating the ldapdock image container

build ldapdock from the dockerfile and run into it, creating the proper volumes to save databases data, config data, and certs data

> docker build -t ldapdock /path/to/dockerfile
> docker run -i -t -p 389:389 -p 636:636 -h example.com -v ldap_data:/var/lib/ldap -v ldap_config:/etc/ldap/slapd.d -v ldap_certs:/etc/ldap/certs -v $(pwd)/host-certs:/export-certs ldapdock

2- Run the openLDAP server and populate a directory

Use the following command to start openLDAP

root@example:/# slapd -h "ldap:/// ldapi:/// ldaps:///" -g openldap -u openldap

Create some groups and users to populate a directory

root@example:/# cat > add_content.ldif << EOF
dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People

dn: ou=Groups,dc=example,dc=com
objectClass: organizationalUnit
ou: Groups

dn: cn=mages,ou=Groups,dc=example,dc=com
objectClass: posixGroup
cn: mages
gidNumber: 5000
memberUid: marisa

dn: uid=marisa,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: marisa
sn: Kirisame
givenName: Marisa
cn: Marisa Kirisame
displayName: Marisa Kirisame
uidNumber: 10000
gidNumber: 5000
userPassword: {CRYPT}x
gecos: Marisa Kirisame
loginShell: /bin/bash
homeDirectory: /home/marisa
EOF

When creating the groups and users, we will be asked the openLDAP root password (default: admin)

root@example:/# ldapadd -x -D cn=admin,dc=example,dc=com -W -f add_content.ldif

Notice the userPassword is invalid, let's set a proper one

root@example:/# ldappasswd -x -D cn=admin,dc=example,dc=com -w admin -s qwerty uid=marisa,ou=people,dc=example,dc=com

3- Load and enable policies module

Write the .ldif file and load the ppolicy.so module that comes with Debian libraries

root@example:/# cat > modify_ppolicy_module.ldif << 'EOF'
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: ppolicy.so
EOF`
ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f modify_ppolicy_module.ldif

Restart slapd to load the module (copy and paste the following as a single line)

root@example:/# slapd -h "ldap:/// ldapi:/// ldaps:///" -u openldap -g openldap &
sleep 3

Write the .ldif file to setup ppolicy.so on the openLDAP server

root@example:/# cat > enable_ppolicy.ldif << 'EOF'
dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcPPolicyConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=default,ou=policies,dc=example,dc=com
EOF
ldapadd -Q -Y EXTERNAL -H ldapi:/// -f enable_ppolicy.ldif

4- Add schemas

Let's add one of the policy schemas that comes with openLDAP, these files can be found in /etc/ldap/schema/. The pre-installed schemas exists in both converted .ldif files that can be loaded directly, as well native .schema formats which can be converted to .ldif files with the package schema2ldif (not loaded by default in this container) if neccesary.

root@example:/# ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/corba.ldif
adding new entry "cn=corba,cn=schema,cn=config"

The following schemas will be loaded by default:

root@example:/# ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=schema,cn=config dn
dn: cn=schema,cn=config

dn: cn={0}core,cn=schema,cn=config

dn: cn={1}cosine,cn=schema,cn=config

dn: cn={2}nis,cn=schema,cn=config

dn: cn={3}inetorgperson,cn=schema,cn=config

dn: cn={4}corba,cn=schema,cn=config

5- Configure TLS/SSL certificates

Create cert directories and generate certificates

root@example:/# mkdir -p /etc/ldap/certs
root@example:/# cd /etc/ldap/certs

CA key

root@example:/etc/ldap/certs# certtool --generate-privkey --bits 4096 --outfile ca-key.pem

CA template

root@example:/etc/ldap/certs# cat > ca.info <<EOF
cn = Example Company CA
ca
cert_signing_key
expiration_days = 3650
EOF

CA certificate

root@example:/etc/ldap/certs# certtool --generate-self-signed --load-privkey ca-key.pem --template ca.info --outfile ca-cert.pem


Now let's generate the key, template, and certificate of the openLDAP server
Server key

root@example:/etc/ldap/certs# certtool --generate-privkey --bits 2048 --outfile ldap01_slapd_key.pem

Server template

root@example:/etc/ldap/certs# cat > ldap01.info <<EOF
organization = Example Company
cn = example.com
tls_www_server
encryption_key
signing_key
expiration_days = 365
EOF

Server certificate

root@example:/etc/ldap/certs# certtool --generate-certificate \
  --load-privkey ldap01_slapd_key.pem \
  --load-ca-certificate ca-cert.pem \
  --load-ca-privkey ca-key.pem \
  --template ldap01.info \
  --outfile ldap01_slapd_cert.pem


Last but not least, fix some permissions because certificates are very delicate when checking authorization

root@example:/etc/ldap/certs# chgrp openldap ldap01_slapd_key.pem
root@example:/etc/ldap/certs# chmod 640 ldap01_slapd_key.pem


Bundle our certs (CA and server) into one and set the right perms

root@example:/etc/ldap/certs# cat ldap01_slapd_cert.pem ca-cert.pem > ldap01_slapd_cert_full.pem
root@example:/etc/ldap/certs# chown root:openldap ldap01_slapd_cert_full.pem
root@example:/etc/ldap/certs# chmod 640 ldap01_slapd_cert_full.pem


Restart slapd (copy and paste as a single line)

root@example:/etc/ldap/certs# slapd -h "ldap:/// ldapi:/// ldaps:///" -u openldap -g openldap &
sleep 3

Re-apply TLS config

root@example:/etc/ldap/certs# cat > /tmp/certinfo.ldif <<EOF
dn: cn=config
changetype: modify
replace: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ldap/certs/ca-cert.pem
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/certs/ldap01_slapd_cert_full.pem
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/certs/ldap01_slapd_key.pem
EOF
root@example:/etc/ldap/certs# ldapmodify -Y EXTERNAL -H ldapi:/// -f /tmp/certinfo.ldif


Stop temp, start final with LDAPS

root@example:/etc/ldap/certs# pkill slapd
root@example:/etc/ldap/certs# slapd -h "ldap:/// ldaps:/// ldapi:///" -u openldap -g openldap -d 0 &

Finally set this ENV variable and make it permanent

root@example:/etc/ldap/certs# export LDAPTLS_CACERT=/etc/ldap/certs/ca-cert.pem
root@example:/etc/ldap/certs# echo 'export LDAPTLS_CACERT=/etc/ldap/certs/ca-cert.pem' >> ~/.bashrc
root@example:/etc/ldap/certs# source ~/.bashrc


Check STARTTLS

root@example:/etc/ldap/certs# ldapwhoami -x -ZZ -H ldap://example.com

Check SSL/ldaps

root@example:/etc/ldap/certs# ldapwhoami -x -H ldaps://example.com

Both should return Anonymous.

Another example to try STARTTLS/ldap it is working:

openssl s_client -connect 127.0.0.1:389 -starttls ldap -servername example.com

SSL/ldaps

openssl s_client -connect example.com:636 -servername example.com

Both will show the connection to the openLDAP server showing the CN(dc=example,dc=com)

To connect to the server via STARTTLS, use port 389, to connect to the server via SSL, use port 636, both auth method Simple. If asked, accept the certificate as with any certificate, or copy the CA file that resides inside ldapdock from out of the container to our host system certificate trust directory (/usr/local/share/ca-certificates/ works for any Debian based distribution):

> sudo docker cp ldapdock:/etc/ldap/certs/ca-cert.pem ./mycacert.crt
> sudo cp mycacert.crt /usr/local/share/ca-certificates/
> sudo update-ca-certificates

In both cases by default the login "user" and password are:
BIND DN=cn=admin,dc=example,dc=com
BIND password=admin