Introduction
I will setup a ready to be used LDAP and LDAPS server in AWS.
I will use a certificate issued by Let’s encrypt.
Versions used
I used a t2.micro EC2 based on:
- Ubuntu 22.04
- OpenLDAP: slapd 2.5.14
Installation
OpenLDAP installation
sudo apt-get update
sudo apt-get install slapd ldap-utils -y
Then check that the installation is good by running:
sudo slapcat
Run the following:
sudo dpkg-reconfigure slapd
Run the following again for checking if all is good:
sudo slapcat
Let’s import more data inside the LDAP, copy the text below in a file that you call test.ldif (ldif = LDAP Data Interchange Format):
version: 1
dn: ou=people,dc=example,dc=org
objectClass: organizationalUnit
objectClass: top
ou: people
dn: ou=roles,dc=example,dc=org
objectClass: organizationalUnit
objectClass: top
ou: roles
dn: uid=user2,ou=people,dc=example,dc=org
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: user2
sn: user2
uid: user2
userPassword: {SSHA}QsCR6t7gBDVXAYVpitypkj1bcjTWtIxvKgzp7g==
dn: uid=admin,ou=people,dc=example,dc=org
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: admin
sn: admin
uid: admin
userPassword: {SSHA}AWSnTbjAtAXP7JbuCszenf8cTvHx7K1Hs6almQ==
dn: uid=user1,ou=people,dc=example,dc=org
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: user1
sn: user1
uid: user1
userPassword: {SSHA}NhJ/TICWzrcS6sncjgebPWvGXxWoCVmpjAw+1Q==
dn: cn=desk_a,ou=roles,dc=example,dc=org
objectClass: groupOfUniqueNames
objectClass: top
cn: desk_a
uniqueMember: uid=user1,ou=people,dc=example,dc=org
dn: cn=kpi,ou=roles,dc=example,dc=org
objectClass: groupOfUniqueNames
objectClass: top
cn: kpi
uniqueMember: uid=admin,ou=people,dc=example,dc=org
uniqueMember: uid=user1,ou=people,dc=example,dc=org
dn: cn=admin,ou=roles,dc=example,dc=org
objectClass: groupOfUniqueNames
objectClass: top
cn: admin
uniqueMember: uid=admin,ou=people,dc=example,dc=org
dn: cn=cs_root,ou=roles,dc=example,dc=org
objectClass: groupOfUniqueNames
objectClass: top
cn: cs_root
uniqueMember: uid=admin,ou=people,dc=example,dc=org
dn: cn=user,ou=roles,dc=example,dc=org
objectClass: groupOfUniqueNames
objectClass: top
cn: user
uniqueMember: uid=admin,ou=people,dc=example,dc=org
uniqueMember: uid=user1,ou=people,dc=example,dc=org
uniqueMember: uid=user2,ou=people,dc=example,dc=org
dn: cn=eur_usd,ou=roles,dc=example,dc=org
objectClass: groupOfUniqueNames
objectClass: top
cn: eur_usd
uniqueMember: uid=user2,ou=people,dc=example,dc=org
Then run the following:
sudo ldapadd -x -D "cn=admin,dc=example,dc=org" -W -c -f test.ldif
If you run sudo slapcat again, you will see that we imported some data.
We imported 3 users: admin, user1 and user2, each one has a password similar to its login (e.g. user1 password is user1).
If you run this command for instance, you will display all the users:
ldapsearch -x -H ldap://localhost -D "cn=admin,dc=example,dc=org" -w "admin" -b "ou=people,dc=example,dc=org" "(uid=*)"
# extended LDIF
#
# LDAPv3
# base <ou=people,dc=example,dc=org> with scope subtree
# filter: (uid=*)
# requesting: ALL
#
# admin, people, example.org
dn: uid=admin,ou=people,dc=example,dc=org
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: admin
sn: admin
uid: admin
userPassword:: e1NTSEF9QVdTblRiakF0QVhQN0pidUNzemVuZjhjVHZIeDdLMUhzNmFsbVE9PQ=
=
# user1, people, example.org
dn: uid=user1,ou=people,dc=example,dc=org
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: user1
sn: user1
uid: user1
userPassword:: e1NTSEF9TmhKL1RJQ1d6cmNTNnNuY2pnZWJQV3ZHWHhXb0NWbXBqQXcrMVE9PQ=
=
# user2, people, example.org
dn: uid=user2,ou=people,dc=example,dc=org
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: user2
sn: user2
uid: user2
userPassword:: e1NTSEF9UXNDUjZ0N2dCRFZYQVlWcGl0eXBrajFiY2pUV3RJeHZLZ3pwN2c9PQ=
=
# search result
search: 2
result: 0 Success
# numResponses: 4
# numEntries: 3
LDAPS configuration
Make sure you open those ports for the EC2 machine:
- 636 and 389 for LDAPS and LDAP
- 80 for the let’s encrypt certificate generation
Then provision a free domain under https://www.duckdns.org/domains, mine is called nboldap.duckdns.org.
Make sure you put your EC2 public IP address next to your domain and click update ip:
Let’s generate the certificate with let’s encrypt, I entered my mail and answered Yes to the 2 questions:
sudo apt-get install certbot
sudo certbot certonly --standalone -d nboldap.duckdns.org
If all is successful you should read:
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/nboldap.duckdns.org/fullchain.pem
Key is saved at: /etc/letsencrypt/live/nboldap.duckdns.org/privkey.pem
This certificate expires on 2023-09-12.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
We were unable to subscribe you the EFF mailing list because your e-mail address appears to be invalid. You can try again later by visiting https://act.eff.org.
Run the following:
cd /etc/ldap
sudo mkdir ssl_certificates
sudo cp /etc/letsencrypt/live/nboldap.duckdns.org/fullchain.pem ssl_certificates
sudo cp /etc/letsencrypt/live/nboldap.duckdns.org/cert.pem ssl_certificates
sudo cp /etc/letsencrypt/live/nboldap.duckdns.org/privkey.pem ssl_certificates
sudo chown -R openldap:openldap ssl_certificates
Create the file tls-config.ldif under /etc/ldap, you should use sudo here:
dn: cn=config
changetype: modify
replace: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ldap/ssl_certificates/fullchain.pem
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/ssl_certificates/cert.pem
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/ssl_certificates/privkey.pem
Then run
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f tls-config.ldif
You should see:
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn=config"
Edit /etc/default/slapd:
sudo vim /etc/default/slapd
Replace:
SLAPD_SERVICES="ldap:/// ldapi:///"
Set it to:
SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"
Edit /etc/ldap/ldap.conf:
sudo vim /etc/ldap/ldap.conf
Comment the line starting with TLS_CACERT and add new lines:
#TLS_CACERT /etc/ssl/certs/ca-certificates.crt
TLS_CACERT /etc/ldap/ssl_certificates/fullchain.pem
TLS_REQCERT allow
Restart the OpenLDAP server:
sudo systemctl restart slapd
You can check the status with:
sudo systemctl status slapd
Verify that the LDAP and LDAPS are working by running:
ldapsearch -x -H ldaps://nboldap.duckdns.org -D "cn=admin,dc=example,dc=org" -w "admin" -b "ou=people,dc=example,dc=org" "(uid=*)"
ldapsearch -x -H ldap://nboldap.duckdns.org -D "cn=admin,dc=example,dc=org" -w "admin" -b "ou=people,dc=example,dc=org" "(uid=*)"
Testing with Python
You can use this Python code for instance, make sure you install the ldap3 library, replace the values according to your setup of course:
from ldap3 import Server, Connection, SUBTREE
# LDAP server configuration
server_url = 'ldaps://nboldap.duckdns.org'
base_dn = 'dc=example,dc=org'
admin_dn = 'cn=admin,dc=example,dc=org'
admin_password = 'admin' #this is my admin password :)
# Connect to the LDAP server
server = Server(server_url, use_ssl=True, get_info="SCHEMA")
conn = Connection(server, admin_dn, admin_password, auto_bind=True)
# Search for user1
search_filter = '(uid=user1)'
conn.search(search_base=base_dn, search_filter=search_filter, search_scope=SUBTREE)
# Get the search results
if conn.entries:
for entry in conn.entries:
print(entry.entry_dn)
else:
print('No results found.')
# Close the connection
conn.unbind()