Best Practices für GKE RBAC


In diesem Dokument werden Best Practices für die Planung Ihrer rollenbasierten Zugriffssteuerungsrichtlinien (Role-Based Access Control, RBAC) beschrieben. Informationen zum Implementieren von RBAC in Google Kubernetes Engine (GKE) finden Sie unter Rollenbasierte Zugriffssteuerung konfigurieren.

RBAC ist ein zentrales Sicherheitsfeature in Kubernetes, mit dem Sie detaillierte Berechtigungen erstellen können, um zu verwalten, welche Aktionen Nutzer und Arbeitslasten für Ressourcen in Ihren Clustern ausführen können. Als Plattformadministrator erstellen Sie RBAC-Rollen und binden diese Rollen an Subjekte, die authentifizierte Nutzer wie Dienstkonten oder Google Groups-Gruppen sind.

Hinweise

Machen Sie sich vor dem Lesen dieses Dokuments mit den folgenden Konzepten vertraut:

Eine Checkliste dieser Anleitung finden Sie unter Zusammenfassung der Checkliste.

Funktionsweise von RBAC

RBAC unterstützt die folgenden Typen von Rollen und Bindungen:

  • ClusterRole: Eine Reihe von Berechtigungen, die auf einen beliebigen Namespace oder auf den gesamten Cluster angewendet werden können.
  • Role: Eine Reihe von Berechtigungen, die auf einen einzelnen Namespace beschränkt sind.
  • ClusterRoleBinding: Binden Sie eine ClusterRole an einen Nutzer oder eine Gruppe für alle Namespaces im Cluster.
  • RoleBinding: Binden Sie eine Role oder eine ClusterRole an einen Nutzer oder eine Gruppe in einem bestimmten Namespace.

Sie definieren Berechtigungen als rules in einer Role oder einer ClusterRole. Jedes rules-Feld in einer Rolle besteht aus einer API-Gruppe, den API-Ressourcen innerhalb dieser API-Gruppe und den für diese Ressourcen zulässigen Verben (Aktionen). Optional können Sie Verben mithilfe des Felds resourceNames auf benannte Instanzen von API-Ressourcen beschränken. Ein Beispiel finden Sie unter Zugriff auf bestimmte Ressourceninstanzen beschränken.

Nachdem Sie eine Rolle definiert haben, verwenden Sie ein RoleBinding oder ein ClusterRoleBinding, um die Rolle an ein Subjekt zu binden. Wählen Sie den Bindungstyp aus, je nachdem, ob Sie Berechtigungen in einem einzelnen Namespace oder in mehreren Namespaces gewähren möchten.

RBAC-Rollendesign

Prinzip der geringsten Berechtigung anwenden

Verwenden Sie beim Zuweisen von Berechtigungen in einer RBAC-Rolle das Prinzip der geringsten Berechtigung und gewähren Sie die Mindestberechtigungen, die zum Ausführen einer Aufgabe erforderlich sind. Das Prinzip der geringsten Berechtigung reduziert das Risiko einer Rechteausweitung, wenn Ihr Cluster manipuliert wurde, und verringert die Wahrscheinlichkeit, dass übermäßiger Zugriff zu einem Sicherheitsvorfall führt.

Berücksichtigen Sie beim Entwerfen Ihrer Rollen sorgfältig die gängigen Risiken der Rechteausweitung, z. B. bei escalate- oder bind-Verben, create-Zugriff für PersistentVolumes oder create-Zugriff für Anfragen für Zertifikatsignaturen. Eine Liste der Risiken finden Sie unter Kubernetes RBAC – Risiken der Rechteausweitung.

Standardrollen und -gruppen vermeiden

Kubernetes erstellt eine Reihe von Standard-ClusterRoles und -ClusterRoleBindings, die Sie für die API-Erkennung verwenden können und zum Aktivieren der Funktionalität für verwaltete Komponenten. Die durch diese Standardrollen gewährten Berechtigungen können umfassend sein, abhängig von der Rolle. Kubernetes verfügt auch über eine Reihe von Standardnutzern und -nutzergruppen, die durch das Präfix system: identifiziert werden. Standardmäßig binden Kubernetes und GKE diese Rollen automatisch an die Standardgruppen und an verschiedene Subjekte. Eine vollständige Liste der von Kubernetes erstellten Standardrollen und -bindungen finden Sie unter Standardrollen und -rollenbindungen.

In der folgenden Tabelle werden einige Standardrollen, Nutzer und Gruppen beschrieben. Wir empfehlen, nur mit diesen Rollen, Nutzern und Gruppen zu interagieren, wenn Sie sie sorgfältig geprüft haben, da die Interaktion mit diesen Ressourcen unbeabsichtigte Auswirkungen auf den Sicherheitsstatus Ihres Clusters haben kann.

Name Typ Beschreibung
cluster-admin ClusterRole Gewährt einem Subjekt die Berechtigung, beliebige Aktionen mit einer Ressource im Cluster auszuführen.
system:anonymous Nutzer

Kubernetes weist diesen Nutzer API-Serveranfragen zu, für die keine Authentifizierungsinformationen angegeben wurden.

Wenn Sie eine Rolle an diesen Nutzer binden, erhält jeder nicht authentifizierte Nutzer die durch diese Rolle gewährten Berechtigungen.

system:unauthenticated Gruppe

Kubernetes weist diese Gruppe API-Serveranfragen zu, für die keine Authentifizierungsinformationen angegeben wurden.

Wenn Sie eine Rolle an diese Gruppe binden, erhält jeder nicht authentifizierte Nutzer die durch diese Rolle gewährten Berechtigungen.

system:authenticated Gruppe

GKE weist diese Gruppe API-Serveranfragen zu, die von Nutzern gestellt werden, die mit einem Google-Konto angemeldet sind, einschließlich aller Gmail-Konten. In der Praxis unterscheidet sich das nicht wesentlich von system:unauthenticated, da jeder ein Google-Konto erstellen kann.

Wenn Sie eine Rolle an diese Gruppe binden, erhalten alle Nutzer mit einem Google-Konto, einschließlich aller Gmail-Konten, die mit dieser Rolle verbundenen Berechtigungen.

system:masters Gruppe

Kubernetes weist dieser Gruppe standardmäßig die ClusterRole cluster-admin zu, um Systemfunktionen zu aktivieren.

Wenn Sie dieser Gruppe eigene Subjekte hinzufügen, erhalten diese Subjekte Zugriff auf alle Ressourcen in Ihrem Cluster und können mit diesen alles tun.

Erstellen Sie nach Möglichkeit keine Bindungen, die die Standardnutzer, -rollen und -gruppen involvieren. Das kann unerwünschte Auswirkungen auf die Sicherheit Ihres Clusters haben. Beispiel:

  • Wenn Sie die Standard-ClusterRole cluster-admin an die Gruppe system:unauthenticated binden, erhalten alle nicht authentifizierten Nutzer Zugriff auf alle Ressourcen im Cluster, einschließlich Secrets. Auf diese sehr umfangreichen Bindungen werden aktiv Angriffe wie Massen-Malware-Kampagnen ausgerichtet.
  • Wenn Sie eine benutzerdefinierte Rolle an die Gruppe system:unauthenticated binden, erhalten nicht authentifizierte Nutzer die mit dieser Rolle gewährten Berechtigungen.

Beachten Sie dabei nach Möglichkeit die folgenden Richtlinien:

  • Fügen Sie der Gruppe system:masters keine eigenen Subjekte hinzu.
  • Binden Sie die Gruppe system:unauthenticated nicht an RBAC-Rollen.
  • Binden Sie die Gruppe system:authenticated nicht an RBAC-Rollen.
  • Binden Sie den Nutzer system:anonymous nicht an RBAC-Rollen.
  • Binden Sie die ClusterRole cluster-admin nicht an Ihre eigenen Subjekte oder an einen der Standardnutzer und -gruppen. Wenn Ihre Anwendung viele Berechtigungen erfordert, ermitteln Sie die erforderlichen Berechtigungen und erstellen Sie eine spezifische Rolle für diesen Zweck.
  • Bewerten Sie die Berechtigungen anderer Standardrollen, bevor Sie Subjekte binden.
  • Prüfen Sie die Rollen, die an Standardgruppen gebunden sind, bevor Sie die Mitglieder dieser Gruppen ändern.

Nutzung von Standardrollen und -gruppen erkennen und verhindern

Sie sollten Ihre Cluster evaluieren, um festzustellen, ob Sie den Nutzer system:anonymous oder die Gruppen system:unauthenticated oder system:authenticated mithilfe von ClusterRoleBindings und RoleBindings gebunden haben.

ClusterRoleBindings
  1. Liste der Namen aller ClusterRoleBindings mit dem Subjekt system:anonymous, system:unauthenticated oder system:authenticated auflisten:

    kubectl get clusterrolebindings -o json \
      | jq -r '["Name"], ["-----"], (.items[] | select((.subjects | length) > 0) | select(any(.subjects[]; .name == "system:anonymous" or .name == "system:unauthenticated" or .name == "system:authenticated")) | [.metadata.namespace, .metadata.name]) | @tsv'
    

    Die Ausgabe sollte nur die folgenden ClusterRoleBindings auflisten:

    Name
    ----
    "system:basic-user"
    "system:discovery"
    "system:public-info-viewer"
    

    Wenn die Ausgabe zusätzliche nicht standardmäßige Bindungen enthält, gehen Sie für jede zusätzliche Bindung so vor: Wenn Ihre Ausgabe keine nicht standardmäßigen Bindungen enthält, überspringen Sie die folgenden Schritte.

  2. Listen Sie die Berechtigungen der Rolle auf, die mit der Bindung verknüpft ist:

    kubectl get clusterrolebinding CLUSTER_ROLE_BINDING_NAME -o json \
        | jq ' .roleRef.name +" " + .roleRef.kind' \
        | sed -e 's/"//g' \
        | xargs -l bash -c 'kubectl get $1 $0 -o yaml'
    

    Ersetzen Sie CLUSTER_ROLE_BINDING_NAME durch den Namen des nicht standardmäßigen ClusterRoleBinding.

    Die Ausgabe sieht in etwa so aus:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
    ...
    rules:
    - apiGroups:
      - ""
      resources:
      - secrets
      verbs:
      - get
      - watch
      - list
    

    Wenn Sie feststellen, dass die Berechtigungen in der Ausgabe den Standardnutzern oder -gruppen sicher erteilt werden können, sind keine weiteren Maßnahmen erforderlich. Wenn Sie feststellen, dass die durch die Bindung gewährten Berechtigungen nicht sicher sind, fahren Sie mit dem nächsten Schritt fort.

  3. Löschen Sie eine unsichere Bindung aus Ihrem Cluster:

    kubectl delete clusterrolebinding CLUSTER_ROLE_BINDING_NAME
    

    Ersetzen Sie CLUSTER_ROLE_BINDING_NAME durch den Namen der zu löschenden ClusterRoleBinding.

RoleBindings
  1. Geben Sie den Namespace und den Namen aller RoleBindings mit einem der Subjekte system:anonymous, system:unauthenticated oder system:authenticated an:

    kubectl get rolebindings -A -o json \
      | jq -r '["Namespace", "Name"], ["---------", "-----"], (.items[] | select((.subjects | length) > 0) | select(any(.subjects[]; .name == "system:anonymous" or .name == "system:unauthenticated" or .name == "system:authenticated")) | [.metadata.namespace, .metadata.name]) | @tsv'
    

    Wenn Ihr Cluster richtig konfiguriert ist, sollte die Ausgabe leer sein. Wenn die Ausgabe nicht standardmäßige Bindungen enthält, führen Sie für jede zusätzliche Bindung die folgenden Schritte aus. Wenn Ihre Ausgabe leer ist, überspringen Sie die folgenden Schritte.

    Wenn Sie nur den Namen des RoleBinding kennen, können Sie mit dem folgenden Befehl übereinstimmende RoleBindings in den anderen Namespaces finden:

    kubectl get rolebindings -A -o json \
      | jq -r '["Namespace", "Name"], ["---------", "-----"], (.items[] | select((.subjects | length) > 0) | select(.metadata.name == "ROLE_BINDING_NAME") | [.metadata.namespace, .metadata.name]) | @tsv'
    

    Ersetzen Sie ROLE_BINDING_NAME durch den Namen des nicht standardmäßigen RoleBinding.

  2. Listen Sie die Berechtigungen der Rolle auf, die mit der Bindung verknüpft ist:

    kubectl get rolebinding ROLE_BINDING_NAME --namespace ROLE_BINDING_NAMESPACE -o json \
        | jq ' .roleRef.name +" " + .roleRef.kind' \
        | sed -e 's/"//g' \
        | xargs -l bash -c 'kubectl get $1 $0 -o yaml --namespace ROLE_BINDING_NAMESPACE'
    

    Ersetzen Sie Folgendes:

    • ROLE_BINDING_NAME: Name der nicht standardmäßigen RoleBinding.
    • ROLE_BINDING_NAMESPACE: Namespace des nicht standardmäßigen RoleBinding.

    Die Ausgabe sieht in etwa so aus:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
    ...
    rules:
    - apiGroups:
      - ""
      resources:
      - secrets
      verbs:
      - get
      - watch
      - list
    

    Wenn Sie feststellen, dass die Berechtigungen in der Ausgabe den Standardnutzern oder -gruppen sicher erteilt werden können, sind keine weiteren Maßnahmen erforderlich. Wenn Sie feststellen, dass die durch die Bindung gewährten Berechtigungen nicht sicher sind, fahren Sie mit dem nächsten Schritt fort.

  3. Löschen Sie eine unsichere Bindung aus Ihrem Cluster:

    kubectl delete rolebinding ROLE_BINDING_NAME --namespace ROLE_BINDING_NAMESPACE
    

    Ersetzen Sie Folgendes:

    • ROLE_BINDING_NAME: Name des zu löschenden RoleBinding.
    • ROLE_BINDING_NAMESPACE: Namespace des zu löschenden RoleBinding.

Berechtigungen auf die Namespace-Ebene beschränken

Verwenden Sie Bindungen und Rollen je nach den Anforderungen Ihrer Arbeitslast oder Ihres Nutzers:

  • Um Zugriff auf Ressourcen in einem Namespace zu gewähren, verwenden Sie eine Role mit einem RoleBinding.
  • Um Zugriff auf Ressourcen in mehr als einem Namespace zu gewähren, verwenden Sie eine ClusterRole mit einem RoleBinding für jeden Namespace.
  • Wenn Sie Zugriff auf Ressourcen in jedem Namespace gewähren möchten, verwenden Sie eine ClusterRole mit einem ClusterRoleBinding.

Gewähren Sie Berechtigungen in so wenigen Namespaces wie möglich.

Keine Platzhalter verwenden

Das Zeichen * ist ein Platzhalter, der für alles gilt. Vermeiden Sie Platzhalter in den Regeln. Geben Sie in API-Regeln explizit API-Gruppen, Ressourcen und Verben an. Wenn Sie beispielsweise * im Feld verbs angeben, werden die Berechtigungen get, list, watch, patch, update, deletecollection und delete für die Ressourcen gewährt. Die folgende Tabelle zeigt Beispiele für die Vermeidung von Platzhaltern in Ihren Regeln:

Empfohlen Nicht empfohlen
- rules:
    apiGroups: ["apps","extensions"]
    resources: ["deployments"]
    verbs: ["get","list","watch"]

Gewährt die Verben get, list und watch speziell für die API-Gruppen apps und extensions.

- rules:
    apiGroups: ["*"]
    resources: ["deployments"]
    verbs: ["get","list","watch"]

Gewährt deployments die Verben in beliebigen API-Gruppen.

- rules:
    apiGroups: ["apps", "extensions"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch"]

Gewährt nur die Verben get, list und watch für Bereitstellungen in den API-Gruppen apps und extensions.

- rules:
    apiGroups: ["apps", "extensions"]
    resources: ["deployments"]
    verbs: ["*"]

Gewährt alle Verben, einschließlich patch oder delete.

Separate Regeln verwenden, um Zugriff mit den geringstmöglichen Berechtigungen auf bestimmte Ressourcen zu gewähren

Führen Sie bei der Planung Ihrer Regeln die folgenden allgemeinen Schritte aus, um in jeder Rolle ein effizienteres Regeldesign mit den geringstmöglichen Berechtigungen zu erhalten:

  1. Entwerfen Sie separate RBAC-Regeln für jedes Verb für jede Ressource, auf die ein Subjekt zugreifen muss.
  2. Nachdem Sie die Regeln erstellt haben, analysieren Sie die Regeln, um zu prüfen, ob mehrere Regeln dieselbe verbs-Liste haben. Kombinieren Sie diese Regeln zu einer einzigen Regel.
  3. Halten Sie alle übrigen Regeln voneinander getrennt.

Dieser Ansatz führt zu einem organisierteren Regeldesign, bei dem Regeln, die mehreren Ressourcen dieselben Verben zuweisen, kombiniert werden und Regeln, die Ressourcen verschiedene Verben zuweisen, getrennt werden.

Wenn Ihre Arbeitslast beispielsweise Berechtigungen für die Ressource deployments benötigt, aber list und watch für die daemonsets-Ressourcen benötigt, sollten Sie beim Erstellen einer Rolle separate Regeln verwenden. Wenn Sie die RBAC-Rolle an Ihre Arbeitslast binden, kann watch nicht für deployments verwendet werden.

Ein weiteres Beispiel: Wenn Ihre Arbeitslast get und watch für die Ressource pods und die Ressource daemonsets benötigt, können Sie diese in einer einzigen Regel kombinieren, da die Arbeitslast für beide Ressourcen die gleichen Verben benötigt.

In der folgenden Tabelle funktionieren beide Regeldesigns, aber die aufgeteilten Regeln beschränken den Ressourcenzugriff genauer entsprechend Ihren Anforderungen:

Empfohlen Nicht empfohlen
- rules:
    apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get"]
- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets"]
    verbs: ["list", "watch"]

Gewährt get-Zugriff für Deployments sowie watch- und list-Zugriff für DaemonSets. Subjekte können keine Deployments auflisten.

- rules:
    apiGroups: ["apps"]
    resources: ["deployments", "daemonsets"]
    verbs: ["get","list","watch"]

Gewährt die Verben sowohl für Deployments als auch für DaemonSets. Ein Subjekt, das möglicherweise keinen list-Zugriff auf deployments-Objekte benötigt, erhält diesen Zugriff trotzdem.

- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets", "deployments"]
    verbs: ["list", "watch"]

Kombiniert zwei Regeln, da das Subjekt dieselben Verben für die Ressourcen daemonsets und deployments benötigt.

- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets"]
    verbs: ["list", "watch"]
- rules:
    apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["list", "watch"]

Diese aufgeteilten Regeln haben dasselbe Ergebnis wie die kombinierte Regel, machen Ihr Rollenmanifest aber unnötig umständlich.

Zugriff auf bestimmte Ressourceninstanzen beschränken

Mit RBAC können Sie das Feld resourceNames in Ihren Regeln verwenden, um den Zugriff auf eine bestimmte benannte Instanz einer Ressource zu beschränken. Wenn Sie beispielsweise eine RBAC-Rolle schreiben, die ein update für die ConfigMap seccomp-high durchführen muss und nichts anderes benötigt, können Sie resourceNames verwenden, um nur diese ConfigMap anzugeben. Verwenden Sie nach Möglichkeit immer resourceNames.

Empfohlen Nicht empfohlen
- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["seccomp-high"]
    verbs: ["update"]

Schränkt das Subjekt ein, sodass nur die ConfigMap seccomp-high aktualisiert wird. Der Subjekt kann keine anderen ConfigMaps im Namespace aktualisieren.

- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["update"]

Das Subjekt kann die ConfigMap seccomp-high und jede andere ConfigMap im Namespace aktualisieren.

- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["list"]
- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["seccomp-high"]
    verbs: ["update"]

Gewährt list-Zugriff auf alle ConfigMaps im Namespace, einschließlich seccomp-high. Beschränkt den update-Zugriff auf die ConfigMap seccomp-high. Die Regeln werden aufgeteilt, da Sie nicht list für benannte Ressourcen zuweisen können.

- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["update", "list"]

Gewährt update-Zugriff für alle ConfigMaps, zusammen mit list-Zugriff.

Nicht zulassen, dass Dienstkonten RBAC-Ressourcen ändern

Binden Sie keine Role- oder ClusterRole-Ressourcen mit den Berechtigungen bind, escalate, create, update oder patch für die API-Gruppe rbac.authorization.k8s.io an Dienstkonten in einem beliebigen Namespace. Insbesondere escalate und bind können es einem Angreifer ermöglichen, die in RBAC integrierten Methoden zur Eskalationsverhinderung zu umgehen.

Kubernetes-Dienstkonten

Kubernetes-Dienstkonto für jede Arbeitslast erstellen

Erstellen Sie ein separates Kubernetes-Dienstkonto für jede Arbeitslast. Binden Sie eine Role oder ClusterRole mit geringstmöglichen Berechtigungen an dieses Dienstkonto.

Nicht das Standarddienstkonto verwenden

Kubernetes erstellt in jedem Namespace ein Dienstkonto mit dem Namen default. Das Dienstkonto default wird automatisch Pods zugewiesen, die im Manifest nicht explizit ein Dienstkonto angeben. Vermeiden Sie die Bindung einer Role oder ClusterRole an das Dienstkonto default. Kubernetes weist das Dienstkonto default möglicherweise einem Pod zu, der den Zugriff in diesen Rollen nicht benötigt.

Dienstkonto-Tokens nicht automatisch bereitstellen

Das Feld automountServiceAccountToken in der Pod-Spezifikation weist Kubernetes an, ein Anmeldedatentoken für ein Kubernetes-Dienstkonto in den Pod einzufügen. Der Pod kann mit diesem Token authentifizierte Anfragen an den Kubernetes API-Server senden. Der Standardwert für dieses Feld ist true.

Legen Sie in allen GKE-Versionen automountServiceAccountToken=false in der Pod-Spezifikation fest, wenn Ihre Pods nicht mit dem API-Server kommunizieren müssen.

Sitzungsspezifische Tokens gegenüber secret-basierten Tokens bevorzugen

Standardmäßig ruft der Kubelet-Prozess auf dem Knoten pro Pod ein kurzlebiges, automatisch rotierendes Dienstkontotoken ab. Kubelet stellt dieses Token als projiziertes Volume auf dem Pod bereit, es sei denn, Sie legen das Feld automountServiceAccountToken in der Pod-Spezifikation auf false fest. Alle Aufrufe der Kubernetes API vom Pod aus verwenden dieses Token, um sich beim API-Server zu authentifizieren.

Wenn Sie Dienstkonto-Tokens manuell abrufen, sollten Sie keine Kubernetes-Secrets zum Speichern des Tokens verwenden. Secret-basierte Dienstkonto-Tokens sind Legacy-Anmeldedaten, die nicht ablaufen und nicht automatisch rotiert werden. Wenn Sie Anmeldedaten für Dienstkonten benötigen, verwenden Sie die TokenRequest API, um kurzlebige Tokens abzurufen, die automatisch rotiert werden.

RBAC-Berechtigungen kontinuierlich prüfen

Prüfen Sie Ihre RBAC-Rollen und den Zugriff regelmäßig, um potenzielle Eskalationspfade und redundante Regeln zu identifizieren. Beispiel: Sie löschen nicht das RoleBinding, das eine Role mit speziellen Berechtigungen an einen gelöschten Nutzer bindet. Wenn ein Angreifer nun in diesem Namespace ein Nutzerkonto mit dem Namen des gelöschten Nutzers erstellt, ist er an diese Role gebunden und übernimmt ihren Zugriff. Regelmäßige Überprüfungen minimieren dieses Risiko.

Zusammenfassung der Checkliste

Nächste Schritte