Veröffentlicht am

Kubernetes RBAC Best Practices 2026: Rollen, Bindings & Least Privilege

Teilen:
Authors

Kubernetes RBAC Best Practices 2026: Rollen, Bindings und Least Privilege richtig umsetzen

TL;DR: Die 7 Regeln, die 90 % der RBAC-Fehlkonfigurationen abdecken

  1. Keine Wildcards. Weder in verbs, noch in resources, noch in apiGroups. Jede Berechtigung explizit aufzählen.
  2. RoleBinding vor ClusterRoleBinding. Der Binding-Typ entscheidet über den Scope, nicht die Rolle. So klein wie möglich binden.
  3. cluster-admin niemals an ServiceAccounts. Nicht an CI/CD, nicht an Operatoren, nicht "nur zum Testen". Ein kompromittierter Pod mit diesem Token ist ein kompromittierter Cluster.
  4. Ein dedizierter ServiceAccount pro Workload, automountServiceAccountToken: false als Default.
  5. Groups binden, keine einzelnen User. Personalwechsel gehören in den Identity Provider, nicht in YAML.
  6. escalate, bind und impersonate wie cluster-admin behandeln. Diese drei Verbs hebeln jede Least-Privilege-Strategie aus.
  7. Jede Rolle vor dem Merge verifizieren: kubectl auth can-i --list, rbac-lookup und Manifest-Linting in der CI.

Wenn Sie nur diese sieben Regeln durchsetzen, sind Sie besser aufgestellt als die Mehrheit der Cluster, die wir in Audits sehen.


Das Problem: RBAC wächst, es wird nie zurückgebaut

Das typische Muster in Clustern von SaaS-Teams mit 10 bis 100 Mitarbeitern: RBAC wurde beim Cluster-Setup einmal konfiguriert, danach kam jede neue Berechtigung "schnell, damit es läuft" dazu. Nach zwei Jahren sieht der Zustand so aus:

  • Der Jenkins- oder ArgoCD-ServiceAccount hat ein ClusterRoleBinding auf cluster-admin, weil ein Deployment vor 18 Monaten an einem Forbidden-Fehler scheiterte und niemand die fehlende Einzelberechtigung debuggen wollte.
  • Eine handgeschriebene ClusterRole dev-access enthält verbs: ["*"] auf resources: ["*"] — funktional identisch mit cluster-admin, aber im Audit unauffälliger, weil sie harmlos benannt ist.
  • Pods laufen mit dem default-ServiceAccount des Namespaces, der irgendwann Berechtigungen bekommen hat, "weil eine App sie brauchte". Jetzt hat jeder Pod im Namespace sie.
  • Ausgeschiedene Mitarbeiter stehen noch als User-Subjects in RoleBindings.

Das ist kein hypothetisches Szenario, sondern der Normalzustand gewachsener Cluster. Die Konsequenz: Der Blast Radius eines einzigen kompromittierten Pods oder geleakten Kubeconfigs ist der gesamte Cluster — inklusive aller Secrets, also Datenbank-Passwörter, API-Keys und TLS-Zertifikate. Wie Sie einen solchen Bestand systematisch aufräumen, beschreibt unser Artikel zum RBAC-Audit mit Least-Privilege-Umbau; hier geht es darum, wie Sie Rollen von Anfang an richtig bauen.


Grundlagen: Vier Ressourcen, ein entscheidendes Detail

RBAC besteht aus genau vier API-Objekten:

RessourceScopeZweck
RoleNamespaceBerechtigungen innerhalb eines Namespaces definieren
ClusterRoleClusterClusterweite Berechtigungen oder wiederverwendbare Rollen-Vorlagen
RoleBindingNamespaceBindet Role oder ClusterRole an Subjects — wirkt nur im eigenen Namespace
ClusterRoleBindingClusterBindet ClusterRole an Subjects — wirkt in allen Namespaces

