Scrivi un modello di vincolo personalizzato

Questa pagina spiega come scrivere un modello di vincolo personalizzato e utilizzarlo per estendere Policy Controller se non riesci a trovare un modello di vincolo precompilato adatto alle tue esigenze.

Questa pagina è rivolta agli amministratori IT e agli operatori che vogliono assicurarsi che tutte le risorse in esecuzione all'interno della piattaforma cloud soddisfino i requisiti di conformità dell'organizzazione fornendo e mantenendo l'automazione per il controllo o l'applicazione e utilizzando i modelli di configurazione dichiarativa. Per saperne di più sui ruoli comuni e sulle attività di esempio a cui facciamo riferimento nei Google Cloud contenuti, consulta Ruoli e attività utente GKE comuni.

I criteri di Policy Controller vengono descritti utilizzando OPA Constraint Framework e sono scritti in Rego. Un criterio può valutare qualsiasi campo di un oggetto Kubernetes.

La scrittura di criteri utilizzando Rego è una competenza specializzata. Per questo motivo, per impostazione predefinita viene installata una libreria di modelli di vincoli comuni. È probabile che tu possa richiamare questi modelli di vincoli durante la creazione dei vincoli. Se hai esigenze specifiche, puoi creare i tuoi modelli di vincoli.

I modelli di vincoli consentono di separare la logica di un criterio dai relativi requisiti specifici, per il riutilizzo e la delega. Puoi creare vincoli utilizzando modelli di vincoli sviluppati da terze parti, come progetti open source, fornitori di software o esperti di normative.

Prima di iniziare

Esempio di modello di vincolo

Di seguito è riportato un esempio di modello di vincolo che nega tutte le risorse il cui nome corrisponde a un valore fornito dal creatore del vincolo. Il resto di questa pagina descrive i contenuti del modello, evidenziando i concetti importanti.

Se utilizzi Config Sync con un repository gerarchico, ti consigliamo di creare i vincoli nella directory cluster/.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdenyname
spec:
  crd:
    spec:
      names:
        kind: K8sDenyName
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            invalidName:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenynames
        violation[{"msg": msg}] {
          input.review.object.metadata.name == input.parameters.invalidName
          msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
        }

Esempio di vincolo

Di seguito è riportato un esempio di vincolo che potresti implementare per negare tutte le risorse denominate policy-violation:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyName
metadata:
  name: no-policy-violation
spec:
  parameters:
    invalidName: "policy-violation"

Parti di un modello di vincolo

I modelli di vincoli sono costituiti da due parti importanti:

  • Lo schema del vincolo che vuoi che gli utenti creino. Lo schema di un modello di vincolo è memorizzato nel campo crd.

  • Il codice sorgente Rego eseguito quando viene valutato il vincolo. Il codice sorgente Rego per un modello è memorizzato nel campo targets.

Schema (campo crd)

Il campo CRD è un progetto per la creazione della definizione di risorsa personalizzata di Kubernetes che definisce la risorsa di vincolo per l'API server di Kubernetes. Devi compilare solo i seguenti campi.

Campo Descrizione
spec.crd.spec.names.kind Il tipo di vincolo. Quando è in minuscolo, il valore di questo campo deve essere uguale a metadata.name.
spec.crd.spec.validation.openAPIV3Schema

Lo schema per il campo spec.parameters della risorsa di vincolo (Policy Controller definisce automaticamente il resto dello schema del vincolo). Segue le stesse convenzioni come farebbe in una normale risorsa CRD.

Il prefisso del modello di vincolo con il nome K8s è una convenzione che consente di evitare conflitti con altri tipi di modelli di vincoli, come i modelli Forseti che hanno come target le Google Cloud risorse.

Codice sorgente Rego (campo targets)

Le sezioni seguenti forniscono ulteriori informazioni sul codice sorgente Rego.

Località

Il codice sorgente Rego è memorizzato nel campo spec.targets, dove targets è un array di oggetti nel seguente formato:

{"target": "admission.k8s.gatekeeper.sh","rego": REGO_SOURCE_CODE, "libs": LIST_OF_REGO_LIBRARIES}
  • target: indica a Policy Controller il sistema che stiamo esaminando (in questo caso Kubernetes); è consentita una sola voce in targets.
  • rego: il codice sorgente del vincolo.
  • libs: un elenco facoltativo di librerie di codice Rego rese disponibili per il modello di vincolo; ha lo scopo di semplificare l'utilizzo delle librerie condivise e non rientra nell'ambito di questo documento.

Codice sorgente

Di seguito è riportato il codice sorgente Rego per il vincolo precedente:

package k8sdenynames

violation[{"msg": msg}] {
   input.review.object.metadata.name == input.parameters.invalidName
   msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
}

