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
- Contents and overview
- Installing OpenLDAP
- Installing Keycloak
- Linking Keycloak and OpenLDAP
- OIDC Kubectl Login with Keycloak
- Authenticate any web app using ingress annotations
- Gitea (requires LDAP)
- Simple Docker Registry
- 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. OU
s 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 ou
s 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.