Best practice per RBAC in GKE


Questa pagina fornisce best practice per pianificare i criteri di controllo dell'accesso basato sui ruoli (RBAC). Per informazioni su come implementare RBAC in Google Kubernetes Engine (GKE), consulta Configurare il controllo degli accessi basato sui ruoli.

RBAC è una funzionalità di sicurezza fondamentale di Kubernetes che consente di creare autorizzazioni granulari per gestire le azioni che utenti e carichi di lavoro possono eseguire sulle risorse nei cluster. In qualità di amministratore di piattaforma, puoi creare ruoli RBAC e associare questi ruoli agli soggetti, che sono utenti autenticati, come account di servizio o gruppi Google.

Prima di iniziare

Assicurati di acquisire familiarità con i seguenti concetti:

Per un elenco di controllo di queste indicazioni, consulta il Riepilogo dell'elenco di controllo.

Come funziona RBAC

RBAC supporta i seguenti tipi di ruoli e associazioni:

  • ClusterRole: un insieme di autorizzazioni che può essere applicato a qualsiasi spazio dei nomi o all'intero cluster.
  • Ruolo: un insieme di autorizzazioni limitate a un singolo spazio dei nomi.
  • ClusterRoleBinding: associa un ClusterRole a un utente o a un gruppo per tutti gli spazi dei nomi nel cluster.
  • RoleBinding: associa un Role o un ClusterRole a un utente o a un gruppo all'interno di uno spazio dei nomi specifico.

Puoi definire le autorizzazioni come rules in un Role o un ClusterRole. Ogni campo rules in un ruolo è costituito da un gruppo di API, dalle risorse API al suo interno e dai verbi (azioni) consentiti per queste risorse. Se vuoi, puoi definire l'ambito dei verbi a istanze denominate delle risorse API utilizzando il campo resourceNames. Per un esempio, consulta Limitare l'accesso a istanze di risorse specifiche.

Dopo aver definito un ruolo, puoi utilizzare RoleBinding o ClusterRoleBinding per associare il ruolo a un soggetto. Scegli il tipo di associazione in base a se vuoi concedere autorizzazioni in un singolo spazio dei nomi o in più spazi dei nomi.

Progettazione dei ruoli RBAC

Usa il principio del privilegio minimo

Quando assegni le autorizzazioni in un ruolo RBAC, utilizza il principio del privilegio minimo e concedi le autorizzazioni minime necessarie per eseguire un'attività. L'uso del principio del privilegio minimo riduce la possibilità di escalation dei privilegi se il cluster è compromesso e riduce la probabilità che un accesso eccessivo causi un incidente di sicurezza.

Durante la progettazione dei ruoli, considera attentamente i rischi comuni di escalation dei privilegi, ad esempio i verbi escalate o bind, l'accesso create per gli oggetti PersistentVolume o l'accesso create per le richieste di firma dei certificati. Per un elenco dei rischi, consulta Kubernetes RBAC - rischi di escalation dei privilegi.

Evita ruoli e gruppi predefiniti

Kubernetes crea un set di ClusterRole e ClusterRoleBinding predefiniti che puoi utilizzare per il rilevamento delle API e per abilitare le funzionalità del componente gestito. Le autorizzazioni concesse da questi ruoli predefiniti potrebbero essere estese a seconda del ruolo. Kubernetes ha anche un insieme di utenti e gruppi di utenti predefiniti, identificati dal prefisso system:. Per impostazione predefinita, Kubernetes e GKE associano automaticamente questi ruoli ai gruppi predefiniti e a vari soggetti. Per un elenco completo delle associazioni e dei ruoli predefiniti creati da Kubernetes, consulta Ruoli e associazioni di ruoli predefiniti.

La tabella seguente descrive alcuni ruoli, utenti e gruppi predefiniti. Ti consigliamo di evitare di interagire con questi ruoli, utenti e gruppi a meno di averli valutati attentamente, poiché l'interazione con queste risorse può avere conseguenze indesiderate sulla strategia di sicurezza del tuo cluster.

Nome Tipo Descrizione
cluster-admin ClusterRole Concede all'oggetto l'autorizzazione a eseguire qualsiasi operazione su qualsiasi risorsa del cluster.
system:anonymous Utente

Kubernetes assegna questo utente alle richieste del server API a cui non sono state fornite informazioni di autenticazione.

Se associ un ruolo a questo utente, concedi a qualsiasi utente non autenticato le autorizzazioni concesse da tale ruolo.

system:unauthenticated Gruppo

