As a modern cloud-native application proxy, Traefik works with most clustering technologies. For the purpose of this tutorial, Traefik is deployed on kubernetes and acts as an edge router to receive all traffic incoming from *.mydomain.org.

IngressRoutes are used to create subdomains, for example app.mydomain.org, to route traffic to ­different services deployed on the cluster. A cert-manager is also running in the cluster to automatically add TLS certificates for each newly created subdomain. This configuration seems to be very popular for creating and configuring new services in a cluster and making them accessible under different subdomains.

However, the default configuration of Traefik does not provide any authentication mechanisms to protect the services from being accessed by unauthorised users. Some services may provide their own authentication mechanisms, other services may not have any means for authentication. With Traefik there is the option to add basic-auth with a middleware for a very simple authorization gate. However, these options would entail managing accounts and credentials at multiple places, adding overhead and complexity to the sensitive process of authorization.

One solution here could be to set up a single dedicated authentication service, managing the access to other services on subdomains and ideally having a feature to group accounts by some logic to reduce the overhead of managing access permissions for each account. A forward-auth middleware then would intercept any traffic to a subdomain at ingress-level, check if the request is authenticated and authorized and then forwarding or denying the traffic to the requested service, thus enabling a group-based access control on subdomains.

Authentication with Traefik, Authentik and Kubernetes

Authentik and Alternatives

Authentik is an open-source identity provider which is easy to set up and works seamlessly with Traefik, providing a forward-auth that is easy to configure and extend. It supports fine-grained ­access control on subdomains and is the IAM solution selected for this tutorial.

There are a few alternatives which can solve the same problem, although they may have slightly different approaches and complexity in setup and managing users:

  • Azure Active Directory is a Microsoft product with many features, including access control on subdomains with a reverse proxy like Traefik. Replicating all the same features with open-source and self-hosted solutions can be difficult.

  • Keycloak is a popular open-source project for identity management with a wide variety of features but does not provide forward-auth functionality on its own. It can be used in combination with this forward-auth service. That project however, does not support authorization based on user-groups and has not been updated recently. Keycloak or any other OIDC Provider can also be used in combination with oauth2-proxy to enable forward-auth ­functionality with groups. However, its configuration can be challenging.

  • Authelia is an open-source authentication server with good integration into Traefik and kubernetes. It also supports fine-grained access control, which can be applied to various subdomains.

Installing Authentik

Authentik provides a helm chart for installation in kubernetes, making it easy to get everything up and running:

helm repo add authentik https://charts.goauthentik.io
helm repo update

A few values have to be set for the chart. Create a authentik-values.yaml file and replace the ­secrets and the host name. The chart will additionally deploy a new Redis and PostgreSQL instance. If you already have your own dedicated databases running, set enabled: false and add a connection to the already running dedicated instance.

authentik:
  secret_key: "<my-secret-key>"
  # This sends anonymous usage-data, stack traces on errors and
  # performance data to sentry.io, and is fully opt-in
  error_reporting:
    enabled: false
  postgresql:
    password: "<postgres-password>"

ingress:
  enabled: true
  hosts:
    - host: authentik.mydomain.org
      paths:
        - path: "/"
          pathType: Prefix

postgresql:
  enabled: true
  postgresqlPassword: "<postgres-password>"
redis:
  enabled: true

Then install it to the cluster:

helm upgrade --install authentik authentik/authentik -f authentik-values.yaml

After the installation, the output of the helm chart should instruct you to visit the initial setup page of your authentik. It should look something like this: https://authentik.mydomain.org/if/flow/initial-setup/

A click on Admin Interface will redirect you to the administration board, where we will later add users, groups and authorization rules.

Adding Authentication to IngressRoutes

Now that Authentik is installed and running, the authentication mechanism can be added and configured to ingresses of existing services. First a middleware needs to be added. This controls where the intercepted traffic should be redirected and what Headers should be forwarded after authentication. Create a middleware.yaml with the following contents and adjust the namespace in metadata and address if necessary.

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: authentik
spec:
  forwardAuth:
    # if cluster dns is set up correctly we can use the service address here
    address: http://authentik.default.svc.cluster.local/outpost.goauthentik.io/auth/traefik
    trustForwardHeader: true
    # these headers will be added and forwarded
    authResponseHeaders:
      - X-authentik-username
      - X-authentik-groups
      - X-authentik-email
      - X-authentik-name
      - X-authentik-uid
      - X-authentik-jwt
      - X-authentik-meta-jwks
      - X-authentik-meta-outpost
      - X-authentik-meta-provider
      - X-authentik-meta-app
      - X-authentik-meta-version

Apply it with:

kubectl apply -f middleware.yaml

After that this middleware then can be added to the ingress configurations. This setup assumes that there are several other applications running, which need to be protected by Authentik. For demonstrational purposes the following setup containing a deployment, a service and an ingressRoute which makes the example app available at https://app.mydomain.org for everyone, will then be protected by adding the middleware:

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
        - name: app
          image: containous/whoami:v1.5.0