Tieni presente quanto segue:

  • package k8sdenynames è richiesto da OPA (il runtime di Rego). Il valore viene ignorato.
  • La regola Rego richiamata da Policy Controller per verificare la presenza di violazioni è denominata violation. Se questa regola ha corrispondenze, si è verificata una violazione del vincolo.
  • La regola violation ha la firma violation[{"msg": "violation message for the user"}], dove il valore di "msg" è il messaggio di violazione restituito all'utente.
  • I parametri forniti al vincolo sono resi disponibili con la parola chiave input.parameters.
  • La request-under-test è memorizzata con la parola chiave input.review.

La parola chiave input.review ha i seguenti campi.

Campo Descrizione
uid L'ID univoco per questa richiesta specifica; non è disponibile durante il controllo.
kind

Le informazioni sul tipo per l'object-under-test. Ha il seguente formato:

  • kind: il tipo di risorsa
  • group: il gruppo di risorse
  • version: la versione della risorsa
name Nome della risorsa. Potrebbe essere vuoto se l'utente si affida al l'API server per generare il nome in una richiesta CREATE.
namespace Lo spazio dei nomi della risorsa (non fornito per le risorse con ambito cluster).
operation L'operazione richiesta (ad esempio CREATE o UPDATE); non è disponibile durante il controllo.
userInfo

Le informazioni dell'utente che ha effettuato la richiesta; non sono disponibili durante il controllo. Ha il seguente formato:

  • username: l'utente che effettua la richiesta
  • uid: l'UID dell'utente
  • groups: un elenco di gruppi di cui l'utente è membro
  • extra: eventuali informazioni utente aggiuntive fornite da Kubernetes
object L'oggetto che l'utente sta tentando di modificare o creare.
oldObject Lo stato originale dell'oggetto; è disponibile solo per le operazioni UPDATE operazioni.
dryRun Indica se questa richiesta è stata richiamata con kubectl --dry-run; non è disponibile durante il controllo.

Scrivere modelli di vincoli referenziali

I modelli di vincoli referenziali sono modelli che consentono all'utente di vincolare un oggetto rispetto ad altri oggetti. Un esempio potrebbe essere "non consentire la creazione di un pod prima che esista un ingresso corrispondente". Un altro esempio potrebbe essere "non consentire a due servizi di avere lo stesso nome host".

Policy Controller consente di scrivere vincoli referenziali monitorando l'API server per un insieme di risorse fornite dall'utente. Quando una risorsa viene modificata, Policy Controller la memorizza nella cache localmente in modo che possa essere facilmente referenziata dal codice sorgente Rego. Policy Controller rende disponibile questa cache con la parola chiave data.inventory.

Le risorse con ambito cluster vengono memorizzate nella cache nella seguente posizione:

data.inventory.cluster["GROUP_VERSION"]["KIND"]["NAME"]

Ad esempio, un nodo denominato my-favorite-node è disponibile in

data.inventory.cluster["v1"]["Node"]["my-favorite-node"]

Le risorse con ambito a livello di spazio dei nomi vengono memorizzate nella cache qui:

data.inventory.namespace["NAMESPACE"]["GROUP_VERSION"]["KIND"]["NAME"]

Ad esempio, un ConfigMap denominato production-variables nello spazio dei nomi shipping-prod è disponibile in

data.inventory.namespace["shipping-prod"]["v1"]["ConfigMap"]["production-variables"]

L'intero contenuto dell'oggetto viene memorizzato in questa posizione della cache e può essere referenziato nel codice sorgente Rego come preferisci.

Ulteriori informazioni su Rego

Le informazioni precedenti forniscono le funzionalità uniche di Policy Controller che semplificano la scrittura di vincoli sulle risorse Kubernetes in Rego. Un tutorial completo su come scrivere in Rego non rientra nell'ambito di questa guida. Tuttavia, la documentazione di Open Policy Agent contiene informazioni sulla sintassi e sulle funzionalità del linguaggio Rego stesso.

Installare il modello di vincolo

Dopo aver creato il modello di vincolo, utilizza kubectl apply per applicarlo e Policy Controller si occuperà dell'importazione. Assicurati di controllare il campo status del modello di vincolo per verificare che non si siano verificati errori durante l'istanza. Se l'importazione è andata a buon fine, il campo status deve mostrare created: true e il campo observedGeneration indicato nel campo status deve essere uguale al campo metadata.generation.

Dopo l'importazione del modello, puoi applicare i vincoli come descritto in Creare vincoli.

Rimuovere un modello di vincolo

Per rimuovere un modello di vincolo:

  1. Verifica che nessun vincolo che vuoi conservare utilizzi il modello di vincolo:

    kubectl get TEMPLATE_NAME
    

    Se si verifica un conflitto di denominazione tra il nome del modello di vincolo e un oggetto diverso nel cluster, utilizza il seguente comando:

    kubectl get TEMPLATE_NAME.constraints.gatekeeper.sh
    
  2. Rimuovi il modello di vincolo:

    kubectl delete constrainttemplate CONSTRAINT_TEMPLATE_NAME
    

Quando rimuovi un modello di vincolo, non puoi più creare vincoli che lo referenziano.

Passaggi successivi