Kubernetes assegna questo gruppo alle richieste del server API che non hanno informazioni di autenticazione fornite.

Se associ un ruolo a questo gruppo, concedi a qualsiasi utente non autenticato le autorizzazioni concesse da quel ruolo.

system:authenticated Gruppo

GKE assegna questo gruppo alle richieste del server API effettuate da qualsiasi utente che ha eseguito l'accesso con un Account Google, inclusi tutti gli account Gmail. In pratica, ciò non è notevolmente diverso da system:unauthenticated perché chiunque può creare un Account Google.

L'associazione di un ruolo a questo gruppo concede a tutti gli utenti con un Account Google, inclusi tutti gli account Gmail, le autorizzazioni concesse da quel ruolo.

system:masters Gruppo

Per impostazione predefinita, Kubernetes assegna il ClusterRole cluster-admin a questo gruppo per abilitare le funzionalità del sistema.

L'aggiunta di soggetti a questo gruppo consente loro di eseguire qualsiasi operazione su qualsiasi risorsa nel cluster.

Se possibile, evita di creare associazioni che coinvolgano gli utenti, i ruoli e i gruppi predefiniti. Questo può avere conseguenze indesiderate sulla strategia di sicurezza del cluster. Ad esempio:

  • L'associazione del valore predefinito cluster-admin ClusterRole al gruppo system:unauthenticated consente a qualsiasi utente non autenticato di accedere a tutte le risorse nel cluster, inclusi i secret. Queste associazioni con privilegi elevati vengono attivamente prese di mira da attacchi come le campagne malware di massa.
  • L'associazione di un ruolo personalizzato al gruppo system:unauthenticated concede agli utenti non autenticati le autorizzazioni concesse da tale Ruolo.

Se possibile, segui queste linee guida:

  • Non aggiungere i tuoi soggetti al gruppo system:masters.
  • Non associare il gruppo system:unauthenticated a ruoli RBAC.
  • Non associare il gruppo system:authenticated a ruoli RBAC.
  • Non associare l'utente system:anonymous ad alcun ruolo RBAC.
  • Non associare cluster-admin ClusterRole ai tuoi oggetti o a nessuno degli utenti e dei gruppi predefiniti. Se l'applicazione richiede molte autorizzazioni, determina le autorizzazioni esatte richieste e crea un ruolo specifico a tale scopo.
  • Valuta le autorizzazioni concesse da altri ruoli predefiniti prima di associare i soggetti.
  • Valuta i ruoli associati ai gruppi predefiniti prima di modificare i membri di questi gruppi.

Rilevare e impedire l'utilizzo di ruoli e gruppi predefiniti

Devi valutare i tuoi cluster per identificare se hai associato l'utente system:anonymous oppure i gruppi system:unauthenticated o system:authenticated utilizzando sia ClusterRoleBindings che RoleBinding.

ClusterRoleBindings
  1. Elenca i nomi di qualsiasi ClusterRoleBinding con oggetto system:anonymous, system:unauthenticated o system:authenticated:

    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'
    

    Nell'output dovrebbero essere elencati solo i seguenti ClusterRoleBinding:

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

    Se l'output contiene altre associazioni non predefinite, segui questi passaggi per ogni associazione aggiuntiva. Se l'output non contiene associazioni non predefinite, ignora i passaggi seguenti.

  2. Elenca le autorizzazioni del ruolo associato all'associazione:

    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'
    

    Sostituisci CLUSTER_ROLE_BINDING_NAME con il nome del ClusterRoleBinding non predefinito.

    L'output è simile al seguente:

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

    Se stabilisci che le autorizzazioni nell'output possono essere concesse in sicurezza agli utenti o ai gruppi predefiniti, non sono necessarie ulteriori azioni. Se determini che le autorizzazioni concesse dall'associazione non sono sicure, vai al passaggio successivo.

  3. Elimina un'associazione non sicura dal cluster:

    kubectl delete clusterrolebinding CLUSTER_ROLE_BINDING_NAME
    

    Sostituisci CLUSTER_ROLE_BINDING_NAME con il nome del ClusterRoleBinding da eliminare.

RoleBindings
  1. Elenca lo spazio dei nomi e il nome di qualsiasi RoleBinding con oggetto system:anonymous, system:unauthenticated o system:authenticated:

    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'
    

    Se il cluster è configurato correttamente, l'output dovrebbe essere vuoto. Se l'output contiene associazioni non predefinite, segui questi passaggi per ogni associazione aggiuntiva. Se l'output è vuoto, salta i seguenti passaggi.

    Se conosci solo il nome di RoleBinding, puoi utilizzare il seguente comando per trovare le associazioni di ruolo corrispondenti in tutti gli spazi dei nomi:

    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'
    

    Sostituisci ROLE_BINDING_NAME con il nome della RoleBinding non predefinita.

  2. Elenca le autorizzazioni del ruolo associato all'associazione:

    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'
    

    Sostituisci quanto segue:

    • ROLE_BINDING_NAME: il nome del RoleBinding non predefinito.
    • ROLE_BINDING_NAMESPACE: lo spazio dei nomi della risorsa RoleBinding non predefinita.

    L'output è simile al seguente:

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

    Se stabilisci che le autorizzazioni nell'output possono essere concesse in sicurezza agli utenti o ai gruppi predefiniti, non sono necessarie ulteriori azioni. Se determini che le autorizzazioni concesse dall'associazione non sono sicure, vai al passaggio successivo.

  3. Elimina un'associazione non sicura dal cluster:

    kubectl delete rolebinding ROLE_BINDING_NAME --namespace ROLE_BINDING_NAMESPACE
    

    Sostituisci quanto segue:

    • ROLE_BINDING_NAME: il nome della risorsa RoleBinding da eliminare.
    • ROLE_BINDING_NAMESPACE: lo spazio dei nomi del RoleBinding da eliminare.

Definisci l'ambito delle autorizzazioni a livello dello spazio dei nomi

Utilizza associazioni e ruoli come segue, a seconda delle esigenze del carico di lavoro o dell'utente:

  • Per concedere l'accesso alle risorse in uno spazio dei nomi, utilizza Role con RoleBinding.
  • Per concedere l'accesso alle risorse in più di uno spazio dei nomi, utilizza ClusterRole con RoleBinding per ogni spazio dei nomi.
  • Per concedere l'accesso alle risorse in ogni spazio dei nomi, utilizza ClusterRole con ClusterRoleBinding.

Concedi le autorizzazioni con il minor numero possibile di spazi dei nomi.

Non utilizzare caratteri jolly

Il carattere * è un carattere jolly che si applica a tutto. Evita di utilizzare caratteri jolly nelle regole. Specificare in modo esplicito gruppi di API, risorse e verbi nelle regole RBAC. Ad esempio, se specifichi * nel campo verbs, concedi le autorizzazioni get, list, watch, patch, update, deletecollection e delete per le risorse. La seguente tabella mostra esempi di come evitare i caratteri jolly nelle regole:

Consigliato Sconsigliato

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

Concede i verbi get, list e watch in modo specifico ai gruppi di API apps e extensions.


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

Concede i verbi a deployments in qualsiasi gruppo API.


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

Concede solo i verbi get, list e watch ai deployment nei gruppi di API apps e extensions.


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

Concede tutti i verbi, tra cui patch o delete.

Utilizza regole separate per concedere l'accesso con privilegi minimi a risorse specifiche

Quando pianifichi le regole, prova i seguenti passaggi di alto livello per una progettazione più efficiente delle regole dei privilegi minimi in ogni ruolo:

  1. Crea una bozza di regole RBAC separate per ogni verbo su ogni risorsa a cui il soggetto deve accedere.
  2. Dopo aver creato la bozza delle regole, analizzale per verificare se più regole hanno lo stesso elenco verbs. Combina queste regole in un'unica regola.
  3. Mantieni separate tutte le regole rimanenti.

Questo approccio si traduce in una progettazione delle regole più organizzata, dove vengono combinate le regole che concedono gli stessi verbi a più risorse e le regole che concedono verbi diversi alle risorse sono separate.

Ad esempio, se il tuo carico di lavoro ha bisogno di ottenere le autorizzazioni per la risorsa deployments, ma di list e watch sulle risorse daemonsets, devi utilizzare regole separate quando crei un ruolo. Se associ il ruolo RBAC al tuo carico di lavoro, non potrà utilizzare watch su deployments.

Come ulteriore esempio, se il tuo carico di lavoro richiede get e watch sia per la risorsa pods sia per la risorsa daemonsets, puoi combinarli in un'unica regola, poiché il carico di lavoro richiede gli stessi verbi su entrambe le risorse.

Nella tabella seguente, entrambe le progettazioni di regole funzionano, ma le regole di suddivisione limitano in modo più granulare l'accesso alle risorse in base alle tue esigenze:

Consigliato Sconsigliato

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

Concede l'accesso get per i deployment e l'accesso watch e list per i DaemonSet. I soggetti non possono elencare i deployment.


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