---
apiVersion: v1
kind: Service
metadata:
  name: app
  labels:
    app: app
spec:
  type: ClusterIP
  ports:
    - port: 80
      name: app
  selector:
    app: app
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: app
spec:
  entryPoints:
    - websecure
  routes:
    - kind: Rule
      match: Host(`app.mydomain.org`)
      services:
        - name: app
          port: 80
  tls: {}
---

The ingressRoutes managed by Traefik routes https-traffic to the kubernetes-service and then the deployment. By adding the middleware, the traffic gets intercepted and redirected to check for authentication status and authorization. A login screen will be displayed if necessary, otherwise the specified Headers will be added and traffic will be forwarded to the service.

To achieve this the configuration for the ingressRoute is extended as follows. The example now has two rules entries:

  1. the original entrypoint that routes https traffic on the subdomain app.mydomain.org to port 80 of the app service. The middleware is added here and an additional low priority ensures that the rule is to be evaluated last.
  2. routes traffic with a specific PathPrefix to Authentik with a higher priority. These are redirects created by Authentik used for subdomain specific permissions, when only a part of the known users of Authentik shall access this subdomain. Additionally, the cluster service address is used here to target the Authentik service.
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: app
spec:
entryPoints:
    - websecure
  routes:
    # a standard ingress rule routing traffic from app.mydomain.org to a service named app
    - kind: Rule
      match: Host(`app.mydomain.org`)
      priority: 10 # this generic route needs a lower priority to be evaluated last
      services:
        - name: app
          port: 80
      middlewares: # we add the middleware here which will intercept traffic along this route
        - name: authentik
    # a second rule which will redirect to the authentic login according to an attached path
    - kind: Rule
      match: "Host(`app.mydomian.org`) && PathPrefix(`/outpost.goauthentik.io/`)"
      priority: 15 # this needs a higher priority
      services:
        - kind: Service
          name: authentik.default.svc.cluster.local # if the cluster dns is set up correctly, we can use the service address of authentik here
  tls: {} # tls is handled by cert-manager

These are all the kubernetes resources needed. The rest can be configured in the Authentik admin console.

Configuring Authentik

Open up the admin console at https://authentik.mydomain.org/if/admin/ and navigate on the side-menu to Applications > Providers. Create a new Proxy Provider here, give it a name and select the default implicit authorization flow. Also select the Forward auth (single application) mode and enter the subdomain of the application as external host. This step can be replicated for all applications deployed at their subdomains. With this setup, different access policies can be applied to different providers. The Forward auth (domain level) mode can be used if the policies are the same for all subdomains. Then only one provider is needed.

Screenshot of the authentik user interface for creating a Provider for your app
Screenshot of the authentik user interface for creating a Provider for your app
Screenshot of the authentik user interface for setting Forward Auth and External Host

The next step is to navigate on the side-menu to Applications > Applications and create a new Application. Give it a name and a slug and select the Provider created previously.

Screenshot of the authentik user interface for creating an Application for your app
Screenshot of the authentik user interface for creating an Application for your app

Then go to Applications > Outposts and edit the existing outpost by clicking on the small edit symbol on the right. Add the previously created Application to the outpost by clicking on it and then apply it with the update button. The application is marked blue when it is selected.

Screenshot of the authentik user interface for editing the Outpost
Screenshot of the authentik user interface for editing the Outpost

From this moment onwards, when users try to access app.mydomain.org, they are prompted to enter their credentials. This applies to any user with an account known to Authentik, whether it was created there or is provided by an external Identity Provider.

This set of potential users can be further restricted by organizing them into different groups and applying restricting policies. Some set of users may access one application, while others may only access a different one and some users may do both. This can be configured and in the following example a policy will be added, with that only members of a specific group may access app.mydomain.org.

Configuring Group Policies

First use the side-menu to navigate to Directory > Groups and create a new Group here. Give it a name and save it. One way to add users to groups would be to assign them manually at ­Directory > Users.

Screenshot of the authentik user interface for adding Groups
Screenshot of the authentik user interface for adding Groups

Then go to Applications > Applications and edit the access policy by clicking on the name of the application and switch the tab to Policy / Group / User Bindings. There, add a group based policy with Bind existing policy, switch to the Group mode and select the previously created group as target.

Screenshot of the authentik user interface for adding Groups

With this setup only members of this group can now access app.mydomain.org. The policies for each application can be as creative and complex as necessary and Authentik provides the tools for more complex permission definitions. Usually abstracting the user base into a few groups should be adequate.

Summary

With an existing kubernetes setup and Traefik as the edge router, Authentik provides an easy way to set up a centralized authentication solution for all other applications deployed on the cluster. This way, a forward-auth mechanism can be created by using Traefik middlewares. Nothing has to be integrated into the applications themselves, instead this way, the authentication step can be deployed on top. All user related information is managed at a single point. Additionally, it supports organizing your users into groups and leveraging these groups with Authentik to create group-based access mechanisms specific for each subdomain.