Das entscheidende Detail, das viele Fehlkonfigurationen erzeugt: Der Binding-Typ bestimmt den Scope, nicht die Rolle. Eine ClusterRole per RoleBinding gebunden wirkt nur im Namespace des Bindings. Dieselbe ClusterRole per ClusterRoleBinding gebunden wirkt überall. Das ist gewollt — so definieren Sie eine Rolle einmal zentral und binden sie pro Namespace — aber es bedeutet auch: Ein einziges falsches kind: ClusterRoleBinding macht aus einer Namespace-Berechtigung eine clusterweite.

Jede Regel (rule) in einer Rolle besteht aus drei Achsen:

  • apiGroups: "" für Core-Ressourcen (Pods, Services, Secrets), apps für Deployments, batch für Jobs, rbac.authorization.k8s.io für RBAC selbst.
  • resources: die Ressourcentypen, inklusive Sub-Ressourcen wie pods/log, pods/exec oder deployments/scale. Sub-Ressourcen müssen separat aufgeführt werden — wer pods lesen darf, darf nicht automatisch Logs lesen oder exec ausführen.
  • verbs: get, list, watch, create, update, patch, delete, deletecollection — plus die drei gefährlichen Sonderfälle escalate, bind und impersonate.

Optional schränkt resourceNames eine Regel auf benannte Objekte ein. Wichtige Einschränkung: resourceNames funktioniert nicht mit list, watch, create und deletecollection, weil der API-Server den Namen bei diesen Operationen nicht vorab kennt.


Praxis: Drei Least-Privilege-Rollen zum Kopieren

1. Entwickler: lesen, Logs, Port-Forward — nicht mehr

Entwickler brauchen im Alltag Einblick in ihre Workloads und die Möglichkeit zu debuggen. Sie brauchen kein delete, kein exec in Produktion und keinen Secret-Zugriff:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
  namespace: produktion
