Authentifizierung und Autorisierung in k3s

In diesem Blogpost widme ich mich dem Thema Authentifizierung und Autorisierung. Besonders in einem Kubernetes-Cluster, selbst in einem Heimsetup, ist es wichtig, dass nur autorisierte Benutzer Zugriff auf sensible Daten und Anwendungen haben. Um dies zu gewährleisten, nutze ich in meinem Setup Authentik in Kombination mit dem OAuth2-Proxy, um meine Anwendungen abzusichern. Als Beispiel zeige ich dir, wie ich das Kubernetes-Dashboard schütze.

Warum Authentifizierung und Autorisierung?

Wenn du Anwendungen in deinem Cluster betreibst, ist es entscheidend, dass nur befugte Personen darauf zugreifen können. Besonders wenn dein Cluster von außen erreichbar ist, sind starke Authentifizierungs- und Autorisierungslösungen notwendig. Der Unterschied zwischen diesen beiden Begriffen:

  • Authentifizierung: Wer bist du? (z.B. durch Login via OAuth2)
  • Autorisierung: Was darfst du tun? (Rollen und Berechtigungen im System)

Für dieses Setup verwende ich Authentik, eine Open-Source-Lösung für Authentifizierung, die mit OAuth2 arbeitet. Um den Zugriff auf Anwendungen zu steuern, nutze ich den OAuth2-Proxy, der Anfragen abfängt und überprüft, ob ein Nutzer authentifiziert ist.

Authentik: Das zentrale Authentifizierungssystem

Authentik ist eine moderne Open-Source-Auth-Lösung, die mir erlaubt, OAuth2, SSO (Single-Sign-On) und weitere Authentifizierungsmechanismen in meinem Cluster zu integrieren. Es ist besonders flexibel und bietet die Möglichkeit, externe Anwendungen, wie das Kubernetes-Dashboard, über OAuth2 abzusichern.

Vorteile von Authentik:

  • OAuth2-Unterstützung: Ideal, um externe Dienste zu sichern.
  • SSO (Single-Sign-On): Einmal einloggen und auf mehrere Anwendungen zugreifen.
  • Einfach erweiterbar: Unterstützt viele Protokolle wie LDAP, SAML und OAuth2.

Die Installation und Konfiguration von Authentik habe ich über FluxCD automatisiert, um es einfach in meinen GitOps-Workflow zu integrieren. Hier ist ein Beispiel für die grundlegende Installation in meinem Setup:

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: authentik
  namespace: authentik
spec:
  spec:
      chart: authentik
      version: 2024.8.0 # auto-update to semver bugfixes only 
      sourceRef:
        kind: HelmRepository
        name: authentik
        namespace: default
  values:
    ...

Authentic benötigt zusätzlich eine Datenbank, ich habe mich für Postgres entschieden und eingerichtet. Ich nutze dafür cloudnative-pg von truecharts. Damit bekomme ich einen Kubernetes Operator, der mir Postgres-Instanzen im Namespace installieren kann.

OAuth2-Proxy: Der Authentifizierungs-Filter

Der OAuth2-Proxy ist ein kleines, aber leistungsstarkes Tool, das sich zwischen den Benutzer und die Anwendung schaltet. Es überprüft, ob der Nutzer über OAuth2 authentifiziert wurde, bevor er Zugriff auf die Anwendung erhält. In Kombination mit Authentik sorgt dies für eine nahtlose Authentifizierung in deinem Kubernetes-Cluster.

Warum OAuth2-Proxy?

  • Absicherung von Anwendungen: OAuth2-Proxy stellt sicher, dass nur authentifizierte Nutzer auf bestimmte Services zugreifen können.
  • Flexibel: Kann mit verschiedenen OAuth2-Providern wie Authentik, Google oder GitHub verwendet werden.

Auch der OAuth2-Proxy wird bei mir über FluxCD installiert:

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: oauth2-proxy
  namespace: oauth
spec:
  chart:
    spec:
      chart: oauth2-proxy
      version: 7.7.16 # auto-update to semver bugfixes only 
      sourceRef:
        kind: HelmRepository
        name: oauth2-proxy
        namespace: default 
  values:
    ...

Kubernetes-Dashboard absichern

Das Kubernetes-Dashboard ist ein nützliches Tool zur Verwaltung des Clusters, aber es ist wichtig, dieses zusätzlich abzusichern, um unerlaubte Zugriffe zu verhindern. Mithilfe des OAuth2-Proxys und Authentik kann ich sicherstellen, dass nur autorisierte Nutzer darauf zugreifen können.

Schritt-für-Schritt Konfiguration:

  1. Authentik einrichten: Erstelle eine OAuth2-Anwendung in Authentik und füge den OAuth2-Proxy als Client hinzu.
  2. OAuth2-Proxy konfigurieren: Verknüpfe den Proxy mit der Authentik-Anwendung.
  3. Dashboard sichern: Deaktiviere den Ingress und nutze den OAuth2-Proxy mit einer Upstreamkonfiguration.

Den Helmchart des OAuth2-Proxies kann man so konfigurieren via values.yaml:

