Deploying OpenLDAP on Openshift with Users Bootstrapped

Ritesh Raj
7 min readNov 27, 2020

Recently, we integrated an external Identity Provider, Keycloak (based on RedHat SSO) with one of the Packaged Application deployments on Openshift 4.3. However, Keycloak require new Users to be created manually each time a new instance of the Packaged Application was integrated with it. This issue was resolved by Federating the Users into Keycloak by setting up a LDAP server. I had setup a LDAP server using OpenLDAP product with all our team members added as Users in the OpenLDAP server.

I have created my own Docker image (of course using a Dockerfile) using osixia/openldap official image from Docker hub (osixia/openldap image). What you are going to read next could help either you or many other folks in their Use-cases, where the client application requires integration with an external Identity and Access Management provider such as Keycloak with their organisation’s members added as Users in the federated LDAP server.

Pre-requisites

1. Access to an Openshift Cluster.

2. Docker Desktop running on Windows 10.

3. Admin access to the Cluster or know the process to reach out to the Cluster Admin.

Building Container Image

  1. To setup an OpenLDAP server on Openshift with all Users added in the image, we require a LDIF (LDAP Data Interchange Format) file which we are going to bootstrap into the image. This file will have all the team members added as Users, all Users added as members of Admin Group and one entry for Policy group. The file bootstrap.ldif content is shown below for quick reference:
version: 1# Entry 1: cn=user1@your.company.com,dc=your,dc=company,dc=com
dn: cn=user1@your.company.com,dc=your,dc=company,dc=com
changetype: add
cn: user1@your.company.com
displayname: User 1
givenname: User
mail: user1@your.company.com
objectclass: inetOrgPerson
sn: 1
userpassword: 1234
# Entry 2: cn=user2@your.company.com,dc=your,dc=company,dc=com
dn: cn=user2your.company.com,dc=your,dc=company,dc=com
changetype: add
cn: user2@your.company.com
displayname: User 2
givenname: User
mail: user2@your.company.com
objectclass: inetOrgPerson
sn: 2
userpassword: 1234
# Entry 3: ou=Groups,dc=your,dc=company,dc=com
dn: ou=Groups,dc=your,dc=company,dc=com
changetype: add
objectclass: organizationalUnit
ou: Groups
# Entry 4: cn=Admins,ou=Groups,dc=your,dc=company,dc=com
dn: cn=Admins,ou=Groups,dc=your,dc=company,dc=com
changetype: add
cn: Admins
objectclass: groupOfUniqueNames
uniquemember: cn=user1@your.company.com,dc=your,dc=company,dc=com
uniquemember: cn=user2@your.company.com,dc=your,dc=company,dc=com
# Entry 5: ou=policies,dc=your,dc=company,dc=com
dn: ou=policies,dc=your,dc=company,dc=com
changetype: add
objectclass: organizationalUnit
ou: policies
# Entry 6: cn=default,ou=policies,dc=your,dc=company,dc=com
dn: cn=default,ou=policies,dc=your,dc=company,dc=com
changetype: add
cn: default
objectclass: organizationalRole
objectclass: pwdPolicy
objectclass: top
pwdattribute: 2.5.4.35
pwdcheckquality: 2
pwdminlength: 4
pwdmustchange: TRUE
# Entry 7: ou=Users,dc=your,dc=company,dc=com
dn: ou=Users,dc=your,dc=company,dc=com
changetype: add
objectclass: organizationalUnit
ou: Users

2. Create a Dockerfile as shown below to build an image for the OpenLDAP server with Users bootstrapped in it.

#Pull the latest base image from Dockerhub
FROM osixia/openldap
# Set the environment variables
ENV LDAP_ORGANISATION="Your Company Name" \
LDAP_DOMAIN="your.company.com" \
LDAP_BASE_DN="dc=your,dc=company,dc=com"
COPY bootstrap.ldif /container/service/slapd/assets/config/bootstrap/ldif/50-bootstrap.ldif

3. Build an image using the above Dockerfile:

docker build -t your_dockerhub_repository_name/openldap_bootstrap .

4. Push the image to your Docker hub repository:

docker push your_dockerhub_repository_name/openldap_bootstrap

Deploying Image in Openshift

5. Create a new project name openldap in your OpenShift Cluster:

oc new-project openldap

6. Create a service account named openldap to run the OpenLDAP container:

oc create serviceaccount openldap

7. Add the service account created in Step 6 to the anyuid Security Context Constraint:

oc adm policy add-scc-to-user anyuid system:serviceaccount:openldap:openldap

8. Build a new OpenLDAP pod using the image pushed in Step 8 above. Make sure you use a strong password instead of anypassword shown in the command below.

oc new-app — name openldap your_dockerhub_repository_name/openldap_bootstrap -e LDAP_ADMIN_PASSWORD=anypassword

Above command will have an ImagePullBack error showing for the Pod on Openshift. To fix this, open Windows Powershell to run the next 2 commands (Note: The next 2 commands will work only in Windows Powershell prompt):

$var='{"spec":{"strategy":{"type":"Recreate"},"template":{"spec":{"serviceAccountName":"openldap"}}}}'  | ConvertTo-Json


oc patch dc/openldap -p $var

Exposing Service Externally/Publicly

Note: Steps 9 to 11 are required only when you want to federate the Users in OpenLDAP server to an IdP such as Keycloak. Otherwise, you can skip Steps 9 to 11.

9. Check if your openldap pod is running. Now, let’s expose this service externally/publicly by exposing the deployment config openldap with type as Load-Balancer. This will provide us an External IP address to access the OpenLDAP server publicly:

oc expose dc/openldap — type=LoadBalancer — name=ingress-openldap

10. Get the external IP address assigned to the service using:

oc get svc

11. Make a note of the External IP address shown after executing the above command:

Persisting Data in OpenLDAP pod

12. Run the following command to create PVCs in Openshift and mount volumes for the OpenLDAP pod to persist data created on it.

oc set volume dc/openldap — add — name=ldap-data — mount-path=/var/lib/ldap -t pvc — claim-name=ldap-data — claim-size=1Goc set volume dc/openldap — add — name=ldap-config — mount-path=/etc/ldap/slapd.d -t pvc — claim-name=ldap-config — claim-size=1G

Enabling Password Policy overlay (ppolicy) module

13. OpenLDAP has a dynamically loadable module which can enforce password policies. It allows to define policies for the userPassword attribute. Policies can define the maximum login attempts with the wrong password, maximum age of a password and many more. Get the name of the running pod:

oc get pods

14. Access the remote shell of the running pod (replace the your-pod-name with the pod name you get from previous step):

oc rsh your-pod-name

Note: Steps 15 to 18 should be run inside the shell prompt of the running pod:

15. Load the ppolicy module using following command (copy and paste all 5 lines shown below together as they are a single block of commands):

ldapmodify -Q -Y EXTERNAL -H ldapi:///
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: ppolicy.la

Press Enter twice. You will see below message:

Once you see the above message, press CTRL + C to exit.

16. Check if the ppolicy module is loaded:

slapcat -n 0 | grep olcModuleLoad

You should see ppolicy as one of modules as shown below:

17. Add a new entry for default policy as shown below (copy and paste all 5 lines shown below together as they are a single block of commands):

ldapadd -Q -Y EXTERNAL -H ldapi:///
dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcPPolicyConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=default,ou=policies,dc=your,dc=company,dc=com

Press Enter twice. You will see below message:

Once you see the above message, press CTRL + C to exit.

18. Type below command to exit the remote shell of the running pod.

exit

Deploying PHPLDAPAdmin pod for the front-end UI

19. Create a Dockerfile as shown below to build an image for the PHPLDAPAdmin server which will connect the OpenLDAP service created above.

#Pull the latest base image from Dockerhub
FROM osixia/phpldapadmin

# Set the environment variables
ENV PHPLDAPADMIN_HTTPS="false"

EXPOSE 8090

20. Build an image using the above Dockerfile:

docker build -t your_dockerhub_repository_name/phpldapadmin_new .

21. Push the image to your Docker hub repository:

docker push your_dockerhub_repository_name/phpldapadmin_new

22. Build a new phpldapadmin pod using the image pushed in the above step.

oc new-app --name phpldapadmin your_dockerhub_repository_name/phpldapadmin_new -e PHPLDAPADMIN_LDAP_HOSTS=openldap

23. Above command will have an ImagePullBack error showing for the Pod on Openshift. To fix this, open Powershell to run the next 2 commands (Note: The next 2 commands will work only in Powershell prompt):

$var='{"spec":{"strategy":{"type":"Recreate"},"template":{"spec":{"serviceAccountName":"openldap"}}}}'  | ConvertTo-Json

oc patch dc/phpldapadmin -p $var

24. Expose the phpldapadmin service using Openshift route to access it, using a browser:

oc expose svc/phpldapadmin

Accessing PHPLDAPAdmin login page using browser

25. Navigate to Networking → Routes in the Openshift Console page under project openldap. Click on the Location URL shown below:

26. The URL will take you to the login page of the phpldapadmin UI which connects to the backend openldap pod.

27. Click on the login icon on the left-hand side menu.

28. Enter the following values:

Login DN: cn=admin,dc=your,dc=company,dc=com

Password: Password set by you in Step 8 for OpenLDAP pod.

Click on Authenticate and you will see the home page with root tree.

29. Click on the + symbol to expand root tree dc=your,dc=company,dc=com. You can view all the entries created in the OpenLDAP server.

You can use the PHP LDAP Admin UI for User Administration such as adding/removing User, resetting their passwords etc.

Thanks for reading this article. Hope this helps many if not all.

--

--