Traefik kann als moderner, cloud-nativer Anwendungsproxy mit den meisten Cluster-Technologien zusammenarbeiten. Für dieses Tutorial wird Traefik auf Kubernetes bereitgestellt und fungiert als Edge-Router, der sämtlichen eingehenden Traffic von *.beispieldomain.org empfängt.

IngressRoutes werden verwendet, um Subdomains wie app.beispieldomain.org zu erstellen und den Traffic zu verschiedenen Services im Cluster zu leiten. Ein cert-manager läuft ebenfalls im Cluster, um automatisch TLS-Zertifikate für jede neu erstellte Subdomain hinzuzufügen. Diese Konfiguration scheint sehr beliebt zu sein, um neue Services in einem Cluster zu kreieren und zu konfigurieren und sie unter verschiedenen Subdomains zugänglich zu machen.

Allerdings bietet die Standardkonfiguration von Traefik keine Authentifizierungsmechanismen zum Schutz vor unbefugten Zugriffen. Einige Services verfügen über eigene Authentifizierungsmethoden, andere wiederum nicht. Es besteht die Möglichkeit, mittels Basic-Auth eine sehr einfache Autorisierungsschranke hinzuzufügen – jedoch würden diese Optionen das Verwalten von Konten und Berechtigungsnachweisen an mehreren Stellen erfordern, was den sensiblen Prozess der Autorisierung zusätzlich belastet und verkompliziert.

Eine Lösung könnte darin bestehen, einen einzigen dedizierten Authentifizierungsservice einzurichten, der den Zugang zu anderen Services auf Subdomains verwaltet und idealerweise die Möglichkeit bietet, Konten nach einer gewissen Logik zu gruppieren, um den Verwaltungsaufwand der Zugriffsberechtigungen für jedes Konto zu reduzieren.

Eine Forward-Auth-Middleware würde dann jeglichen Traffic zu einer Subdomain auf Eingangsebene abfangen und danach überprüfen, ob der Request authentifiziert und autorisiert ist. Danach würde diese den Traffic zum angeforderten Service weiterleiten oder ablehnen, wodurch eine gruppenbasierte Zugangskontrolle auf Subdomains ermöglicht wird.

Abbildung der Authentifizierung mit Traefik, Authentik und Kubernetes

Authentik und Alternativen

Authentik ist ein Open-Source-Identity-Provider, der einfach einzurichten ist und nahtlos mit Traefik zusammenarbeitet. Der Identity Provider bietet ein Forward-Auth, das leicht konfigurierbar und erweiterbar ist. Es unterstützt eine feingranulare Zugangskontrolle auf Subdomains und ist die IAM-Lösung, die in diesem Tutorial verwendet wird.

Es gibt einige Alternativen mit verschiedenen Ansätzen, die das gleiche Problem lösen können, sie unterscheiden sich allerdings bei der Komplexität sowie bei der Einrichtung und Verwaltung von Benutzern:

  • Azure Active Directory ist ein Produkt von Microsoft mit vielen Funktionen, einschließlich der Zugriffskontrolle auf Subdomains mit einem Reverse-Proxy wie Traefik. Gleiche Funktionen und Features mit Open-Source- und selbst gehosteten Lösungen zu replizieren kann schwierig sein.

  • Keycloak ist ein beliebtes Open-Source-Projekt für Identitätsmanagement mit einer Vielzahl von Funktionen. Es bietet keine eigene Forward-Auth-Funktionalität, kann aber in Kombination mit diesem Forward-Auth-Service verwendet werden. Dieses Projekt unterstützt jedoch keine Autorisierung basierend auf Benutzergruppen und wurde in letzter Zeit nicht aktualisiert. Keycloak oder ein anderer OIDC-Provider können auch in Kombination mit oauth2-proxy verwendet werden, um Forward-Auth-Funktionalität mit Gruppen zu ermöglichen. Die Konfiguration kann jedoch schwierig sein.

  • Authelia ist ein Open-Source-Authentifizierungsserver und lässt sich gut in Traefik und Kubernetes integrieren. Er unterstützt auch eine feingranulare Zugriffskontrolle, die auf verschiedene Subdomains angewendet werden kann.

Installation von Authentik

Authentik beinhaltet ein Helm Chart für die Installation in Kubernetes, das es ermöglicht, alles unkompliziert zum Laufen zu bringen:

helm repo authentik hinzufügen https://charts.goauthentik.io
helm repo update

Für das Chart müssen ein paar Werte gesetzt werden. Dazu erstellen wir eine neue Datei ­authentik-values.yaml und ersetzen die Secrets und den Host Name. Das Chart wird außerdem eine neue Redis- und PostgreSQL-Instanz erzeugen. Wenn man bereits eigene dedizierte Datenbanken betreibt, setzt man enabled: false und fügt eine Verbindung zu der bereits laufenden dedizierten Instanz hinzu.

authentik:
  secret_key: "<my-secret-key>"
  # Das sendet anonyme Nutzungsdaten, Stack Traces bei Fehlern und
  # Performance-Daten an sentry.io und ist vollständig opt-in
  error_reporting:
    enabled: false
  postgresql:
    password: "<postgres-password>"

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

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

