This repository contains Kubernetes manifest files for deploying Traefik Forward Authentication using OpenID Connect with Keycloak.
The traefik-forward-auth
service that this deploys provides support for Google
as well as other OpenID Connect Providers, you can modify this configuration to
match other OIDC providers you integrate with.
Traefik is a Cloud Native Edge Router and reverse proxy that can direct traffic between services based on routing rules. Traefik provides a Ingress Controller that can be deployed into Kubernetes clusters for these purposes. Traefik introduced a Kubernetes Custom Resource Definition (CRD) for Ingress Routes, which is what the configuration in this repository is based on.
Traefik does not provide native authentication for things such as JWT, OpenID Connect, etc. Traefik instead provides a ForwardAuth middleware that can be used to delegate authentication to external service. Upon a successful response Traefik will grant access to the requested resources.
See the Github repository https://github.com/sleighzy/k3s-traefik-v2-kubernetes-crd for instructions and configuration on deploying a k3s cluster with Traefik v2.
k3s is a lightweight, certified Kubernetes distribution, for production workloads from Rancher Labs. k3s installs Traefik, version 1.7, as the Ingress Controller, and a service loadbalancer (klippy-lb) by default so that the cluster is ready to go as soon as it starts up. The instructions below are using Traefik v2 so this cluster has been deployed without the default Traefik 1.7 and Traefik v2 installed separately
The k3s distribution has been used for the examples in this repository.
OpenID Connect is extremely popular authentication and authorization framework based on the OAuth 2.0 protocol.
Keycloak is a widely used production Identity Provider (IdP) and Identity Broker and natively supports authentication mechanisms such as SAML and OpenID Connect. The instructions and configuration in this repository will be integrating with Keycloak.
These instructions do not cover the actual deployment or configuration of Keycloak. They are based on the following assumptions:
- that you have a client id configured in Keycloak, in my example this is
traefik-forward-auth
- that you have the client secret for this client id
- that you have a user, or some form of identity, that you can authenticate with Keycloak
The k3s-keycloak-deployment repository contains my manifest files and instructions for deploying Keycloak on K3s.
The screenshot below shows the Keycloak configuration for the
traefik-forward-auth
client.
The Valid Redirect URIs entry contains the endpoint
https://auth.mydomain.io/_oauth
, this configuration needs to match the
AUTH_HOST
and URL_PATH
environment variables specified in the
001-config.yaml file.
Variable | Description |
---|---|
AUTH_HOST |
This configuration uses the Auth Host Mode which means that a single domain and path is used for the redirect_uri in the authentication flow, e.g. auth.mydomain.io/_oauth . This allows for authenticating multiple subdomains, e.g. app1.mydomain.io , app2.mydomain.io , etc. without needing to add a whitelisted redirect uri and an entry for the cookie for each subdomain. |
URL_PATH |
The URL_PATH environment variable value of /_oauth is the default value for the thomseddon/traefik-forward-auth image but can be overridden. |
The GitHub repository https://github.com/thomseddon/traefik-forward-auth and associated Docker image on Docker Hub is a Traefik Forward Authentication implementation that uses OpenID Connect to authenticate with OpenID Connect Providers. This implementation previously only supported Google as an OIDC Provider, and a number of popular forks were made of this to extend this support. This implementation however now offers full and extensive support for other providers, and extended functionality. The instructions and configuration below are based on this image given it is the original, now offers full support, and is being maintained.
The 001-secrets.yaml file needs to be updated with the client secret (from Keycloak) and the random secret used for signing cookies.
$ echo -n '<my oidc client secret>' | base64
NWNhOWXXXXXXXXXXXXXXXXXXMjcw
$ openssl rand -hex 16 | base64
OWUwNTBmZTM5ODQwNjE1NzJmZGE1ZjQ2NGE4YjVkOTgK
The 001-config.yaml file needs to be updated with the configuration for your
OIDC provider and other information. In the example configuration a Keycloak
realm named homelab
is used.
Refer to the documentation on https://github.com/thomseddon/traefik-forward-auth as to what the items are and their values based on the configuration in the 001-config.yaml file in this repository.
The forward authentication middleware can be configured at a "global" level, for example within the same namespace as the Traefik deployment. This can then be referenced by ingress/ingressroutes in other namespaces.
In Traefik v2.4.10 a change was made so that by default it was not possible to
reference resources in other namespaces. To enable this the Traefik
providers.kubernetescrd.allowCrossNamespace
configuration property needs to
be set to a value of true
. If this is not set to true
then ingresses in
other namespaces will not be able to reference this "global" middleware.
Apply the manifests in order (prefixed by number) to install the secrets,
config, deployment and ingress route for the traefik-forward-auth
delegated
authentication service.
The example configuration is using the original thomseddon/traefik-forward-auth
Docker image. I have provided the sleighzy/traefik-forward-auth
image within
Docker Hub which offers arm64 support for systems such as Raspberry Pi and the
macOS M1 Apple Silicon chip that can be used instead.
Ingress Controllers such as Nginx, Traefik, etc. deployed within Kubernetes can use rules to route traffic to services. Traefik as an Ingress Controller can use the standard Ingress annotations and annotations to configure Traefik to use forward auth for services. Traefik v2 however also has a Kubernetes CRD Ingress Controller which is what this repository uses.
If using the new Traefik IngressRoute
CRD then the 002-middlewares.yaml file
should be applied. This middleware can then be referenced within the
IngressRoute
definition for each service it should be applied to. This removes
a lot of the boiler-plate yaml for adding annotations to all your services.
If using Traefik with the normal Ingress
annotations then the annotations
below would be applied to your service instead.
metadata:
name: whoami
namespace: default
annotations:
kubernetes.io/ingress.class: traefik
ingress.kubernetes.io/auth-type: forward
ingress.kubernetes.io/auth-url: http://traefik-forward-auth.kube-system.svc.cluster.local
ingress.kubernetes.io/auth-response-headers: X-Forwarded-User
Using the classic whoami
service deployment commonly used in Traefik and other
documentation the below IngressRoute
can be applied. This specifies that
requests to the host whoami.mydomain.io
will be routed to the whoami
service
on port 80. This however also references the traefik-forward-auth
middleware
that was applied in the 002-middlewares.yaml file. If the session has not yet
been authenticated then the user will be redirected to Keycloak when attempting
to access whoami.mydomain.io
. Once they have successfully provided their
credentials they will be redirected back to the whoami
service.
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami
namespace: default
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`whoami.mydomain.io`)
middlewares:
- name: traefik-forward-auth
namespace: kube-system
services:
- name: whoami
port: 80
tls:
certResolver: godaddy
Credits to the following for getting this going:
- https://github.com/thomseddon/traefik-forward-auth/blob/master/examples/docker-compose-oidc.yml - OIDC example with current configuration
- thomseddon/traefik-forward-auth#33 - initial k8s configuration, but seems to be out-of-date (or incorrect) with the exact configuration
- https://geek-cookbook.funkypenguin.co.nz/ha-docker-swarm/traefik-forward-auth/keycloak/ - blog post on integrating with Keycloak using Traefik 1.7 and the funkypenguin fork of the traefik-forward-auth service