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
3- 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
4- 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