rules:
  - apiGroups: [""]
    resources: ["pods", "services", "configmaps", "events", "endpoints"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get", "list"]
  - apiGroups: [""]
    resources: ["pods/portforward"]
    verbs: ["create"]
  - apiGroups: ["apps"]
    resources: ["deployments", "replicasets", "statefulsets"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["batch"]
    resources: ["jobs", "cronjobs"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-binding
  namespace: produktion
subjects:
  - kind: Group
    name: team-backend
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

Bewusste Entscheidungen: secrets fehlt komplett. pods/exec fehlt — in Produktion ist kubectl exec ein Audit-Problem, im Entwicklungs-Namespace können Sie es ergänzen. Gebunden wird eine Group aus Ihrem Identity Provider (OIDC-Claim, Azure-AD-Gruppe, etc.), kein einzelner User.

2. CI/CD-ServiceAccount: deployen, nicht regieren

Der häufigste RBAC-Unfall überhaupt: cluster-admin für die Pipeline. Eine Deployment-Pipeline braucht tatsächlich nur das hier:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: ci-deployer
  namespace: produktion
automountServiceAccountToken: false
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: ci-deployer
  namespace: produktion
rules:
  - apiGroups: ["apps"]
    resources: ["deployments", "statefulsets"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
  - apiGroups: ["apps"]
    resources: ["deployments/scale"]
    verbs: ["update", "patch"]
  - apiGroups: [""]
    resources: ["services", "configmaps"]
    verbs: ["get", "list", "create", "update", "patch"]
  - apiGroups: ["networking.k8s.io"]
    resources: ["ingresses"]
    verbs: ["get", "list", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ci-deployer-binding
  namespace: produktion
subjects:
  - kind: ServiceAccount
    name: ci-deployer
    namespace: produktion
roleRef:
  kind: Role
  name: ci-deployer
  apiGroup: rbac.authorization.k8s.io

Kein delete (Rollbacks laufen über patch auf die vorherige Image-Version), kein secrets (Secrets kommen über External Secrets Operator oder Sealed Secrets in den Cluster, nicht über die Pipeline), kein RBAC-Schreibzugriff. Für die Pipeline erzeugen Sie ein kurzlebiges Token statt eines statischen Secrets:

kubectl create token ci-deployer --namespace produktion --duration=1h

Deployt Ihre Pipeline in mehrere Namespaces, definieren Sie die Rolle einmal als ClusterRole und binden sie pro Namespace per RoleBinding — nicht per ClusterRoleBinding.

3. Read-Only-Auditor: clusterweit lesen, Secrets ausgenommen

Für Security-Reviews, externe Auditoren oder ein Monitoring-Team brauchen Sie clusterweiten Lesezugriff — ohne Secret-Inhalte. Die eingebaute view-ClusterRole ist hier ein guter Ausgangspunkt (sie schließt Secrets bereits aus), deckt aber keine clusterweiten Ressourcen wie Nodes ab:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-auditor
rules:
  - apiGroups: [""]
    resources: ["nodes", "namespaces", "persistentvolumes"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["rbac.authorization.k8s.io"]
    resources: ["roles", "clusterroles", "rolebindings", "clusterrolebindings"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["networking.k8s.io"]
    resources: ["networkpolicies", "ingresses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["policy"]
    resources: ["poddisruptionbudgets"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cluster-auditor-binding
subjects:
  - kind: Group
    name: security-team
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-auditor
  apiGroup: rbac.authorization.k8s.io

Kombinieren Sie das mit view per zusätzlichem Binding, hat der Auditor alles, was er braucht — und liest trotzdem keine Secret-Werte. Achtung bei ConfigMaps: Wer dort Credentials ablegt, hat den Secret-Ausschluss faktisch ausgehebelt. Das ist ein Konfigurationsfehler auf Workload-Seite, kein RBAC-Problem.


Anti-Pattern-Tabelle: Was Sie in Ihren Manifesten suchen sollten

Anti-PatternWarum gefährlichFix
verbs: ["*"] oder resources: ["*"]Faktisch cluster-admin unter harmlosem Namen; erfasst auch künftige API-RessourcenVerbs und Ressourcen explizit aufzählen
ClusterRoleBinding auf cluster-admin für ServiceAccountsPod-Kompromittierung = Cluster-KompromittierungNamespace-scoped Role mit exakten Verbs
Workloads auf dem default-ServiceAccountJede Berechtigung des default-SA gilt für alle Pods ohne eigenen SADedizierter SA pro Workload, automountServiceAccountToken: false
secrets mit get/list in breiten Rollenlist liefert alle Secret-Werte des Namespaces auf einmalget plus resourceNames auf benannte Secrets
escalate, bind, impersonate in Nicht-Admin-RollenErlaubt Rechteausweitung bis cluster-adminNur für Cluster-Administratoren, jede Nutzung im Audit-Log alarmieren
User-Subjects statt GroupsRBAC-Drift bei Personalwechsel, Offboarding-LückenGroups aus dem Identity Provider binden
RoleBindings auf system:authenticated oder system:unauthenticatedBerechtigt jeden Token-Inhaber bzw. anonyme RequestsBindings auf diese Gruppen grundsätzlich verbieten

Zum letzten Punkt: system:masters verdient eine eigene Warnung. Mitglieder dieser Gruppe umgehen RBAC vollständig — der Authorizer wird gar nicht erst gefragt. Ein Client-Zertifikat mit O=system:masters ist ein nicht widerrufbarer Generalschlüssel bis zum Ablauf des Zertifikats. Stellen Sie solche Zertifikate nie für den Alltagsbetrieb aus.


Verifikation: Erst prüfen, dann mergen

kubectl auth can-i

Der schnellste Test für einzelne Berechtigungen und ganze Berechtigungsprofile:

# Einzelne Berechtigung als ServiceAccount prüfen
kubectl auth can-i patch deployments -n produktion --as=system:serviceaccount:produktion:ci-deployer
# yes

kubectl auth can-i list secrets -n produktion --as=system:serviceaccount:produktion:ci-deployer
# no

# Komplettes Berechtigungsprofil auflisten
kubectl auth can-i --list -n produktion --as=system:serviceaccount:produktion:ci-deployer

Die --list-Ausgabe ist Ihr Abnahme-Artefakt: Steht dort mehr, als die Rolle laut Design erlauben soll, greift noch ein zweites Binding — häufig ein vergessenes ClusterRoleBinding.

rbac-lookup und kubectl-who-can

kubectl auth can-i beantwortet "Was darf Subjekt X?". Die umgekehrte Frage — "Wer darf Aktion Y?" — beantworten zwei Tools:

# rbac-lookup (Fairwinds): Welche Rollen hat ein Subjekt, über alle Bindings hinweg?
kubectl krew install rbac-lookup
kubectl rbac-lookup ci-deployer --kind serviceaccount --output wide

# Alle cluster-admin-Inhaber finden — die wichtigste Einzelabfrage im RBAC-Audit
kubectl rbac-lookup --output wide | grep cluster-admin

# kubectl-who-can (Aqua Security): Wer kann Secrets in produktion lesen?
kubectl krew install who-can
kubectl who-can list secrets -n produktion

Wenn kubectl who-can list secrets mehr als eine Handvoll erwarteter Subjects liefert, haben Sie Ihr erstes Audit-Finding.

Manifest-Linting in der CI

RBAC-Manifeste gehören ins Git-Repository und durch dieselbe Pipeline wie Anwendungscode. Drei Werkzeuge, die Wildcard-Rollen und überprivilegierte Bindings vor dem Merge stoppen:

# kubeaudit: statische RBAC- und Security-Checks auf Manifesten
kubeaudit all -f rbac/ci-deployer.yaml

# Trivy: erkennt u. a. Wildcard-Verbs und cluster-admin-Bindings in Manifesten
trivy config rbac/ --severity HIGH,CRITICAL

# Polaris: Policy-Checks inkl. RBAC als CI-Gate
polaris audit --audit-path rbac/ --set-exit-code-on-danger

Für einen schnellen Check ohne lokale Tool-Installation können Sie Manifeste auch direkt im Browser gegen RBAC- und Hardening-Regeln prüfen — dazu unten mehr. Läuft Ihr Rollout über ArgoCD oder Flux, gilt zusätzlich: Der GitOps-Controller selbst ist Ihr privilegiertestes Subjekt.


Fallstricke, die im Alltag Zeit kosten

Aggregated ClusterRoles. Die eingebauten Rollen admin, edit und view sind Aggregationen: Der Controller sammelt per Label-Selector (aggregationRule) Regeln aus anderen ClusterRoles ein. Viele Operatoren und CRD-Installationen liefern ClusterRoles mit Labels wie rbac.authorization.k8s.io/aggregate-to-edit: "true" mit — und erweitern damit stillschweigend, was jeder mit edit-Binding darf. Prüfen Sie das nach jeder Operator-Installation:

kubectl get clusterroles -l rbac.authorization.k8s.io/aggregate-to-admin=true
kubectl get clusterroles -l rbac.authorization.k8s.io/aggregate-to-edit=true

Managed Kubernetes: RBAC ist nur die halbe Wahrheit. Bei EKS, AKS und GKE sitzt vor dem Kubernetes-RBAC eine Cloud-IAM-Schicht. Bei EKS entscheiden Access Entries (früher die aws-auth-ConfigMap), welche IAM-Rolle auf welche Kubernetes-Groups gemappt wird — ein Mapping auf system:masters umgeht Ihr gesamtes RBAC. Bei AKS kann Azure RBAC for Kubernetes die clusterinterne Autorisierung teilweise ersetzen; dann greifen Ihre RoleBindings nicht so, wie Sie erwarten. Bei GKE werden IAM-Berechtigungen wie container.admin zusätzlich zu RBAC ausgewertet — ein Nutzer kann per IAM alles dürfen, obwohl im Cluster kein einziges Binding auf ihn zeigt. Konsequenz: Ein RBAC-Audit auf Managed Kubernetes muss immer beide Ebenen prüfen.

Forbidden-Fehler nach dem Härten. Wer Rollen von Wildcards auf explizite Listen umstellt, produziert anfangs Forbidden-Fehler, weil einzelne Sub-Ressourcen oder API-Gruppen fehlen. Das ist kein Rückschlag, sondern der Prozess.

Privilege Escalation über RBAC selbst. Wer create auf rolebindings plus bind auf Rollen hat, kann sich schrittweise Rechte verschaffen. Kubernetes verhindert zwar, dass jemand Rechte vergibt, die er nicht selbst hat — aber escalate schaltet genau diese Prüfung ab. Behandeln Sie Schreibzugriff auf RBAC-Ressourcen als das, was er ist: administrativer Zugriff.


FAQ

Wann Role, wann ClusterRole?

Role, wenn die Berechtigung nur einen Namespace betrifft. ClusterRole in zwei Fällen: für clusterweite Ressourcen (Nodes, PersistentVolumes, Namespaces, CRDs), und als wiederverwendbare Vorlage, die Sie per RoleBinding in mehreren Namespaces binden. Faustregel: Rollen-Definition darf clusterweit sein, das Binding sollte es fast nie sein.

Wie verhindere ich Rollen-Sprawl bei wachsendem Team?

Standardisieren Sie auf drei bis fünf Rollen-Archetypen (z. B. Developer, Deployer, Namespace-Admin, Auditor) als ClusterRoles und binden Sie sie pro Namespace an Identity-Provider-Groups. Neue Sonderrollen nur mit dokumentierter Begründung im Pull Request. Ein Quartals-Check mit rbac-lookup findet Rollen ohne aktive Bindings — die werden gelöscht, nicht archiviert.

Wie handhabe ich RBAC in einem GitOps-Setup mit ArgoCD?

Alle RBAC-Manifeste ins Git, Änderungen nur per Pull Request mit Pflicht-Review, Linting als CI-Gate. Der ArgoCD-Application-Controller braucht weitreichende Rechte, aber nicht zwingend cluster-admin: Beschränken Sie ihn auf die Namespaces und Ressourcentypen, die er tatsächlich verwaltet, und nutzen Sie ArgoCD-Projects, um zu begrenzen, welche Repos in welche Namespaces deployen dürfen. Direkte kubectl apply-Rechte auf RBAC-Ressourcen behält dann niemand mehr.

Sind die eingebauten Rollen view, edit und admin gut genug?

Als Startpunkt ja, dauerhaft meist nein. edit erlaubt das Lesen von Secrets und create auf Pods — damit lässt sich über einen Pod mit fremdem ServiceAccount eskalieren. Nutzen Sie view großzügig, edit nur in Entwicklungs-Namespaces und ersetzen Sie beide in Produktion durch explizite eigene Rollen wie oben gezeigt.

Wie oft sollte ich RBAC auditieren?

Kontinuierlich über CI-Linting für alles Neue, plus ein manueller Durchgang pro Quartal: rbac-lookup über alle Subjects, who-can für die kritischen Aktionen (list secrets, create pods, RBAC-Schreibzugriff, impersonate), Abgleich der Groups gegen den Identity Provider. Aufwand nach dem ersten Aufräumen: erfahrungsgemäß ein halber Tag pro Quartal — die erste Iteration in einem gewachsenen Cluster dauert deutlich länger und ist ein eigenes Projekt.


Fazit

RBAC-Härtung ist kein einmaliges Projekt, sondern eine Disziplin: explizite Rollen statt Wildcards, kleinste sinnvolle Bindings, dedizierte ServiceAccounts und Verifikation vor jedem Merge. Die drei Manifeste aus diesem Artikel decken die häufigsten Subjekt-Typen ab — Entwickler, Pipeline, Auditor — und lassen sich direkt an Ihre Namespaces anpassen. Der Rest ist Konsequenz: Jede neue Berechtigung geht durch Review und Linting, und einmal pro Quartal beantworten Sie die Frage "Wer kann was?" mit Werkzeugen statt mit Bauchgefühl.

Bevor Sie Ihre Rollen in den Cluster geben: Prüfen Sie Ihre RBAC- und Workload-Manifeste mit unserem kostenlosen Kubernetes YAML-Validator — er erkennt Wildcard-Verbs, überprivilegierte Bindings und weitere Hardening-Lücken direkt im Browser, inklusive DSGVO/BSI-orientierter Regeln.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen