Architecture

During the installation and configuration of the services you see below, I realized that even in the lab, user management is starting to become very confusing.
That’s why I turned to OpenLDAP, an open source and very simple tool. At first, I won’t go into great configuration details.
Only simple LDAP, without TLS or Database.

The service will be installed in a Container/Docker, the exposed ports will be 389 and 636 (for future TLS configuration).

There are countless images with OpenLDAP, some of which are often cited in articles and forums, but have been out of date for a long time.

I opted for bitnami/openldap, as it has VMWare behind it and has recent updates. The latest version at the time I’m writing (2.6.7) has some flaw, as the OpenLDAP service doesn’t start, and that’s why I decided to use 2.5.17.
One of the reasons for choosing bitnami/openldap is because of the ease of configuring the “memberOf” module in relation to others.

Docker

OpenLDAP, by default, does not have a way to create user groups and assign them as memberOf. Making this type of assignment helps a lot with filters, for example, when logging into a service, the user must be in group “X”. This is only possible with “memberOf”.
Therefore, we will have to manually configure and enable this module in the image.

OpenLDAP does not have a GUI, maintenance is all done by bash. Right after creating the container, I will leave some examples, to create some OUs, groups, the first user and assign it to a group. Also to delete the users that OpenLDAP brings as an example.


There are several GUI interfaces, among the ones I evaluated, I highlight 3:

In the next topic I will show the basic use of LDAP Accoun Manager, it has a very friendly interface, and despite being more tedious to configure, it is easy to install.

Installation

Important point, in docker compose, I already have the certificate settings, in my case: devops-db_info.
It is necessary to either remove the ENV lines: LDAP_TLS_* or create a certificate with your DNS.
I bought the wrong certificate, which doesn’t use a wildcard, so for now I’m going to create the configurations without TLS.

First, let’s create a file locally called memberof.ldif, it will have the configurations for the module. Create in a folder that will be shared with the Docker Container. If you want to redo the image or manually copy the file into the Container and not use volumes, feel free.

LDAP Data Interchange Format

(/work/ldap/memberof.ldif)

dn: cn=module,cn=config
cn: module
objectClass: olcModuleList
olcModulePath: /opt/bitnami/openldap/lib/openldap
olcModuleLoad: memberof.so
olcModuleLoad: refint.so
dn: olcOverlay=memberof,olcDatabase={2}mdb,cn=config
objectClass: olcMemberOf
objectClass: olcOverlayConfig
olcOverlay: memberof
dn: olcOverlay=refint,olcDatabase={2}mdb,cn=config
objectClass: olcConfig
objectClass: olcOverlayConfig
objectClass: olcRefintConfig
objectClass: top
olcOverlay: refint
olcRefintAttribute: memberof member manager owner

Then I create the container using docker create above.

docker run -tid \
  --network local-bridge \
  --name srv-ldap-01 \
  -p 389:389 \
  -p 636:636 \
  --env LDAP_ADMIN_USERNAME=admin \
  --env LDAP_PORT_NUMBER=389 \
  --env LDAP_ADMIN_PASSWORD='JbBmKx#lK@ZX4*amqd5l' \
  --env LDAP_ROOT=dc=devops-db,dc=info \
  --env LDAP_ADMIN_DN=CN=admin,DC=devops-db,DC=info \
  --env LDAP_EXTRA_SCHEMAS=cosine,inetorgperson,nis,memberof \
  --volume /work/ldap/memberof.ldif:/bitnami/openldap/memberof.ldif \
  --volume /work/ldap/memberof.ldif:/opt/bitnami/openldap/etc/schema/memberof.ldif \
  bitnami/openldap:2.5.17

Check the container log:

docker container logs srv-ldap-01

It should end the creation with something like this:

 21:09:14.34 INFO  ==> ** Starting slapd **
660c73fa.15014241 0x7f721b0d1740 @(#) $OpenLDAP: slapd 2.5.17 (Feb 22 2024 18:13:25) $
        @fa2d8b9b89f1:/bitnami/blacksmith-sandox/openldap-2.5.17/servers/slapd
660c73fa.16ed22ca 0x7f721b0d1740 slapd starting

At this point, the LDAP server is created and functional.

Info Box

The admin user and password are in Docker Compose: JbBmKx#lK@ZX4*amqd5l

And, I will use DNS:

nslookup ldap.devops-db.info
Server:         172.21.5.72
Address:        172.21.5.72#53

Name:   ldap.devops-db.info
Address: 172.21.5.72

Creation of OU, Groups and Users.

OpenLDAP comes with some tools, for example:
ldapsearch, ldapadd, ldapdelete, ldapmodify, ldapwhoami, etc… are Command-Line Tools for managing LDAP, in the example below, I create the initial structure of the Lab:

In some folder on your host, create the ldif file with the initial instructions:

(initial-devops-db.ldif)

cat << EOL > /work/ldap/initial-devops-db.ldif
## OUs
dn: ou=AdminGroups,dc=devops-db,dc=info
objectclass: organizationalUnit
ou: AdminGroups

dn: ou=SecurityGroups,dc=devops-db,dc=info
objectclass: organizationalUnit
ou: SecurityGroups

dn: ou=ServiceGroups,dc=devops-db,dc=info
objectclass: organizationalUnit
ou: ServiceGroups

dn: ou=UserGroups,dc=devops-db,dc=info
objectclass: organizationalUnit
ou: UserGroups

## Default human User Group
dn: cn=AllUsers,ou=SecurityGroups,dc=devops-db,dc=info
cn: AllUsers
gidnumber: 10000
objectclass: posixGroup

## Users
dn: cn=Fausto Branco,ou=UserGroups,dc=devops-db,dc=info
cn: Fausto Branco
gidnumber: 10000
givenname: Fausto
homedirectory: /home/fbranco
loginshell: /bin/bash
objectclass: posixAccount
objectclass: inetOrgPerson
objectclass: organizationalPerson
objectclass: person
sn: Branco
uid: fbranco
uidnumber: 10000
userpassword: XXXXXXXXXXXXXXXXX

## Group MemberOf
dn: cn=GitLabGroup,ou=SecurityGroups,dc=devops-db,dc=info
cn: readers
member: cn=Fausto Branco,ou=UserGroups,dc=devops-db,dc=info
objectclass: groupOfNames
EOL

Then, use the ldapadd tool to create the file objects in LDAP.
Note, create the users you need and the userpassword. These are the examples I will use in the Lab.

ldapadd -x -H ldap://172.21.5.72:389 -D "CN=admin,DC=devops-db,DC=info" -W -f /work/ldap/initial-devops-db.ldif

Remember that every interaction with LDAP requires a login, this combination:

Info Box

“Admin User” = "CN=admin,DC=devops-db,DC=info"
“Admin Pass” = JbBmKx#lK@ZX4*amqd5l

And to delete the OpenLdap example structure:

ldapdelete -v -x -H ldap://172.21.5.72:389 -D "CN=admin,DC=devops-db,DC=info" "cn=user01,ou=users,dc=devops-db,dc=info" -w "JbBmKx#lK@ZX4*amqd5l"
ldapdelete -v -x -H ldap://172.21.5.72:389 -D "CN=admin,DC=devops-db,DC=info" "cn=readers,ou=users,dc=devops-db,dc=info" -w "JbBmKx#lK@ZX4*amqd5l"
ldapdelete -v -x -H ldap://172.21.5.72:389 -D "CN=admin,DC=devops-db,DC=info" "cn=user02,ou=users,dc=devops-db,dc=info" -w "JbBmKx#lK@ZX4*amqd5l"
ldapdelete -v -x -H ldap://172.21.5.72:389 -D "CN=admin,DC=devops-db,DC=info" "ou=users,dc=devops-db,dc=info" -w "JbBmKx#lK@ZX4*amqd5l"

Some more query examples:

ldapsearch -v -x -H ldap://172.21.5.72:389 -b "cn=Fausto Branco,ou=UserGroups,dc=devops-db,dc=info" -D "CN=admin,DC=devops-db,DC=info" -w "JbBmKx#lK@ZX4*amqd5l"

ldapsearch -v -x -H ldap://172.21.5.72:389 -b "cn=Fausto Branco,ou=UserGroups,dc=devops-db,dc=info" "(memberof=cn=GitLabGroup,ou=SecurityGroups,dc=devops-db,dc=info)" -D "CN=admin,DC=devops-db,DC=info" -w "JbBmKx#lK@ZX4*amqd5l"
ldapsearch -v -x -H ldap://172.21.5.72:389 -b "cn=Fausto Branco,ou=UserGroups,dc=devops-db,dc=info" "(memberof=cn=AnyOtherGroup,ou=SecurityGroups,dc=devops-db,dc=info)" -D "CN=admin,DC=devops-db,DC=info" -w "JbBmKx#lK@ZX4*amqd5l"

ldapsearch -v -x -H ldap://ldap.devops-db.info:389 -b "cn=Fausto Branco,ou=UserGroups,dc=devops-db,dc=info" -D "CN=admin,DC=devops-db,DC=info" -w "JbBmKx#lK@ZX4*amqd5l"

To validate LDAP authentication:

ldapwhoami -vvv -H 'ldap://ldap.devops-db.info:389' -D 'cn=Fausto Branco,ou=UserGroups,dc=devops-db,dc=info' -x -W