Concede i verbi sia ai Deployment che ai DaemonSet. Un soggetto che potrebbe non richiedere l'accesso list su deployments oggetti otterrà comunque questo accesso.


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

Combina due regole perché il soggetto ha bisogno degli stessi verbi per entrambe le risorse daemonsets e deployments.


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

Queste regole di suddivisione avranno lo stesso risultato della regola combinata, ma creerebbero inutilmente disordine nel manifest del ruolo.

Limita l'accesso a istanze di risorse specifiche

RBAC consente di utilizzare il campo resourceNames nelle regole per limitare l'accesso a una specifica istanza denominata di una risorsa. Ad esempio, se stai scrivendo un ruolo RBAC che deve update il ConfigMap seccomp-high e nient'altro, puoi utilizzare resourceNames per specificare solo quel ConfigMap. Usa resourceNames quando possibile.

Consigliato Sconsigliato

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

Limita l'oggetto al solo aggiornamento di ConfigMap seccomp-high. L'oggetto non può aggiornare altri oggetti ConfigMap nello spazio dei nomi.


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

L'oggetto può aggiornare il ConfigMap seccomp-high e qualsiasi altro ConfigMap nello spazio dei nomi.


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

Concede l'accesso list a tutti i ConfigMap nello spazio dei nomi, incluso seccomp-high. Limita l'accesso update solo al ConfigMap di seccomp-high. Le regole sono suddivise perché non puoi concedere list per le risorse denominate.


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

Concede l'accesso update per tutti i ConfigMap, insieme all'accesso list.

Non consentire agli account di servizio di modificare le risorse RBAC

Non associare le risorse Role o ClusterRole che dispongono di autorizzazioni bind, escalate, create, update o patch nel gruppo API rbac.authorization.k8s.io agli account di servizio in qualsiasi spazio dei nomi. escalate e bind in particolare possono consentire a un utente malintenzionato di aggirare i meccanismi di prevenzione dell'escalation integrati in RBAC.

Account di servizio Kubernetes

Crea un account di servizio Kubernetes per ogni carico di lavoro

Crea un account di servizio Kubernetes separato per ogni carico di lavoro. Associa un privilegio minimo Role o ClusterRole a quell'account di servizio.

Non utilizzare l'account di servizio predefinito

Kubernetes crea un account di servizio denominato default in ogni spazio dei nomi. L'account di servizio default viene assegnato automaticamente ai pod che non specificano in modo esplicito un account di servizio nel manifest. Evita di associare Role o ClusterRole all'account di servizio default. Kubernetes potrebbe assegnare l'account di servizio default a un pod per cui non è necessario concedere l'accesso in questi ruoli.

Non montare automaticamente i token degli account di servizio

Il campo automountServiceAccountToken nella specifica del pod indica a Kubernetes di inserire nel pod un token delle credenziali per un account di servizio Kubernetes. Il pod può utilizzare questo token per effettuare richieste autenticate al server API Kubernetes. Il valore predefinito di questo campo è true.

In tutte le versioni di GKE, imposta automountServiceAccountToken=false nella specifica del pod se i tuoi pod non devono comunicare con il server API.

Preferisci i token temporanei ai token basati su secret

Per impostazione predefinita, il processo kubelet sul nodo recupera un token dell'account di servizio a rotazione automatica di breve durata per ogni pod. Il kubelet monta questo token sul pod come un volume previsto, a meno che non imposti il campo automountServiceAccountToken su false nella specifica del pod. Qualsiasi chiamata all'API Kubernetes dal pod utilizza questo token per eseguire l'autenticazione al server API.

Se recuperi manualmente i token degli account di servizio, evita di utilizzare i secret di Kubernetes per archiviare il token. I token degli account di servizio basati sui secret sono credenziali legacy che non hanno scadenza e non vengono ruotate automaticamente. Se hai bisogno delle credenziali per gli account di servizio, utilizza l'API TokenRequest per ottenere token di breve durata che vengono ruotati automaticamente.

Rivedi continuamente le autorizzazioni RBAC

Rivedi i ruoli RBAC e accedi regolarmente per identificare potenziali percorsi di escalation e regole ridondanti. Ad esempio, considera una situazione in cui non elimini un RoleBinding che associa un Role con privilegi speciali a un utente eliminato. Se un utente malintenzionato crea un account utente in quello spazio dei nomi con lo stesso nome dell'utente eliminato, viene associato a quel Role ed eredita lo stesso accesso. Revisioni periodiche riducono al minimo questo rischio.

Riepilogo elenco di controllo

Passaggi successivi