Anschließend installieren wir es im Cluster:

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

Nach der Installation sollte die Ausgabe des Helm Charts einen Hinweis darauf geben, dass man die Einrichtungsseite von Authentik besuchen soll. Sie sollte in etwa so aussehen: https://authentik.beispieldomain.org/if/flow/initial-setup/

Ein Klick auf Admin Interface leitet uns zur Admin-Oberfläche weiter, in der wir später Benutzer, Gruppen und Autorisierungsregeln hinzufügen.

Hinzufügen von Authentifizierung zu IngressRoutes

Nun, da Authentik installiert ist und läuft, kann der Authentifizierungsmechanismus zu den Ingressen bestehender Services hinzugefügt und konfiguriert werden. Zuerst muss dazu eine ­Middleware hinzugefügt werden. Diese steuert, wohin der abgefangene Traffic umgeleitet werden soll und welche Header nach der Authentifizierung weitergeleitet werden sollen. Hierzu erstellen wir eine middleware.yaml mit folgendem Inhalt und passen ggf. den Namensraum in den Metadaten und die Adresse an.

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: authentik
spec:
  forwardAuth:
    # Wenn die Cluster-DNS richtig eingerichtet ist, können wir die Service-Adresse hier verwenden
   Adresse: http://authentik.default.svc.cluster.local/outpost.goauthentik.io/auth/traefik
    trustForwardHeader: true
    # diese Header werden hinzugefügt und weitergeleitet
    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

Damit wird es angewendet:

kubectl apply -f middleware.yaml

Danach kann diese Middleware dann zu den Ingress-Konfigurationen hinzugefügt werden. In diesem Setup wird davon ausgegangen, dass mehrere andere Anwendungen laufen, die durch Authentik geschützt werden müssen. Zu Demonstrationszwecken wird das folgende Setup mit einem Deployment, einem Service und einer ingressRoute, die die Beispiel-App unter https://app.beispieldomain.org für jeden verfügbar macht, durch Hinzufügen der Middleware geschützt:

---
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.beispieldomain.org`)
      services:
        - name: app
          port: 80
  tls: {}
---

Die von Traefik verwalteten ingressRoutes leiten den https-Traffic an den Kubernetes-Service und dann an das Deployment weiter. Durch Hinzufügen der Middleware wird der Traffic abgefangen und umgeleitet, um den Authentifizierungsstatus und die Autorisierung zu prüfen. Falls erforderlich, wird ein Login-Bildschirm angezeigt, andernfalls werden die angegebenen Header hinzugefügt und der Traffic an den Service weitergeleitet.

Das Beispiel hat nun zwei Regeleinträge:

  1. den ursprünglichen Einstiegspunkt, der https-Traffic auf der Subdomain app.beispieldomain.org an Port 80 des App-Services weiterleitet. Hier wird die Middleware hinzugefügt und eine zusätzliche niedrige Priorität sorgt dafür, dass die Regel zuletzt ausgewertet wird.

  2. leitet Traffic mit einem bestimmten PathPrefix mit höherer Priorität an Authentik weiter. Das sind von Authentik erstellte Redirects, die für subdomain-spezifische Berechtigungen verwendet werden, wenn nur ein Teil der bekannten Benutzer von Authentik auf diese Subdomain zugreifen soll.

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: app
spec:
  entryPoints:
    - websecure
  routes:
    # eine Standard-Ingress-Regel, die den Traffic von app.beispieldomain.org zu einem Service namens "App" leitet
    - kind: Rule
      match: Host(`app.beispieldomain.org`)
      priority: 10 # diese generische Route benötigt eine niedrigere Priorität, um zuletzt ausgewertet zu werden
      services:
        - name: app
          port: 80
      middlewares: # hier fügen wir die Middleware hinzu, die den Traffic auf dieser Route abfangen wird
        - name: authentik
    #  eine zweite Regel, die gemäß einem angehängten Pfad zum authentischen Login umleitet
    - kind: Rule
      match: "Host(`app.mydomian.org`) && PathPrefix(`/outpost.goauthentik.io/`)"
      priority: 15 # dies benötigt eine höhere Priorität
      services:
        - kind: Service
          name: authentik.default.svc.cluster.local # wenn das DNS-Cluster korrekt eingerichtet ist, können wir hier die Dienstadresse von Authentik verwenden
  tls: {} # TLS wird von cert-manager verwaltet

Dies sind alle benötigten Kubernetes-Ressourcen. Der Rest kann in der Authentik-Admin-Konsole konfiguriert werden.

Konfigurieren von Authentik

Wir öffnen die Verwaltungskonsole unter https://authentik.beispieldomain.org/if/admin/ und navigieren über das Seitenmenü zu Applications > Provider. Dort erstellen wir einen neuen Proxy Provider, geben ihm einen Namen und wählen den default implicit authorization flow. Dann wählen wir den Modus Forward auth (single application) und geben die Subdomain der Anwendung als external host an. Dieser Schritt kann für alle Anwendungen wiederholt werden, die in ihren Subdomains bereitgestellt werden. Mit dieser Einrichtung können verschiedene Zugriffsregeln auf verschiedene Provider angewendet werden. Der Modus „Forward auth“ (Domain-Ebene) kann verwendet werden, wenn die Richtlinien für alle Subdomains gleich sind. Dann wird nur ein Provider benötigt.

Screenshot der Authentik-Benutzeroberfläche für das Erstellen eines Providers für die Anwendung
Screenshot der Authentik-Benutzeroberfläche für das Erstellen eines Proxy-Providers für die Anwendung
Screenshot der Authentik-Benutzeroberfläche für das Festlegen von Weiterleitungsautorisierung und externem Host

Im nächsten Schritt navigieren wir über das Seitenmenü zu Applications > Applications und erstellen eine neue Anwendung. Dort geben wir ihr einen Namen, einen Slug und wählen den zuvor erstellten Provider.

Screenshot der Authentik-Benutzeroberfläche für das Erstellen einer Anwendung für die App
Screenshot der Authentik-Benutzeroberfläche für das Erstellen einer Anwendung für die App

Dann gehen wir zu Applications > Outposts und bearbeiten den bestehenden Outpost, indem wir auf das kleine Bearbeitungssymbol auf der rechten Seite klicken. Dort fügen wir die zuvor erstellte Anwendung zu dem Outpost hinzu, indem wir sie anklicken und dann mit dem Update-Button übernehmen. Die Anwendung wird blau markiert, wenn sie ausgewählt ist.

Screenshot der Authentik-Benutzeroberfläche für das Bearbeiten des Outposts
Screenshot der Authentik-Benutzeroberfläche für das Bearbeiten des Outposts

Von diesem Moment an werden die User aufgefordert ihre Anmeldedaten einzugeben, wenn sie versuchen, auf app.beispieldomain.org zuzugreifen. Dies gilt für jeden Benutzer mit einem Authentik bekannten Account, egal ob dieser dort angelegt wurde oder von einem externen Identity Provider bereitgestellt wird. Die Anzahl von potenziellen Usern kann weiter eingeschränkt werden, indem man sie in verschiedene Gruppen einteilt und restriktive Richtlinien anwendet. Einige User dürfen auf eine Anwendung zugreifen, manche nur auf eine andere Anwendung und andere User wiederum dürfen auf beide Anwendungen zugreifen. Im folgenden Beispiel wird eine Richtlinie hinzugefügt, die besagt, dass nur Mitglieder einer bestimmten Gruppe auf app.beispieldomain.org zugreifen dürfen.

Konfigurieren von Gruppenrichtlinien

Wir navigieren zunächst über das Seitenmenü zu Directory > Groups und erstellen hier eine neue Gruppe. Wir geben ihr einen Namen und speichern sie. Eine Möglichkeit, User manuell zu Gruppen hinzuzufügen, ist sie unter Directory > Users zuzuweisen.

Screenshot der Authentik-Benutzeroberfläche für das Hinzufügen von Gruppen
Screenshot der Authentik-Benutzeroberfläche für das Hinzufügen von Gruppen

Danach gehen wir zu Applications > Applications und bearbeiten die Zugriffsrichtlinie, indem wir auf den Namen der Anwendung klicken und den Tab zu Policy / Group / User Bindings wechseln. Dort fügen wir mit Bind existing policy eine gruppenbasierte Richtlinie hinzu, wechseln in den Modus Group und wählen die zuvor erstellte Gruppe als Ziel aus.

Screenshot der Authentik-Benutzeroberfläche für das Hinzufügen von Gruppen

Mit dieser Einrichtung können nun nur Mitglieder dieser Gruppe auf app.beispieldomain.org zugreifen. Die Richtlinien für jede Applikation können so kreativ und komplex wie nötig sein, Authentik bietet die Tools für komplexere Zugriffsrechte. In der Regel reicht es aus, die User Base in ein paar Gruppen zu unterteilen.

Zusammenfassung

Mit einem bestehenden Kubernetes-Setup und Traefik als Edge-Router bietet Authentik eine einfache Möglichkeit, eine zentralisierte Authentifizierungslösung für alle anderen Anwendungen im Cluster einzurichten. Auf diese Weise kann mit Hilfe von Traefik-Middlewares ein Forward-Auth-Mechanismus geschaffen werden. Es muss nichts in die Anwendungen selbst integriert werden, stattdessen kann der Authentifizierungsschritt auf diese Weise on top aufgesetzt werden. Alle Benutzerinformationen werden an einem einzigen Punkt verwaltet. Zusätzlich können alle Benutzer in Gruppen eingeteilt werden und diese Gruppen mit Authentik verwendet werden, um gruppenbasierte Zugriffsmechanismen für jede Subdomain zu erstellen. Auf diese Weise kann mit Hilfe von Traefik-Middlewares ein Forward-Auth-Mechanismus geschaffen werden. Es muss nichts in die Anwendungen selbst integriert werden, stattdessen kann der Authentifizierungsschritt auf diese Weise on top aufgesetzt werden.