...

  config:
    configFile: |-
        email_domains = [ "*" ]
        upstreams = [ "http://kubernetes-dashboard-kong-proxy" ]
        pass_access_token = true

...

    extraArgs:
      provider: oidc
      provider-display-name: "Authentik"
      skip-provider-button: "true"
      pass-authorization-header: "true" 
      set-authorization-header: true
      oidc-issuer-url: https://<authentik-domain>/application/o/kube-apiserver/
      redirect-url: https://<dashboard-domain>/oauth2/callback
      #redis-connection-url: "redis://oauth2-proxy-redis-master" # if you want to use redis
      session-store-type: cookie # alternative is to use redis or cookie
      cookie-refresh: 119m

...

    ingress:
      enabled: true
      className: "" 
      path: /
      pathType: ImplementationSpecific
      hosts:
        - <dashboard-domain>
      labels: {}
      annotations:
        external-dns.alpha.kubernetes.io/hostname: <dashboard-domain>. # creates a DNS entry
        external-dns.alpha.kubernetes.io/target: <CNAME or A-Record?>.
      tls:
        - secretName: <secret name that contains https certificate> 
          hosts:
            - <dashboard-domain> 
Code-Sprache: PHP (php)

RBAC: Benutzerrollen und Berechtigungen verwalten

Zusätzlich zur Authentifizierung durch Authentik wird im Kubernetes-Cluster die Autorisierung durch RBAC (Role-Based Access Control) geregelt. RBAC ermöglicht es, spezifische Berechtigungen basierend auf Rollen zu vergeben, was besonders nützlich ist, wenn mehrere Benutzer im Cluster arbeiten oder Zugriff auf bestimmte Anwendungen benötigen.

RBAC funktioniert, indem es Rollen (Roles) definiert, die mit Berechtigungen (Permissions) verbunden sind. Diese Rollen können dann bestimmten Benutzern oder Gruppen zugewiesen werden, um festzulegen, welche Aktionen sie im Cluster ausführen dürfen. So kannst du genau steuern, welche Befugnisse jeder Benutzer hat.

Zum Beispiel habe ich für das Kubernetes-Dashboard spezifische RBAC-Rollen definiert, die sicherstellen, dass nur autorisierte Benutzer das Dashboard verwalten oder sensible Daten einsehen können. Hier ein Beispiel für eine einfache RBAC-Konfiguration für das Dashboard:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: kubernetes-dashboard
  name: dashboard-user
rules:
- apiGroups: [""]
  resources: ["pods", "services", "endpoints", "configmaps"]
  verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dashboard-user-binding
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: dashboard-user
subjects:
- kind: User
  name: "<Benutzername>"
  apiGroup: rbac.authorization.k8s.ioCode-Sprache: JavaScript (javascript)

In dieser Konfiguration bekommt der Benutzer die dashboard-user-Rolle zugewiesen, die ihm Zugriff auf Ressourcen wie Pods und Services im Kubernetes-Dashboard gewährt.

Auf meinem Cluster habe ich es mir einfach gemacht und die vorhandene Rolle cluster-admin verwendet. Das Vorgehen ist allerdings nur empfehlenswert, wenn die Anzahl der Administratoren sehr klein ist. Hiermit wird die Clusterrolle einer Gruppe aus authentik zugewiesen:

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: oidc-group-admin-kube-apiserver
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin 
subjects:
- kind: Group
  name: admin-kube-apiserver

Desweiteren habe ich den kube-api-server in der ansible-Konfiguration aktiviert:

      kube-apiserver-arg:
        - "oidc-issuer-url=https://<authentik-url/application/o/kube-apiserver/"
        - "oidc-client-id=kube-apiserver"
        - "oidc-username-claim=email"
        - "oidc-groups-claim=groups"Code-Sprache: JavaScript (javascript)

RBAC und Authentik

Die Authentifizierung über Authentik wird in Kombination mit RBAC noch leistungsfähiger, da du für authentifizierte Benutzer direkt Rollen definieren kannst. Das bedeutet, dass du nicht nur sicherstellst, dass Benutzer authentifiziert sind, sondern auch genau festlegen kannst, was sie im Cluster tun dürfen. So kann z.B. ein Administrator Zugriff auf alle Ressourcen haben, während ein normaler Benutzer nur lesenden Zugriff auf bestimmte Bereiche des Dashboards erhält.

Vorteile und erweiterte Möglichkeiten

Neben dem Kubernetes-Dashboard kann diese Lösung auf andere Anwendungen in deinem Cluster ausgeweitet werden. Jede Anwendung, die OAuth2 unterstützt, lässt sich so absichern. Außerdem gibt es Alternativen wie Keycloak oder Dex, die ähnliche Funktionen bieten, je nach deinen Anforderungen.

Fazit

Durch die Kombination von Authentik für die Authentifizierung und RBAC für die Autorisierung habe ich eine flexible und sichere Lösung für mein Kubernetes-Cluster implementiert. Benutzer können sich nicht nur sicher anmelden, sondern erhalten auch nur die Rechte, die sie benötigen.

Weitere Blogposts aus der k3s-Reihe

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert