Migrazione da OpenShift a GKE Enterprise: migrazione dei vincoli del contesto di sicurezza di OpenShift a GKE Enterprise

Last reviewed 2022-01-24 UTC

Questo documento ti aiuta a pianificare la migrazione dei criteri di sicurezza dai vincoli di contesto di sicurezza (SCC) di OpenShift definiti in un cluster OpenShift di origine a un cluster GKE di destinazione. L'implementazione utilizza i vincoli di Policy Controller per definire i criteri di cui è stata eseguita la migrazione sul cluster di destinazione.

Il documento presuppone che tu abbia familiarità con Migrazione dei container a Google Cloud: migrazione da OpenShift a GKE Enterprise. Si presume che tu abbia familiarità con OpenShift e i vincoli di contesto di sicurezza e che tu abbia accesso a un cluster OpenShift di origine e a un cluster GKE di destinazione.

Questo documento fa parte di una serie in più parti sulla migrazione a Google Cloud. Per una panoramica della serie, consulta Migrazione a Google Cloud: scelta del percorso di migrazione.

Questo documento fa parte di una serie che illustra la migrazione dei containers a Google Cloud:

Questo documento è utile se prevedi di eseguire la migrazione delle sCC di OpenShift a GKE Enterprise. Questo documento è utile anche se stai valutando l'opportunità di eseguire la migrazione e vuoi esplorare il possibile aspetto.

Questo documento si basa sui concetti trattati negli argomenti Migrazione a Google Cloud: Introduzione, Migrazione dei container in Google Cloud: migrazione di Kubernetes a GKE, Migrazione dei container in Google Cloud: migrazione da OpenShift a GKE Enterprise e Best practice per il networking di GKE. Ove appropriato, include i link ai documenti in questione.

SCC OpenShift

Le SCC sono risorse specifiche di OpenShift utilizzate per definire criteri per i pod che specificano le azioni che un pod può eseguire e le risorse a cui può accedere sui nodi. Quando effettui una richiesta API per creare un pod, le SCC valutano le richieste pod in termini di privilegi per il processo in base a un insieme di criteri definiti tramite la SCC. Le SCC valutano le richieste per consentire o impedire l'esecuzione dei pod in base ai criteri configurati. Per saperne di più sulle SCC di OpenShift, consulta Gestire i vincoli del contesto di sicurezza.

SCC OpenShift predefinite

I cluster di OpenShift 4.x contengono un set di SCC predefinite descritte nel post del blog Gestire le SCC in OpenShift di Red Hat.

Config Sync e Policy Controller

Questa sezione descrive Config Sync e Policy Controller. Questa sezione fornisce i link alla documentazione pertinente e alle indicazioni per configurare Policy Controller per l'esecuzione delle attività di migrazione descritte più avanti in questo documento.

Config Sync

Config Sync consente di utilizzare un repository comune conforme a Git per definire centralmente la configurazione di qualsiasi risorsa applicabile a qualsiasi cluster Kubernetes gestito da GKE Enterprise. che puoi applicare a più cluster.

Policy Controller

Policy Controller è un controller di ammissione dinamico di Kubernetes che verifica, controlla e applica la conformità dei cluster ai criteri definiti a livello centrale. Policy Controller si basa sul progetto open source Open Policy Agent (OPA) Gatekeeper.

Configurazione di Config Sync e Policy Controller

Per prepararti a implementare i criteri di sicurezza che eseguono il mirroring delle SCC OpenShift, devi abilitare i componenti Config Sync e Policy Controller per ciascuno dei cluster di destinazione. Questa sezione descrive come configurare questi componenti. La sezione Esegui la migrazione delle SCC di OpenShift più avanti in questo documento descrive come utilizzare i modelli di vincoli di Policy Controller per implementare i criteri di sicurezza.

Quando configuri Policy Controller, è buona norma inserire nel campo Spazi dei nomi esenti gli spazi dei nomi relativi al sistema che non eseguono pod dell'applicazione. L'esenzione degli spazi dei nomi relativi al sistema consente di evitare il rischio di bloccare qualsiasi pod di sistema che richiede privilegi elevati. Gli spazi dei nomi relativi al sistema su un cluster GKE possono includere quanto segue:

  • kube-system
  • kube-public
  • gke-connect
  • gke-system
  • config-management-system
  • config-management-monitoring
  • gatekeeper-system
  • istio-system
  • cnrm-system
  • knative-serving
  • monitoring-system

Dopo aver configurato Policy Controller con le eccezioni precedenti, escludi gli spazi dei nomi dall'applicazione dei vincoli aggiungendo l'etichetta admission.gatekeeper.sh/ignore=true a ogni spazio dei nomi. Se non aggiungi l'etichetta a ogni spazio dei nomi, i pod di sistema (e quindi l'intero cluster) possono essere interessati da criteri restrittivi.

Esegui la migrazione delle SCC OpenShift ai vincoli di Policy Controller

Questa sezione descrive come esportare le SCC dal cluster OpenShift e configurare i vincoli di GKE Enterprise Policy Controller di destinazione in modo che corrispondano ai criteri richiesti. Questa sezione descrive anche alcune differenze tra i vincoli SCC e Policy Controller in modo da poter pianificare la migrazione di conseguenza.

Valuta le SCC OpenShift

Per esportare un elenco e la configurazione delle SCC installate nel tuo cluster OpenShift, puoi utilizzare i seguenti comandi:

  1. Recupera un elenco di tutte le SCC:

    oc get scc
    
  2. Esporta la configurazione di ciascuna SCC:

    oc get scc SCC_NAME > SCC_NAME.yaml
    

    Sostituisci SCC_NAME con il nome della SCC per cui vuoi esportare la configurazione.

Dopo aver esportato la configurazione, puoi analizzarla e utilizzare la tabella nella seguente sezione Mappa le SCC OpenShift per configurare i vincoli di Policy Controller che corrispondono ai tuoi requisiti di sicurezza delle applicazioni.

Mappare le SCC OpenShift ai modelli di vincoli di Policy Controller

La seguente tabella fornisce i vincoli e le impostazioni di Policy Controller corrispondenti ai campi SCC di OpenShift e ai relativi valori possibili. Utilizza la tabella per configurare i vincoli di Policy Controller di destinazione che corrispondono ai requisiti di sicurezza delle applicazioni implementati tramite le SCC OpenShift nell'ambiente di origine. La sezione Esempio di migrazione end-to-end più avanti in questo documento fornisce un esempio di come utilizzare le informazioni nella tabella.

Campo SCC OpenShift Tipo / valori possibili Modello di vincolo di Policy Controller Specifica del vincolo di Policy Controller
allowPrivilegedContainer: Booleano K8sPSPPrivilegedContainer Impedisce i container con privilegi, se applicati.
allowHostIPC: Booleano Spazio dei nomi K8sPSPHost Impedisce l'accesso all'host pid e allo spazio dei nomi ipc, se applicato.
allowHostPID: Booleano Spazio dei nomi K8sPSPHost Impedisce l'accesso all'host pid e allo spazio dei nomi ipc, se applicato.
allowHostNetwork: Booleano K8sPSPHostNetworkingPorts Ha un parametro booleano per impedire l'accesso alla rete host e può definire un intervallo di porte host accessibili.
allowHostPorts: Booleano K8sPSPHostNetworkingPorts Ha un parametro booleano per impedire l'accesso alla rete host e può definire un intervallo di porte host accessibili.
readOnlyRootFilesystem: Booleano K8sPSPReadOnlyRootFilesystem Consente di montare il file system radice del container solo in sola lettura, se applicato.
allowPrivilegeEscalation: true Booleano K8sPSPAllowPrivilegeEscalationContainer Impedisce i pod con contesto di sicurezza AllowPrivilegeEscalation impostato su true, se applicato.
allowHostDirVolumePlugin: Booleano K8sPSPVolumeTypes Contiene un parametro per definire l'elenco dei tipi di volumi consentiti (come in SCC), inclusa la directory host.
volumes: Elenco di array con tipo di volumi consentiti K8sPSPVolumeTypes Contiene un parametro per definire l'elenco dei tipi di volumi consentiti (come in SCC), inclusa la directory host.
allowedCapabilities: Elenco di array di funzionalità Linux che è possibile richiedere. Funzionalità K8sPSP Ha parametri per definire le funzionalità Linux che possono essere richieste (allowedCapabilities) e che sono vietate (requiredDropCapabilites).

Non può essere utilizzata per aggiungere o rilasciare direttamente le funzionalità elencate, come è possibile fare in defaultAddCapabilities: e requiredDropCapabilities: nelle SCC OpenShift.

defaultAddCapabilities: Elenco di array di funzionalità Linux da aggiungere a ogni container. Funzionalità K8sPSP Ha parametri per definire le funzionalità Linux che possono essere richieste (allowedCapabilities) e che sono vietate (requiredDropCapabilites).

Non può essere utilizzata per aggiungere o rilasciare direttamente le funzionalità elencate, come è possibile fare in defaultAddCapabilities: e requiredDropCapabilities: nelle SCC OpenShift.

requiredDropCapabilities: Elenco di array di funzionalità Linux che vengono eliminate automaticamente dal pod o dal container. Funzionalità K8sPSP Ha parametri per definire le funzionalità Linux che possono essere richieste (allowedCapabilities) e che sono vietate (requiredDropCapabilites).

Non può essere utilizzata per aggiungere o rilasciare direttamente le funzionalità elencate, come è possibile fare in defaultAddCapabilities: e requiredDropCapabilities: nelle SCC OpenShift.

fsGroup: Ha un valore type: key che può essere uno dei seguenti:
  • MustRunAs: richiede di specificare almeno un intervallo se non vengono utilizzati valori preallocati.
  • RunAsAny: consente di specificare qualsiasi ID fsGroup.
UtentiK8sPSPAllowed Consente di definire regole che hanno una funzione simile a type: key negli intervalli SCC e id per i parametri runAsUser, runAsGroup, supplementalGroups e fsGroup.

Può essere utilizzato per definire gli intervalli consentiti per utenti, gruppi, gruppi supplementari o gruppi FS, ma non per impostare lo User-ID direttamente nel pod, come è possibile fare nelle SCC di OpenShift.

runAsUser: Ha un valore type: key che può essere uno dei seguenti:
  • MustRunAs: richiede la configurazione di un runAsUser.
  • MustRunAsRange: richiede la definizione dei valori minimo e massimo se non vengono utilizzati valori preallocati dallo spazio dei nomi.
  • MustRunAsNonRoot: richiede che il pod venga inviato con un valore runAsUser diverso da zero o che abbia l'istruzione USER definita nell'immagine.
  • RunAsAny: consente di specificare qualsiasi runAsUser.
UtentiK8sPSPAllowed Consente di definire regole che hanno una funzione simile a type: key negli intervalli SCC e id per i parametri runAsUser, runAsGroup, supplementalGroups e fsGroup.

Può essere utilizzato per definire gli intervalli consentiti per utenti, gruppi, gruppi supplementari o gruppi FS, ma non per impostare lo User-ID direttamente nel pod, come è possibile fare nelle SCC di OpenShift.

supplementalGroups: Ha un valore type: key che può essere uno dei seguenti:
  • MustRunAs: richiede almeno un intervallo da specificare se non vengono utilizzati valori preallocati dallo spazio dei nomi
  • RunAsAny: consente di specificare eventuali gruppi supplementari.
UtentiK8sPSPAllowed Consente di definire regole che hanno una funzione simile a type: key negli intervalli SCC e id per i parametri runAsUser, runAsGroup, supplementalGroups e fsGroup.

Può essere utilizzato per definire gli intervalli consentiti per utenti, gruppi, gruppi supplementari o gruppi FS, ma non per impostare lo User-ID direttamente nel pod, come è possibile fare nelle SCC di OpenShift.

seLinuxContext: Ha un valore type: key che può essere uno dei seguenti:
  • MustRunAs: richiede la configurazione di seLinuxOptions se non vengono utilizzati valori preallocati dallo spazio dei nomi.
  • RunAsAny: consente di specificare qualsiasi seLinuxOptions.
K8sPSPSELinuxV2 Ha un parametro allowedSELinuxOptions in cui è possibile impostare livello, ruolo, tipo e utente seLinuxOptions consentiti

Differenze tra le SCC OpenShift e i vincoli di Policy Controller

In questa sezione vengono descritte alcune differenze tra i vincoli di Policy Controller e le SCC OpenShift. Valuta queste differenze prima di utilizzare la tabella precedente per eseguire il deployment dei vincoli nell'ambiente di destinazione.

Come vengono applicati i vincoli alle risorse

Puoi assegnare SCC OpenShift a utenti e gruppi utilizzando la specifica users: o group: presente nell'oggetto SCC. Con OpenShift 4.x e le versioni successive, puoi anche assegnare SCC a utenti o gruppi utilizzando il controllo controllo dell'accesso basato sui ruoli (RBAC). Le SCC hanno anche un campo priority: che viene utilizzato per ordinare le SCC applicate a un pod.

I vincoli di Policy Controller vengono applicati a cluster, spazi dei nomi o pod di destinazione utilizzando selettori di risorse specifici nel vincolo, anziché scegliere come target l'account utente o di servizio. Per ulteriori informazioni, consulta la documentazione di Policy Controller. L'utilizzo di selettori di risorse specifici consente di assicurare che il pod si comporti allo stesso modo indipendentemente dal fatto che un utente con privilegi limitati lo esegua utilizzando uno strumento di deployment o un amministratore del cluster lo avvii dalla riga di comando.

I vincoli di Policy Controller supportano anche la modalità di prova, che consente di testare i criteri e controllare le violazioni prima dell'applicazione effettiva. Questa modalità consente di prevenire l'impatto sui carichi di lavoro esistenti, mentre le SCC vengono sempre applicate se applicabili all'utente.

Mutazione del pod SCC utilizzando valori preallocati negli spazi dei nomi OpenShift

Nelle SCC OpenShift, puoi modificare il contesto di sicurezza correlato di ogni pod a cui viene applicata la SCC con un ID specifico da un intervallo preallocato fornito dalle annotazioni negli spazi dei nomi. Puoi farlo utilizzando i campi RunAsUser, fsGroup, supplementalGroups e seLinuxContext con un tipo di strategia MustRunAs o MustRunAsRange.

Ad esempio, considera una SCC restricted con un campo RunAsUser con un tipo di strategia MustRunAsRange senza intervallo definito nella SCC. In questo scenario, ogni pod a cui si applica la SCC riceve un ID RunAsUser dall'intervallo specificato nell'annotazione openshift.io/sa.scc.uid-range nello spazio dei nomi del pod.

I vincoli di Policy Controller insieme alle funzionalità di mutazione forniscono sia la convalida che la mutazione dei pod. Tuttavia, i vincoli non utilizzano annotazioni negli spazi dei nomi per fornire valori per i contesti di sicurezza dei pod. La prossima sezione, Esempio di migrazione end-to-end, fornisce un esempio di come i team di distribuzione delle applicazioni devono configurare esplicitamente i contesti di sicurezza sui pod per rispettare vincoli che implementano restrizioni simili a quelle elencate in precedenza.

Esempio di migrazione end-to-end

Questa sezione fornisce un esempio di file manifest di destinazione che include tutti i vincoli e i mutatori di Policy Controller necessari per mappare le seguenti SCC predefinite di OpenShift sul cluster GKE di destinazione:

  • privileged
  • anyuid
  • nonroot
  • restricted

A seconda dello spazio dei nomi in cui viene eseguito un pod, quest'ultimo riceve vincoli di controller dei criteri diversi quando mappi i criteri SCC definiti in un ambiente OpenShift di origine:

  • I carichi di lavoro che richiedono il massimo accesso con privilegi, ad esempio la possibilità di essere eseguiti in modalità con privilegi o di accedere a qualsiasi risorsa host, devono essere eseguiti in uno degli spazi dei nomi esenti definiti nella configurazione di Policy Controller.

    Nessun vincolo viene applicato agli spazi dei nomi esenti. I carichi di lavoro che dispongono dell'accesso con i privilegi più elevati sono in genere componenti di sistema o qualsiasi carico di lavoro a cui è stata applicata la SCC con privilegi nell'ambiente OpenShift di origine.

  • Tutti i pod creati in spazi dei nomi non esenti ricevono i vincoli più restrittivi. Questi vincoli negano l'accesso a tutte le funzionalità host e richiedono l'esecuzione dei pod con un UID che fa parte di un intervallo specifico. Questa configurazione corrisponde ai criteri applicati da OpenShift restricted SCC. Le eccezioni a questa configurazione includono quanto segue:

    • I pod creati in uno spazio dei nomi con l'etichetta security=anyuid ricevono i vincoli restrittivi precedenti, ma possono essere eseguiti con qualsiasi UID e qualsiasi GID. Corrisponde ai vincoli della SCC anyuid su OpenShift.
    • I pod creati in uno spazio dei nomi con l'etichetta security=nonroot ricevono i vincoli restrittivi precedenti. Tuttavia, i pod possono essere eseguiti con qualsiasi UID non principale. Questo soddisfa i vincoli della SCC nonroot su OpenShift.

Esempio di manifest target

Di seguito è riportato un esempio di un singolo manifest che include un insieme di vincoli e mutatori di Policy Controller corrispondenti al comportamento descritto nell'esempio di migrazione end-to-end precedente. Ti consigliamo di rivedere e modificare i vincoli o il relativo ambito in questo esempio in base alle esigenze della tua organizzazione.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPHostNamespace
metadata:
  name: psp-host-namespace
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPHostNetworkingPorts
metadata:
  name: psp-host-network-ports
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    hostNetwork: false
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPPrivilegedContainer
metadata:
  name: psp-privileged-container
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
---
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
  name: restricted-capabilities
spec:
  applyTo:
  - groups: [""]
    kinds: ["Pod"]
    versions: ["v1"]
  match:
    scope: Namespaced
    kinds:
    - apiGroups: ["*"]
      kinds: ["Pod"]
    namespaceSelector:
      matchExpressions:
        - operator: NotIn
          key: security
          values: ["anyuid"]
  location: "spec.containers[name:*].securityContext.capabilities.drop"
  parameters:
    assign:
      value: ["KILL","MKNOD","SYS_CHROOT"]
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPCapabilities
metadata:
  name: restricted-capabilities
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaceSelector:
      matchExpressions:
        - operator: NotIn
          key: security
          values: ["anyuid"]
  parameters:
    requiredDropCapabilities: ["KILL","MKNOD","SYS_CHROOT"]
---
apiVersion: mutations.gatekeeper.sh/v1alpha1
kind: Assign
metadata:
  name: anyuid-capabilities
spec:
  applyTo:
  - groups: [""]
    kinds: ["Pod"]
    versions: ["v1"]
  match:
    scope: Namespaced
    kinds:
    - apiGroups: ["*"]
      kinds: ["Pod"]
    namespaceSelector:
      matchExpressions:
        - operator: In
          key: security
          values: ["anyuid"]
  location: "spec.containers[name:*].securityContext.capabilities.drop"
  parameters:
    assign:
      value: ["MKNOD"]
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPCapabilities
metadata:
  name: anyuid-capabilities
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaceSelector:
      matchExpressions:
        - operator: In
          key: security
          values: ["anyuid"]
  parameters:
    requiredDropCapabilities: ["MKNOD"]
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPAllowedUsers
metadata:
  name: restricted-users-and-groups
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaceSelector:
      matchExpressions:
        - operator: NotIn
          key: security
          values: ["anyuid","nonroot"]
  parameters:
    runAsUser:
      rule: MustRunAs # MustRunAsNonRoot # RunAsAny
      ranges:
        - min: 1000
          max: 2000
    fsGroup:
      rule: MustRunAs # MayRunAs # RunAsAny
      ranges:
        - min: 1000
          max: 2000
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPAllowedUsers
metadata:
  name: nonroot-users-and-groups
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaceSelector:
      matchExpressions:
        - operator: In
          key: security
          values: ["nonroot"]
  parameters:
    runAsUser:
      rule: MustRunAsNonRoot
    fsGroup:
      rule: MustRunAsNonRoot
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPVolumeTypes
metadata:
  name: psp-volume-types
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    volumes:
      - configMap
      - downwardAPI
      - emptyDir
      - nfs
      - persistentVolumeClaim
      - projected
      - secret

Il vincolo restricted-users-and-groups nel manifest di esempio utilizza il modello K8sPSPAllowedUsers per impostare esplicitamente un intervallo di esempio compreso tra 1000 e 2000 per i parametri runAsUser: e fsGroup:. Qualsiasi pod che non è impostato per utilizzare un ID in questo intervallo per runAsUser: e fsGroup: è bloccato.

GKE Enterprise e Kubernetes non utilizzano le annotazioni dello spazio dei nomi per modificare automaticamente i pod con un ID utente o gruppo specifico. Pertanto, per limitare l'intervallo UID come nell'esempio precedente, i team di distribuzione delle applicazioni devono impostare esplicitamente un UID conforme sul pod creato oppure devi rimuovere completamente il vincolo per consentire qualsiasi ID.

Di seguito è riportato un esempio di manifest del pod conforme ai vincoli precedenti in qualsiasi spazio dei nomi in cui lo crei (il manifest è conforme allo SCC restricted):

apiVersion: v1
kind: Pod
metadata:
  name: restricted-pod-example
spec:
  securityContext:
    runAsUser: 1000
    fsGroup: 1100
  volumes:
  - name: sec-ctx-vol
    emptyDir: {}
  containers:
  - name: sec-ctx-demo
    image: busybox
    command: [ "sh", "-c", "sleep 1h" ]
    volumeMounts:
    - name: sec-ctx-vol
      mountPath: /data/demo

Passaggi successivi

  • Esplora le architetture di riferimento, i diagrammi e le best practice su Google Cloud. Visita il nostro Cloud Architecture Center.