Setting up LDAP authentication in a Kubernetes cluster run by Deckhouse

Flant staff
Deckhouse blog
Published in
5 min readFeb 22, 2023

--

Deckhouse is an Open Source Kubernetes platform providing a means of creating identical Kubernetes clusters on any infrastructure and managing them in an automated fashion. Deckhouse uses the user-authn module for authentication. It establishes a unified authentication system that integrates with Kubernetes and the web interfaces of the other modules (e.g., Grafana).

user-authn supports various external authentication providers and protocols: GitHub, GitLab, Bitbucket Cloud, Crowd, LDAP, and OIDC. This article shows how to deploy an LDAP server and configure it to enable access to the application.

Preliminary steps

You will need a Kubernetes cluster with the Deckhouse platform installed. You can run the cluster in the cloud or locally (using the kind command). Installation usually takes 15 to 30 minutes.

In the Deckhouse configuration, the publicDomainTemplate parameter must have a valid DNS name pattern that points to the IP addresses of the cluster Ingress controllers. Alternatively, you can also use sslip.io or another similar service. In that case, all you’ll have to do is set publicDomainTemplate to %s.x.x.x.x.sslip.io, where x.x.x.x is your IP address.

Note that the commands and templates below use the openldap-demo namespace. The namespace can be adjusted if necessary.

Configuring the LDAP server

Let’s deploy the LDAP server:

kubectl create -f https://raw.githubusercontent.com/flant/examples/master/2022/11-d8-user-authn/ldap.yaml

Before proceeding, make sure that the server’s Pod is Running:

# kubectl -n openldap-demo get pod 
NAME READY STATUS RESTARTS AGE
ldap-6c949b6c6d-4zxg7 1/1 Running 0 1m

There are two pre-configured users in the LDAP server configuration:

  • johndoe@example.com (password: bar) is a member of the admins group;
  • janedoe@example.com (password: foo) is a member of the admins and developers groups.

Let’s grant access to the developers’ janedoe@example.com for example.

Create a DexProvider resource in the cluster. This will “plug in” the LDAP server we created earlier and will be used for authentication:

kubectl create -f https://raw.githubusercontent.com/flant/examples/master/2022/11-d8-user-authn/dex-provider.yaml

Configuring the web application

Let’s deploy a basic echo web server that generates a web page with the HTTP request information. It will serve as an example application.

Run the following command (don’t forget to set the DOMAINNAME variable to the domain you use):

DOMAINNAME=<YOUR_DOMAIN>
curl https://raw.githubusercontent.com/flant/examples/master/2022/11-d8-user-authn/echo-service.yaml | sed "s/{{ __cluster__domain__ }}/${DOMAINNAME}/" | kubectl create -f -

The application will be deployed to the openldap-demo namespace. The application’s Ingress resource will be configured to use the echo subdomain.

Now let’s check that the echoserver Pod is running:

# kubectl -n openldap-demo get pod 
NAME READY STATUS RESTARTS AGE
echoserver-6944fb9c86-9flgh 1/1 Running 0 1m
ldap-6c949b6c6d-4zxg7 1/1 Running 0 3m

Open the browser and confirm that the application is available at echo.<YOUR_DOMAIN>. No authentication is required.

Enabling authentication

Now for the fun part — let’s restrict access to the app.

To enable authentication, do the following:

  • create a DexAuthenticator resource to deploy the OAuth2 Proxy;
  • enable authentication via the deployed OAuth2 Proxy instance in the application’s Ingress resource.

The OAuth2 Proxy will intercept NGINX requests and handle LDAP authentication.

Create the DexAuthenticator resource and set the DOMAINNAME variable to the domain you are using:

DOMAINNAME=<YOUR_DOMAIN>
curl https://raw.githubusercontent.com/flant/examples/master/2022/11-d8-user-authn/dex-authenticator.yaml | sed "s/{{ __cluster__domain__ }}/${DOMAINNAME}/" | kubectl create -f -

Check that the echoserver-dex-authenticator Pod is up and running in the openldap-demo namespace.

# kubectl -n openldap-demo get pod
NAME READY STATUS RESTARTS AGE
echoserver-6944fb9c86-9flgh 1/1 Running 0 5m
echoserver-dex-authenticator-6bdd57cc95-wvbgk 2/2 Running 1 2m
ldap-6c949b6c6d-4zxg7 1/1 Running 0 8m

Now let’s look at the DexAuthenticator resource. The spec.allowedGroups parameter contains a list of groups to grant access to the application. In our case, it includes the developers group containing the janedoe@example.com user:

# kubectl -n openldap-demo get dexauthenticator echoserver -o yaml
apiVersion: deckhouse.io/v1
kind: DexAuthenticator
...
spec:
allowedGroups:
- developers
...

Now it’s time to configure the Ingress controller to use the OAuth2 Proxy.

Add two annotations to the application’s Ingress resource by running the following commands:

kubectl -n openldap-demo annotate ingress echoserver 'nginx.ingress.kubernetes.io/auth-signin=https://$host/dex-authenticator/sign_in'
kubectl -n openldap-demo annotate ingress echoserver 'nginx.ingress.kubernetes.io/auth-url=https://echoserver-dex-authenticator.openldap-demo.svc.cluster.local/dex-authenticator/auth'

Refresh the application page in your browser. This time, there will be a redirect to the login page:

Select Log in with OpenLDAP Demo. Log in as janedoe@example.com (LDAP password is foo).

Let’s check that everything is working as expected. Open your browser in safe mode and try to log in as johndoe@example.com (LDAP password is bar). You should get the User not in allowed groups error since the johndoe user is not in the developers group.

You can add several authentication providers by creating additional DexProvider resources. In this case, when you enter the application, you will be prompted to select the desired provider from the list.

You can also create a static user — an account with all its data stored in the Kubernetes cluster.

Adding a static user

A unique aspect of static users is that no external authentication providers are involved in authenticating them. To create a static user, you must first create a User custom resource.

Let’s create an openldap-demo@example.com user with an account TTL of 24 hours and a password of bar and make it part of the developers group:

# kubectl create -f - <<"EOF"
apiVersion: deckhouse.io/v1
kind: User
metadata:
name: openldap-demo
spec:
email: openldap-demo@example.com
# echo "bar" | htpasswd -BinC 10 "" | cut -d: -f2
password: '$2a$10$spCnoGzDIRicDfiTmtImwu7sn2Csjj6oWRoLjNs6N/bV3WDsxioui'
groups:
- developers
ttl: 24h
EOF

Note the commands in the comment just above the password field. You can use them to generate a new password.

Once the user is created, you can log into the application by selecting Log in with Email.

For more information about configuring cluster authentication, see the user-authn module documentation. It also provides ready-made usage examples.

Cleaning up our mess

Run the following commands to delete the resources we created earlier:

kubectl delete dexprovider openldap-demo
kubectl delete user openldap-demo
kubectl delete ns openldap-demo

P.S.

Our Getting started guide will help you begin your journey with the Deckhouse Kubernetes platform.

Follow @deckhouseio for updates and join our Telegram chat to ask any questions. Deckhouse’s main GitHub repo might also be useful to ask for feature requests and discuss any issues; your GitHub stars are also much appreciated!

--

--