| About Me

Installing OpenLDAP on Kubernetes with Helm

In this post we cover how to install OpenLDAP on Kubernetes and how to test that it is working using the command line.

LDAP while an older - and in some ways more challenging to work with - approach to SSO than something like OIDC, is still the de-facto standard.

There are many popular applications which don't support OIDC but do support LDAP. This is likely to be the case for many years to come so for now, any robust SSO solution is likely to need to support LDAP.

This post is part of a series on single sign on for Kubernetes

  1. Contents and overview
  2. Installing OpenLDAP
  3. Installing Keycloak
  4. Linking Keycloak and OpenLDAP
  5. OIDC Kubectl Login with Keycloak
  6. Authenticate any web app using ingress annotations
  7. Gitea (requires LDAP)
  8. Simple Docker Registry
  9. Harbor Docker Registry with ACL

Pre-requisites

This assumes you have CLI access to a Kubernetes cluster, will be working in a namespace called identity and have both Helm 3 and Kubectl installed and working locally. Finally it assumes that you're using NGINX for Ingress along with cert manager for SSL certificates with a Cluster Issuer called letsencrypt-production.

If your configuration is different, the majority of the steps will be the same, but you'll need to change the ingress annotations accordingly.

The source for this series of tutorials can be found here: https://github.com/TalkingQuickly/kubernetes-sso-guide and cloned with:

git clone [email protected]:TalkingQuickly/kubernetes-sso-guide.git

All commands in the tutorial assume that they're being executed from the root of this cloned repository.

Installing OpenLDAP

The Helm chart for OpenLDAP was deprecated as part of the deprecation of the stable chart repository. So while we await a replacement to appear, the most recent version is mirrored in the repo for this tutorial.

An example helm values file is abailable in openldap/values-openldap.yml and we'll want to customise the following sections:

# Default configuration for openldap as environment variables. These get injected directly in the container.
# Use the env variables from https://github.com/osixia/docker-openldap#beginner-guide
env:
  LDAP_ORGANISATION: "Talking Quickly Demo"
  LDAP_DOMAIN: "ssotest.staging.talkingquickly.co.uk"
  LDAP_BACKEND: "hdb"
  LDAP_TLS: "true"
  LDAP_TLS_ENFORCE: "false"
  LDAP_REMOVE_CONFIG_AFTER_SETUP: "true"
  LDAP_READONLY_USER: "true"
  LDAP_READONLY_USER_USERNAME: readonly
  LDAP_READONLY_USER_MASSWORD: password

# Default Passwords to use, stored as a secret. If unset, passwords are auto-generated.
# You can override these at install time with
# helm install openldap --set openldap.adminPassword=<passwd>,openldap.configPassword=<passwd>
adminPassword: admin
configPassword: 9h8sdfg9sdgfjsdfg8sdgsdfjgklsdfg8sdgfhj

customLdifFiles:
  initial-ous.ldif: |-
    dn: ou=People,dc=ssotest,dc=staging,dc=talkingquickly,dc=co,dc=uk
    objectClass: organizationalUnit
    ou: People

    dn: ou=Group,dc=ssotest,dc=staging,dc=talkingquickly,dc=co,dc=uk
    objectClass: organizationalUnit
    ou: Group

In this case dc=ssotest,dc=staging,dc=talkingquickly,dc=co,dc=uk is the base domain I'm using for my test Kubernetes cluster. For the purposes of setting up our LDAP server, this is just an internal identifier, so does not need to map to any sort of DNS.

The customLdifFiles section is being used to pre-seed the LDAP database. In this case with two organizationalUnit's, one of type People which will be used to store individual users and another with type Group will be used to store Groups. OUs can be though of simplistically as analogous to folders in a traditional file system, this article on ous is well worth a read to get a better understanding for how they fit together.

We can now install OpenLDAP with the following command:

helm upgrade --install openldap ./charts/openldap --values openldap/values-openldap.yml

Once it installs, you should see some output confirming success and some examples of how to access the server.

Importantly this will include the commands for retrieving the config and administration passwords, e.g:

kubectl get secret --namespace identity openldap -o jsonpath="{.data.LDAP_ADMIN_PASSWORD}" | base64 --decode; echo
kubectl get secret --namespace identity openldap -o jsonpath="{.data.LDAP_CONFIG_PASSWORD}" | base64 --decode; echo

Using The OpenLDAP CLI

Although we'll primarily manage our LDAP directory through KeyCloak, it's useful to have a basic familiarity with the CLI for testing purposes. Splunk has a great introduction to the CLI here.

We'll start by using kubectl proxy to expose our LDAP server locally:

kubectl port-forward --namespace identity \
      $(kubectl get pods -n identity --selector='release=openldap' -o jsonpath='{.items[0].metadata.name}') \
      3890:389

In a separate terminal execute (most unix systems, inc OSX, come with ldapsearch installed, if yours does not, you'll need to download it, for debian based distributions you'll need ldap-utils):

ldapsearch -x -H ldap://localhost:3890 -b dc=ssotest,dc=staging,dc=talkingquickly,dc=co,dc=uk -D "cn=admin,dc=ssotest,dc=staging,dc=talkingquickly,dc=co,dc=uk" -w password

This return something along the lines of:

objectClass: organization
o: Talking Quickly's Demo
dc: k4stest4

# admin, k4stest4.talkingquickly.co.uk
dn: cn=admin,dc=k4stest4,dc=talkingquickly,dc=co,dc=uk
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9YjM1a0hLYXVwcDlvcGU5R1N2UE5qcFBLd3FxdUorWFk=

# People, k4stest4.talkingquickly.co.uk
dn: ou=People,dc=k4stest4,dc=talkingquickly,dc=co,dc=uk
objectClass: organizationalUnit
ou: People

# Group, k4stest4.talkingquickly.co.uk
dn: ou=Group,dc=k4stest4,dc=talkingquickly,dc=co,dc=uk
objectClass: organizationalUnit
ou: Group

# search result
search: 2
result: 0 Success

# numResponses: 6
# numEntries: 4

It's worth perusing this Stack Overflow post to understand a little more about the dn, dc terminology.

Note that my test domain ssotest.staging.talkingquickly.co.uk results in a dn (Distinguished Name) made up of a comma separated list of dc (Domain Components) dc=ssotest,dc=staging,dc=talkingquickly,dc=co,dc=uk. We can also see that our ous from the customLdiffFiles have been created.

So now we have an LDAP server and have a simple way of checking what's stored in it. We can now move onto installing Keycloak.

  1. Contents and overview
  2. Installing OpenLDAP
  3. Installing Keycloak
  4. Linking Keycloak and OpenLDAP
  5. OIDC Kubectl Login with Keycloak
  6. Authenticate any web app using ingress annotations
  7. Gitea (requires LDAP)
  8. Simple Docker Registry
  9. Harbor Docker Registry with ACL