Applicare criteri di sicurezza personalizzati a livello di pod utilizzando Gatekeeper

Questa pagina mostra come utilizzare il controller di ammissione Gatekeeper per applicare controlli di sicurezza a livello di pod ai cluster Google Kubernetes Engine (GKE). In questa pagina imparerai a utilizzare Gatekeeper per applicare vincoli che ti consentono di applicare policy di sicurezza per soddisfare i requisiti di sicurezza della tua organizzazione.

Questa pagina è rivolta agli esperti di sicurezza che vogliono applicare controlli di sicurezza ai propri cluster GKE. Per scoprire di più sui ruoli comuni e sulle attività di esempio a cui facciamo riferimento nei contenuti di Google Cloud , consulta Ruoli e attività comuni degli utenti GKE.

Prima di leggere questa pagina, assicurati di avere familiarità con i seguenti concetti:

Panoramica di Gatekeeper

Gatekeeper è un controller di ammissione che convalida le richieste di creazione e aggiornamento dei pod sui cluster Kubernetes utilizzando Open Policy Agent (OPA).

L'utilizzo di Gatekeeper consente agli amministratori di definire policy con un vincolo, ovvero un insieme di condizioni che consentono o negano i comportamenti di deployment in Kubernetes. Puoi quindi applicare queste policy a un cluster utilizzando un ConstraintTemplate. Questo documento fornisce esempi per limitare le funzionalità di sicurezza dei workload per garantire l'applicazione, il test e l'audit delle policy di sicurezza utilizzando Gatekeeper.

Il gatekeeper può anche:

  • Implementa le policy: applica le policy in modo graduale e mirato per limitare il rischio di interruzioni dei workload.
  • Modifiche alle policy in modalità dry run: forniscono meccanismi per testare l'impatto e l'intervallo delle policy prima dell'applicazione.
  • Controlla le policy esistenti: assicurati che i controlli di sicurezza vengano applicati ai workload nuovi ed esistenti (controlli di audit).

Concetti chiave di Gatekeeper

Gatekeeper introduce due concetti per fornire agli amministratori un mezzo potente e flessibile per controllare il proprio cluster: i vincoli e i modelli di vincolo, entrambi concetti ereditati dal framework dei vincoli di Open Policy Agent.

I vincoli sono la rappresentazione della tua policy di sicurezza e definiscono i requisiti e l'ambito di applicazione. I template di vincoli sono istruzioni riutilizzabili (scritte in Rego) che applicano la logica per valutare campi specifici negli oggetti Kubernetes, in base ai requisiti definiti nei vincoli.

Ad esempio, potresti avere un vincolo che dichiara i profili seccomp consentiti che possono essere applicati ai pod in uno spazio dei nomi specifico e un modello di vincolo paragonabile che fornisce la logica per estrarre questi valori e gestire l'applicazione.

Il seguente template di vincolo, proveniente dal repository Gatekeeper, verifica l'esistenza di securityContext.privileged in una specifica del pod:

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8spspprivilegedcontainer
spec:
  crd:
    spec:
      names:
        kind: K8sPSPPrivilegedContainer
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8spspprivileged

        violation[{"msg": msg, "details": {}}] {
            c := input_containers[_]
            c.securityContext.privileged
            msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext])
        }
        input_containers[c] {
            c := input.review.object.spec.containers[_]
        }
        input_containers[c] {
            c := input.review.object.spec.initContainers[_]
        }

Per estendere l'esempio di template di vincolo precedente, il seguente vincolo definisce l'ambito (kinds) per l'applicazione specifica di questo template di vincolo in modalità dryrun:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPPrivilegedContainer
metadata:
  name: psp-privileged-container
spec:
  enforcementAction: dryrun
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]

Con Gatekeeper, puoi creare i tuoi vincoli e modelli di vincoli per soddisfare le tue esigenze specifiche. Puoi anche utilizzare un set standard di vincoli e modelli di vincoli nel repository Gatekeeper che sono stati definiti per consentire un'adozione rapida e l'applicazione della sicurezza. Ogni vincolo è inoltre accompagnato da configurazioni di pod di esempio.

Google Cloud fornisce una versione gestita e supportata ufficialmente di Gatekeeper open source denominata Policy Controller. Google non supporta ufficialmente il progetto open source Gatekeeper.

Prima di iniziare

Prima di iniziare, assicurati di aver eseguito le seguenti attività:

  • Abilita l'API Google Kubernetes Engine.
  • Abilita l'API Google Kubernetes Engine
  • Per utilizzare Google Cloud CLI per questa attività, installala e poi inizializza gcloud CLI. Se hai già installato gcloud CLI, scarica l'ultima versione eseguendo il comando gcloud components update. Le versioni precedenti di gcloud CLI potrebbero non supportare l'esecuzione dei comandi in questo documento.

Abilita Gatekeeper su un cluster con Policy Controller

Policy Controller è un motore di policy basato sul progetto open source Gatekeeper. Google consiglia l'utilizzo di Policy Controller perché include funzionalità aggiuntive per applicare le policy su larga scala, tra cui policy as code, supporto multi-cluster, integrazione con Cloud Logging e possibilità di visualizzare lo stato secondo le norme nella console Google Cloud . Policy Controller è disponibile con GKE, ma puoi installare Gatekeeper sul tuo cluster.

Per abilitare Policy Controller su un cluster, segui la guida all'installazione di Policy Controller.

Abilita vincoli e modelli di vincolo

Gatekeeper e i relativi modelli di vincolo possono essere installati e abilitati senza influire negativamente sui workload esistenti o nuovi. Per questo motivo, ti consigliamo di applicare al cluster tutti i modelli di vincoli di sicurezza dei pod applicabili.

Inoltre, è possibile implementare i vincoli di Gatekeeper per applicare controlli per oggetti specifici, come spazi dei nomi e pod.

Osserva l'esempio seguente che limita l'ambito ai pod che si trovano nello spazio dei nomi production definendoli nell'istruzione di corrispondenza del vincolo:

...
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces:
      - "production"

Per saperne di più sulle opzioni disponibili per gli oggetti Constraint e ConstraintTemplate, consulta Come utilizzare Gatekeeper.

Testa le policy

L'introduzione di nuove policy nei cluster esistenti può avere un comportamento negativo, ad esempio limitando i workload esistenti. Uno dei vantaggi dell'utilizzo di Gatekeeper per la sicurezza dei pod è la possibilità di testare l'efficacia e l'impatto che avrà una policy senza apportare modifiche effettive, utilizzando una modalità dry run. In questo modo, è possibile testare la configurazione delle policy sui cluster in esecuzione senza applicarle. Le violazioni delle policy vengono registrate e identificate senza interferenze.

I passaggi seguenti mostrano come uno sviluppatore, un operatore o un amministratore può applicare modelli di vincoli e vincoli per determinarne l'efficacia o il potenziale impatto:

  1. Applica la configurazione di Gatekeeper per la replica dei dati per la funzionalità di controllo e dry run:

    kubectl create -f- <<EOF
    apiVersion: config.gatekeeper.sh/v1alpha1
    kind: Config
    metadata:
      name: config
      namespace: "gatekeeper-system"
    spec:
      sync:
        syncOnly:
          - group: ""
            version: "v1"
            kind: "Namespace"
          - group: ""
            version: "v1"
            kind: "Pod"
    EOF
    
  2. Senza vincoli applicati, esegui un workload con privilegi elevati:

    kubectl create -f- <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          privileged: true
    EOF
    
  3. Carica il modello di vincolo k8spspprivilegedcontainer precedente:

    kubectl create -f- <<EOF
    apiVersion: templates.gatekeeper.sh/v1beta1
    kind: ConstraintTemplate
    metadata:
      name: k8spspprivilegedcontainer
    spec:
      crd:
        spec:
          names:
            kind: K8sPSPPrivilegedContainer
      targets:
        - target: admission.k8s.gatekeeper.sh
          rego: |
            package k8spspprivileged
    
            violation[{"msg": msg, "details": {}}] {
                c := input_containers[_]
                c.securityContext.privileged
                msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext])
            }
            input_containers[c] {
                c := input.review.object.spec.containers[_]
            }
            input_containers[c] {
                c := input.review.object.spec.initContainers[_]
            }
    EOF
    
  4. Crea un nuovo vincolo per estendere questo template di vincolo. Questa volta, imposta enforcementAction su dryrun:

    kubectl create -f- <<EOF
    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sPSPPrivilegedContainer
    metadata:
      name: psp-privileged-container
    spec:
      enforcementAction: dryrun
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Pod"]
    EOF
    
  5. Con Gatekeeper che sincronizza i dati degli oggetti in esecuzione e controlla passivamente la presenza di violazioni, verifica se sono state rilevate violazioni controllando il campo status del vincolo:

    kubectl get k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container -o yaml
    
    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sPSPPrivilegedContainer
    metadata:
    ...
     name: psp-privileged-container
    ...
    spec:
     enforcementAction: dryrun
     match:
       kinds:
       - apiGroups:
         - ""
         kinds:
         - Pod
    status:
     auditTimestamp: "2019-12-15T22:19:54Z"
     byPod:
     - enforced: true
       id: gatekeeper-controller-manager-0
     violations:
     - enforcementAction: dryrun
       kind: Pod
       message: 'Privileged container is not allowed: nginx, securityContext: {"privileged":
         true}'
       name: nginx
       namespace: default
    
  6. Per verificare che la policy non interferisca con i deployment, esegui un altro pod con privilegi:

    kubectl create -f- <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: privpod
      labels:
        app: privpod
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          privileged: true
    EOF
    

    Il deployment del nuovo pod verrà eseguito correttamente.

  7. Per eseguire la pulizia delle risorse create in questa sezione, esegui questi comandi:

    kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container
    kubectl delete constrainttemplate k8spspprivilegedcontainer
    kubectl delete pod/nginx
    kubectl delete pod/privpod
    

Applicare i criteri

Ora che puoi confermare la validità e l'impatto di una policy senza influire sui workload esistenti o nuovi, puoi implementare una policy con l'applicazione completa.

Sulla base degli esempi utilizzati per convalidare la policy precedente, i passaggi seguenti mostrano come uno sviluppatore, un operatore o un amministratore può applicare modelli di vincoli e vincoli per applicare una policy:

  1. Carica il template di vincolo k8spspprivilegedcontainer menzionato in precedenza:

    kubectl create -f- <<EOF
    apiVersion: templates.gatekeeper.sh/v1beta1
    kind: ConstraintTemplate
    metadata:
      name: k8spspprivilegedcontainer
    spec:
      crd:
        spec:
          names:
            kind: K8sPSPPrivilegedContainer
      targets:
        - target: admission.k8s.gatekeeper.sh
          rego: |
            package k8spspprivileged
    
            violation[{"msg": msg, "details": {}}] {
                c := input_containers[_]
                c.securityContext.privileged
                msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext])
            }
            input_containers[c] {
                c := input.review.object.spec.containers[_]
            }
            input_containers[c] {
                c := input.review.object.spec.initContainers[_]
            }
    EOF
    
  2. Crea un nuovo vincolo per estendere questo template di vincolo. Questa volta, non impostare la chiave enforcementAction. Per impostazione predefinita, la chiave enforcementAction è impostata su deny:

    kubectl create -f- <<EOF
    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sPSPPrivilegedContainer
    metadata:
      name: psp-privileged-container
    spec:
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Pod"]
    EOF
    
  3. Prova a eseguire il deployment di un container che dichiara autorizzazioni con privilegi:

    kubectl create -f- <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          privileged: true
    EOF
    

    Dovresti ricevere il seguente messaggio di errore:

    Error from server ([denied by psp-privileged-container] Privileged container is not allowed:
    nginx, securityContext: {"privileged": true}): error when creating "STDIN": admission webhook "validation.gatekeeper.sh" denied the request: [denied by psp-privileged-container]
    Privileged container is not allowed: nginx, securityContext: {"privileged": true}
    
  4. Per eseguire la pulizia, esegui questi comandi:

    kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container
    kubectl delete constrainttemplate k8spspprivilegedcontainer
    

Alternative a Gatekeeper

Gatekeeper ti consente di dichiarare e applicare policy di sicurezza personalizzate a livello di pod. Puoi anche utilizzare il controller di ammissione PodSecurity integrato di Kubernetes per applicare policy di sicurezza predefinite a livello di pod. Queste policy predefinite sono allineate ai livelli definiti dagli standard di sicurezza dei pod.

Passaggi successivi

Gatekeeper fornisce un mezzo incredibilmente potente per applicare e convalidare la sicurezza sui cluster GKE utilizzando policy dichiarative. Tuttavia, l'utilizzo di Gatekeeper va oltre la sicurezza e può essere utilizzato in altri aspetti dell'amministrazione e delle operazioni.