Build sicura e Esegui il deployment con Cloud Build, Artifact Registry e GKE

Creazione e implementazione sicure con Cloud Build, Artifact Registry e GKE

Informazioni su questo codelab

subjectUltimo aggiornamento: mar 4, 2023
account_circleScritto da: Christopher Grant

1. Introduzione

Container Analysis fornisce l'analisi delle vulnerabilità e l'archiviazione dei metadati per i container. Il servizio di scansione esegue analisi delle vulnerabilità sulle immagini in Artifact Registry e Container Registry, quindi archivia i metadati risultanti e li rende disponibili per l'utilizzo tramite un'API. L'archiviazione dei metadati ti consente di archiviare informazioni provenienti da diverse origini, tra cui scansione delle vulnerabilità, servizi Google Cloud e fornitori di terze parti.

L'analisi delle vulnerabilità può essere eseguita automaticamente o su richiesta:

  • Quando la scansione automatica è attiva, la scansione viene attivata automaticamente ogni volta che esegui il push di una nuova immagine in Artifact Registry o Container Registry. Le informazioni sulle vulnerabilità vengono aggiornate continuamente quando vengono scoperte nuove vulnerabilità.
  • Quando On-Demand Scanning è abilitato, devi eseguire un comando per eseguire la scansione di un'immagine locale o di un'immagine in Artifact Registry o Container Registry. La scansione on demand ti offre flessibilità in merito al momento in cui eseguire la scansione dei container. Ad esempio, puoi analizzare un'immagine creata localmente e correggere le vulnerabilità prima di archiviarla in un registry. I risultati della scansione sono disponibili fino a 48 ore dopo il completamento della scansione e le informazioni sulle vulnerabilità non vengono aggiornate dopo la scansione.

Con Container Analysis integrato nella pipeline CI/CD, puoi prendere decisioni in base a questi metadati. Ad esempio, puoi utilizzare Autorizzazione binaria per creare criteri di deployment che consentano solo i deployment di immagini conformi provenienti da registry attendibili.

Cosa imparerai a fare

  • Come attivare la scansione automatica
  • Come eseguire la scansione on demand
  • Come integrare la scansione in una pipeline di compilazione
  • Come firmare le immagini approvate
  • Come utilizzare i controller di ammissione GKE per bloccare le immagini
  • Come configurare GKE per consentire solo le immagini approvate firmate

2. Configurazione e requisiti

Configurazione dell'ambiente a tuo ritmo

  1. Accedi alla console Google Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Il nome del progetto è il nome visualizzato per i partecipanti al progetto. Si tratta di una stringa di caratteri non utilizzata dalle API di Google. Puoi aggiornarlo in qualsiasi momento.
  • L'ID progetto è univoco per tutti i progetti Google Cloud ed è immutabile (non può essere modificato dopo essere stato impostato). La console Cloud genera automaticamente una stringa univoca; in genere non è importante quale sia. Nella maggior parte dei codelab, dovrai fare riferimento all'ID progetto (in genere identificato come PROJECT_ID). Se l'ID generato non ti piace, puoi generarne un altro casuale. In alternativa, puoi provare il tuo e vedere se è disponibile. Non può essere modificato dopo questo passaggio e rimarrà invariato per tutta la durata del progetto.
  • Per tua informazione, esiste un terzo valore, un Numero progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
  1. Successivamente, dovrai abilitare la fatturazione nella console Cloud per utilizzare le API/risorse Cloud. L'esecuzione di questo codelab non dovrebbe costare molto, se non del tutto. Per arrestare le risorse in modo da non generare costi oltre questo tutorial, puoi eliminare le risorse che hai creato o l'intero progetto. I nuovi utenti di Google Cloud sono idonei al programma Prova senza costi di 300$.

Avvia l'editor di Cloud Shell

Questo lab è stato progettato e testato per l'utilizzo con l'editor di Google Cloud Shell. Per accedere all'editor:

  1. Accedi al tuo progetto Google all'indirizzo https://console.cloud.google.com.
  2. Nell'angolo in alto a destra, fai clic sull'icona dell'editor Cloud Shell

8560cc8d45e8c112.png

  1. Nella parte inferiore della finestra si aprirà un nuovo riquadro

Configurazione dell'ambiente

In Cloud Shell, imposta l'ID progetto e il numero del progetto. Salvale come variabili PROJECT_ID e PROJECT_ID.

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
   
--format='value(projectNumber)')

Abilitazione dei servizi

Attiva tutti i servizi necessari:

gcloud services enable \
  cloudkms
.googleapis.com \
  cloudbuild
.googleapis.com \
  container
.googleapis.com \
  containerregistry
.googleapis.com \
  artifactregistry
.googleapis.com \
  containerscanning
.googleapis.com \
  ondemandscanning
.googleapis.com \
  binaryauthorization
.googleapis.com

Crea un repository Artifact Registry

In questo lab utilizzerai Artifact Registry per archiviare e scansionare le immagini. Crea il repository con il seguente comando.

gcloud artifacts repositories create artifact-scanning-repo \
 
--repository-format=docker \
 
--location=us-central1 \
 
--description="Docker repository"

Configura Docker in modo che utilizzi le tue credenziali gcloud quando accedi ad Artifact Registry.

gcloud auth configure-docker us-central1-docker.pkg.dev

3. Scansione automatica

La scansione degli elementi si attiva automaticamente ogni volta che esegui il push di una nuova immagine in Artifact Registry o Container Registry. Le informazioni sulle vulnerabilità vengono aggiornate continuamente quando vengono scoperte nuove vulnerabilità. In questa sezione eseguirai il push di un'immagine in Artifact Registry ed esplorerai i risultati.

Creare e passare a una directory di lavoro

mkdir vuln-scan && cd vuln-scan

Definisci un'immagine di esempio

Crea un file denominato Dockerfile con i seguenti contenuti.

cat > ./Dockerfile << EOF
FROM gcr
.io/google-appengine/debian9@sha256:ebffcf0df9aa33f342c4e1d4c8428b784fc571cdf6fbab0b31330347ca8af97a

# System
RUN apt update
&& apt install python3-pip -y

# App
WORKDIR
/app
COPY
. ./

RUN pip3 install
Flask==1.1.4
RUN pip3 install gunicorn
==20.1.0

CMD
exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

EOF

Crea un file chiamato main.py con i seguenti contenuti

cat > ./main.py << EOF
import os
from flask import Flask

app
= Flask(__name__)

@app.route("/")
def hello_world():
    name
= os.environ.get("NAME", "Worlds")
   
return "Hello {}!".format(name)

if __name__ == "__main__":
    app
.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
EOF

Crea ed esegui il push dell'immagine in AR

Utilizza Cloud Build per creare il container ed eseguirne automaticamente il push in Artifact Registry. Prendi nota dell'attributo bad sull'immagine. In questo modo potrai identificarlo per i passaggi successivi.

gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad

Rivedi i dettagli delle immagini

Al termine del processo di compilazione, controlla l'immagine e i risultati relativi alle vulnerabilità nella dashboard di Artifact Registry.

  1. Apri Artifact Registry nella console Cloud
  2. Fai clic sul repository di scansione degli elementi per visualizzarne i contenuti
  3. Fai clic sui dettagli dell'immagine
  4. Fai clic sull'ultimo riepilogo della tua immagine
  5. Al termine della scansione, fai clic sulla scheda Vulnerabilità dell'immagine

Nella scheda Vulnerabilità vedrai i risultati della scansione automatica dell'immagine appena creata.

361be7b3bf293fca.png

L'automazione della scansione è abilitata per impostazione predefinita. Esplora le impostazioni di Artifact Registry per scoprire come disattivare/attivare la scansione automatica.

4. Scansione on demand

Esistono vari scenari in cui potresti dover eseguire una scansione prima di eseguire il push dell'immagine in un repository. Ad esempio, uno sviluppatore di container potrebbe eseguire la scansione di un'immagine e correggere i problemi prima di eseguire il push del codice nel controllo del codice sorgente. Nell'esempio seguente, creerai e analizzerai l'immagine localmente prima di intervenire in base ai risultati.

Crea un'immagine

In questo passaggio utilizzerai Docker locale per creare l'immagine nella cache locale.

docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image .

Scansiona l'immagine

Una volta creata l'immagine, richiedi una scansione. I risultati della ricerca vengono archiviati in un server di metadati. Il job viene completato con la posizione dei risultati nel server dei metadati.

gcloud artifacts docker images scan \
    us
-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
   
--format="value(response.scan)" > scan_id.txt

Esamina il file di output

Esamina l'output del passaggio precedente, che è stato memorizzato nel file scan_id.txt. Tieni presente la posizione del report dei risultati della scansione nel server dei metadati.

cat scan_id.txt

Esaminare i risultati dettagliati della scansione

Per visualizzare i risultati effettivi della scansione, utilizza il comando list-vulnerabilities nella posizione del report indicata nel file di output.

gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) 

L'output contiene una quantità significativa di dati su tutte le vulnerabilità dell'immagine.

Segnalare problemi critici

Gli utenti raramente utilizzano direttamente i dati archiviati nel report. In genere, i risultati vengono utilizzati da un processo automatizzato. Utilizza i comandi riportati di seguito per leggere i dettagli del report e registrare eventuali vulnerabilità CRITICHE rilevate.

export SEVERITY=CRITICAL

gcloud artifacts docker images list
-vulnerabilities $(cat scan_id.txt) --format="value(vulnerability.effectiveSeverity)" | if grep -Fxq ${SEVERITY}; then echo "Failed vulnerability check for ${SEVERITY} level"; else echo "No ${SEVERITY} Vulnerabilities found"; fi

L'output di questo comando sarà

Failed vulnerability check for CRITICAL level

5. Scansione della pipeline di compilazione

In questa sezione creerai una pipeline di compilazione automatica che creerà l'immagine del contenitore, la scansionerà e valuterà i risultati. Se non vengono rilevate vulnerabilità CRITICHE, l'immagine verrà inviata al repository. Se vengono rilevate vulnerabilità CRITICHE, la compilazione non andrà a buon fine ed uscirà.

Fornire l'accesso per l'account di servizio Cloud Build

Cloud Build avrà bisogno dei diritti per accedere all'API di scansione on demand. Fornisci l'accesso con i seguenti comandi.

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
       
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
       
--role="roles/iam.serviceAccountUser"
       
gcloud projects add
-iam-policy-binding ${PROJECT_ID} \
       
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
       
--role="roles/ondemandscanning.admin"

Crea la pipeline di Cloud Build

Il seguente comando crea un file cloudbuild.yaml nella tua directory che verrà utilizzato per la procedura automatica. Per questo esempio, i passaggi sono limitati al processo di compilazione del contenitore. In pratica, però, oltre ai passaggi del contenitore, dovrai includere istruzioni e test specifici per l'applicazione.

Crea il file con il seguente comando.

cat > ./cloudbuild.yaml << EOF
steps
:

# build
- id: "build"
  name
: 'gcr.io/cloud-builders/docker'
  args
: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
  waitFor
: ['-']

#Run a vulnerability scan at _SECURITY level
- id: scan
  name
: 'gcr.io/cloud-builders/gcloud'
  entrypoint
: 'bash'
  args
:
 
- '-c'
 
- |
   
(gcloud artifacts docker images scan \
    us
-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
   
--location us \
   
--format="value(response.scan)") > /workspace/scan_id.txt

#Analyze the result of the scan
- id: severity check
  name
: 'gcr.io/cloud-builders/gcloud'
  entrypoint
: 'bash'
  args
:
 
- '-c'
 
- |
      gcloud artifacts docker images list
-vulnerabilities \$(cat /workspace/scan_id.txt) \
     
--format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
     
then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi

#Retag
- id: "retag"
  name
: 'gcr.io/cloud-builders/docker'
  args
: ['tag',  'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']


#pushing to artifact registry
- id: "push"
  name
: 'gcr.io/cloud-builders/docker'
  args
: ['push',  'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']

images
:
 
- us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
EOF

Esegui la pipeline CI

Invia la build per l'elaborazione per verificare che la build venga interrotta quando viene rilevata una vulnerabilità con gravità CRITICAL.

gcloud builds submit

Errore di compilazione della recensione

La build che hai appena inviato non andrà a buon fine perché l'immagine contiene vulnerabilità CRITICHE.

Esamina l'errore di compilazione nella pagina Cronologia di Cloud Build.

Risolvere la vulnerabilità

Aggiorna il Dockerfile in modo da utilizzare un'immagine di base che non contenga vulnerabilità CRITICHE.

Sostituisci il Dockerfile per utilizzare l'immagine Debian 10 con il seguente comando

cat > ./Dockerfile << EOF
from python:3.8-slim  

# App
WORKDIR
/app
COPY
. ./

RUN pip3 install
Flask==2.1.0
RUN pip3 install gunicorn
==20.1.0

CMD
exec gunicorn --bind :\$PORT --workers 1 --threads 8 main:app

EOF

Esegui il processo CI con l'immagine corretta

Invia la build per l'elaborazione per verificare che venga completata correttamente quando non vengono rilevate vulnerabilità con gravità CRITICAL.

gcloud builds submit

Esamina la riuscita della compilazione

La compilazione che hai appena inviato andrà a buon fine perché l'immagine aggiornata non contiene vulnerabilità CRITICHE.

Controlla il buon esito della compilazione nella pagina Cronologia di Cloud Build.

Esamina i risultati della scansione

Esamina l'immagine corretta in Artifact Registry

  1. Apri Artifact Registry nella console Cloud
  2. Fai clic sul repository di scansione degli elementi per visualizzarne i contenuti
  3. Fai clic sui dettagli dell'immagine
  4. Fai clic sull'ultimo riepilogo della tua immagine
  5. Fai clic sulla scheda Vulnerabilità per l'immagine.

6. Immagini di firme

Creare una nota dell'attestatore

Una nota dell'attestatore è semplicemente un piccolo bit di dati che funge da etichetta per il tipo di firma applicata. Ad esempio, una nota potrebbe indicare la scansione delle vulnerabilità, mentre un'altra potrebbe essere utilizzata per la firma del QA. La nota verrà richiamata durante la procedura di firma.

Creare una nota

cat > ./vulnz_note.json << EOM
{
 
"attestation": {
   
"hint": {
     
"human_readable_name": "Container Vulnerabilities attestation authority"
   
}
 
}
}
EOM

Memorizza la nota

NOTE_ID=vulnz_note

curl
-vvv -X POST \
   
-H "Content-Type: application/json"  \
   
-H "Authorization: Bearer $(gcloud auth print-access-token)"  \
   
--data-binary @./vulnz_note.json  \
   
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"

Verifica la nota

curl -vvv  \
   
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
   
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"

Creazione di un attestatore

Gli attestatori vengono utilizzati per eseguire la procedura di firma effettiva dell'immagine e allegheranno un'occorrenza della nota all'immagine per la verifica successiva. Crea l'attestatore per utilizzarlo in un secondo momento.

Crea attestatore

ATTESTOR_ID=vulnz-attestor

gcloud container binauthz attestors create $ATTESTOR_ID
\
   
--attestation-authority-note=$NOTE_ID \
   
--attestation-authority-note-project=${PROJECT_ID}

Verifica attestatore

gcloud container binauthz attestors list

Tieni presente che l'ultima riga indica NUM_PUBLIC_KEYS: 0 che fornirai le chiavi in un passaggio successivo

Tieni inoltre presente che Cloud Build crea automaticamente l'attestatore built-by-cloud-build nel tuo progetto quando esegui una build che genera immagini. Pertanto, il comando riportato sopra restituisce due attestatori, vulnz-attestor e built-by-cloud-build. Dopo la compilazione delle immagini, Cloud Build le firma e crea automaticamente le attestazioni.

Aggiunta del ruolo IAM

L'account di servizio Authorization for Binary avrà bisogno dei diritti per visualizzare le note di attestazione. Fornisci l'accesso con la seguente chiamata API

PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}"  --format="value(projectNumber)")

BINAUTHZ_SA_EMAIL
="service-${PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"


cat
> ./iam_request.json << EOM
{
 
'resource': 'projects/${PROJECT_ID}/notes/${NOTE_ID}',
 
'policy': {
   
'bindings': [
     
{
       
'role': 'roles/containeranalysis.notes.occurrences.viewer',
       
'members': [
         
'serviceAccount:${BINAUTHZ_SA_EMAIL}'
       
]
     
}
   
]
 
}
}
EOM

Utilizza il file per creare il criterio IAM

curl -X POST  \
   
-H "Content-Type: application/json" \
   
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
   
--data-binary @./iam_request.json \
   
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}:setIamPolicy"

Aggiunta di una chiave KMS

L'Attestatore ha bisogno di chiavi crittografiche per allegare la nota e fornire firme verificabili. In questo passaggio creerai e memorizzerai le chiavi in KMS per consentire a Cloud Build di accedervi in un secondo momento.

Innanzitutto, aggiungi alcune variabili di ambiente per descrivere la nuova chiave

KEY_LOCATION=global
KEYRING
=binauthz-keys
KEY_NAME
=codelab-key
KEY_VERSION
=1

Creare un mazzo di chiavi per contenere un insieme di chiavi

gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"

Crea una nuova coppia di chiavi di firma asimmetrica per l'attestatore

gcloud kms keys create "${KEY_NAME}" \
   
--keyring="${KEYRING}" --location="${KEY_LOCATION}" \
   
--purpose asymmetric-signing   \
   
--default-algorithm="ec-sign-p256-sha256"

La chiave dovrebbe essere visualizzata nella pagina KMS della console Google Cloud.

Ora associa la chiave all'attestatore tramite il comando gcloud binauthz:

gcloud beta container binauthz attestors public-keys add  \
   
--attestor="${ATTESTOR_ID}"  \
   
--keyversion-project="${PROJECT_ID}"  \
   
--keyversion-location="${KEY_LOCATION}" \
   
--keyversion-keyring="${KEYRING}" \
   
--keyversion-key="${KEY_NAME}" \
   
--keyversion="${KEY_VERSION}"

Se stampi di nuovo l'elenco delle autorità, ora dovresti vedere una chiave registrata:

gcloud container binauthz attestors list

Creazione di un'attestazione firmata

A questo punto, hai configurato le funzionalità che ti consentono di firmare le immagini. Utilizza l'Attestatore che hai creato in precedenza per firmare l'immagine contenitore con cui hai lavorato

CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image

DIGEST
=$(gcloud container images describe ${CONTAINER_PATH}:latest \
   
--format='get(image_summary.digest)')

Ora puoi utilizzare gcloud per creare l'attestazione. Il comando acquisisce semplicemente i dettagli della chiave che vuoi utilizzare per la firma e l'immagine contenitore specifica che vuoi approvare

gcloud beta container binauthz attestations sign-and-create  \
   
--artifact-url="${CONTAINER_PATH}@${DIGEST}" \
   
--attestor="${ATTESTOR_ID}" \
   
--attestor-project="${PROJECT_ID}" \
   
--keyversion-project="${PROJECT_ID}" \
   
--keyversion-location="${KEY_LOCATION}" \
   
--keyversion-keyring="${KEYRING}" \
   
--keyversion-key="${KEY_NAME}" \
   
--keyversion="${KEY_VERSION}"

In termini di analisi dei contenitori, verrà creata una nuova occorrenza e allegata alla nota del tuo attestatore. Per assicurarti che tutto funzioni come previsto, puoi elencare le tue attestazioni

gcloud container binauthz attestations list \
   
--attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}

7. Firma con Cloud Build

Hai attivato la firma delle immagini e hai utilizzato manualmente l'Attestatore per firmare l'immagine di esempio. In pratica, ti consigliamo di applicare le attestazioni durante i processi automatici, come le pipeline CI/CD.

In questa sezione configurerai Cloud Build per eseguire l'attestazione delle immagini automaticamente

Ruoli

Aggiungi il ruolo Visualizzatore attestatore di autorizzazione binaria all'account di servizio Cloud Build:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
 
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
 
--role roles/binaryauthorization.attestorsViewer

Aggiungi il ruolo Firmatario/Responsabile verifica Cloud KMS CryptoKey all'account di servizio Cloud Build (firma basata su KMS):

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
 
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
 
--role roles/cloudkms.signerVerifier

Aggiungi il ruolo Container Analysis Notes Attacher all'account di servizio Cloud Build:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
 
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
 
--role roles/containeranalysis.notes.attacher

Prepara il passaggio di Cloud Build per la build personalizzata

Utilizzerai un passaggio di compilazione personalizzata in Cloud Build per semplificare la procedura di attestazione. Google fornisce questo passaggio di compilazione personalizzata che contiene funzioni di assistenza per semplificare il processo. Prima dell'uso, il codice per il passaggio di compilazione personalizzato deve essere compilato in un contenitore ed eseguito il push in Cloud Build. Per farlo, esegui i seguenti comandi:

git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
cd cloud
-builders-community/binauthz-attestation
gcloud builds submit
. --config cloudbuild.yaml
cd
../..
rm
-rf cloud-builders-community

Aggiungi un passaggio di firma a cloudbuild.yaml

In questo passaggio aggiungerai il passaggio di attestazione alla pipeline Cloud Build creata in precedenza.

  1. Rivedi il nuovo passaggio che aggiungerai.

Solo revisione. Non copiare

#Sign the image only if the previous severity check passes
- id: 'create-attestation'
  name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
  args:
    - '--artifact-url'
    - 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image'
    - '--attestor'
    - 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
    - '--keyversion'
    - 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'
  1. Sovrascrivi il file cloudbuild.yaml con la pipeline completa aggiornata.
cat > ./cloudbuild.yaml << EOF
steps
:

# build
- id: "build"
  name
: 'gcr.io/cloud-builders/docker'
  args
: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
  waitFor
: ['-']

#Run a vulnerability scan at _SECURITY level
- id: scan
  name
: 'gcr.io/cloud-builders/gcloud'
  entrypoint
: 'bash'
  args
:
 
- '-c'
 
- |
   
(gcloud artifacts docker images scan \
    us
-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
   
--location us \
   
--format="value(response.scan)") > /workspace/scan_id.txt

#Analyze the result of the scan
- id: severity check
  name
: 'gcr.io/cloud-builders/gcloud'
  entrypoint
: 'bash'
  args
:
 
- '-c'
 
- |
      gcloud artifacts docker images list
-vulnerabilities \$(cat /workspace/scan_id.txt) \
     
--format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
     
then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi

#Retag
- id: "retag"
  name
: 'gcr.io/cloud-builders/docker'
  args
: ['tag',  'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']


#pushing to artifact registry
- id: "push"
  name
: 'gcr.io/cloud-builders/docker'
  args
: ['push',  'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']


#Sign the image only if the previous severity check passes
- id: 'create-attestation'
  name
: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
  args
:
   
- '--artifact-url'
   
- 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good'
   
- '--attestor'
   
- 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
   
- '--keyversion'
   
- 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'



images
:
 
- us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good
EOF

Esegui la build

gcloud builds submit

Esamina la build nella cronologia di Cloud Build

Apri Cloud Console nella pagina Cronologia di Cloud Build e controlla l'ultima build e l'esecuzione corretta dei passaggi di compilazione.

8. Criteri di controllo di ammissione

Autorizzazione binaria è una funzionalità di GKE e Cloud Run che consente di convalidare le regole prima che un'immagine contenitore possa essere eseguita. La convalida viene eseguita su qualsiasi richiesta di esecuzione di un'immagine, che provenga da una pipeline CI/CD attendibile o da un utente che tenta di eseguire manualmente il deployment di un'immagine. Questa funzionalità ti consente di proteggere i tuoi ambienti di runtime in modo più efficace rispetto ai soli controlli della pipeline CI/CD.

Per comprendere questa funzionalità, modifichi il criterio GKE predefinito per applicare una regola di autorizzazione rigorosa.

Crea il cluster GKE

Crea il cluster GKE:

gcloud beta container clusters create binauthz \
   
--zone us-central1-a  \
   
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE

Consenti a Cloud Build di eseguire il deployment in questo cluster:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
       
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
       
--role="roles/container.developer"

Criterio Consenti tutto

Innanzitutto, verifica lo stato del criterio predefinito e la tua capacità di eseguire il deployment di qualsiasi immagine

  1. Esamina i criteri esistenti
gcloud container binauthz policy export
  1. Tieni presente che il criterio di applicazione è impostato su ALWAYS_ALLOW

evaluationMode: ALWAYS_ALLOW

  1. Esegui il deployment di Sample per verificare di poter eseguire il deployment di qualsiasi elemento
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. Verificare che il deployment abbia funzionato
kubectl get pods

Verrà visualizzato il seguente output

161db370d99ffb13.png

  1. Elimina deployment
kubectl delete pod hello-server

Criterio di rifiuto di tutti

Ora aggiorna il criterio per non consentire tutte le immagini.

  1. Esportare il criterio attuale in un file modificabile
gcloud container binauthz policy export  > policy.yaml
  1. Modifica la norma

In un editor di testo, modifica il valore evaluationMode da ALWAYS_ALLOW a ALWAYS_DENY.

edit policy.yaml

Il file YAML dei criteri dovrebbe avere il seguente aspetto:

globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_DENY
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/PROJECT_ID/policy
  1. Apri il terminale, applica il nuovo criterio e attendi qualche secondo per la propagazione della modifica
gcloud container binauthz policy import policy.yaml
  1. Provare il deployment di un carico di lavoro di esempio
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. Il deployment non riesce con il seguente messaggio
Error from server (VIOLATES_POLICY): admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image gcr.io/google-samples/hello-app:1.0 denied by Binary Authorization default admission rule. Denied by always_deny admission rule

Ripristina il criterio per consentire tutto

Prima di passare alla sezione successiva, assicurati di annullare le modifiche ai criteri

  1. Modifica la norma

In un editor di testo, modifica il valore evaluationMode da ALWAYS_DENY a ALWAYS_ALLOW.

edit policy.yaml

Il file YAML dei criteri dovrebbe avere il seguente aspetto:

globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_ALLOW
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/PROJECT_ID/policy
  1. Applica il criterio ripristinato
gcloud container binauthz policy import policy.yaml

9. Bloccare le vulnerabilità in GKE

In questa sezione combinerai ciò che hai imparato finora implementando una pipeline CI/CD con Cloud Build che esegue la scansione delle immagini, quindi controlla la presenza di vulnerabilità prima di firmare l'immagine e tentare di eseguire il deployment. GKE utilizzerà l'autorizzazione binaria per convalidare che l'immagine abbia una firma dell'analisi delle vulnerabilità prima di consentirne l'esecuzione.

d5c41bb89e22fd61.png

Aggiorna il criterio GKE in modo da richiedere l'attestazione

Richiedi che le immagini siano firmate dall'Attestatore aggiungendo clusterAdmissionRules al criterio BinAuth di GKE

Sostituisci il criterio con la configurazione aggiornata utilizzando il comando seguente.

COMPUTE_ZONE=us-central1-a

cat
> binauth_policy.yaml << EOM
defaultAdmissionRule
:
  enforcementMode
: ENFORCED_BLOCK_AND_AUDIT_LOG
  evaluationMode
: ALWAYS_DENY
globalPolicyEvaluationMode
: ENABLE
clusterAdmissionRules
:
  $
{COMPUTE_ZONE}.binauthz:
    evaluationMode
: REQUIRE_ATTESTATION
    enforcementMode
: ENFORCED_BLOCK_AND_AUDIT_LOG
    requireAttestationsBy
:
   
- projects/${PROJECT_ID}/attestors/vulnz-attestor
EOM

Applica il criterio

gcloud beta container binauthz policy import binauth_policy.yaml

Tentativo di eseguire il deployment dell'immagine non firmata

Crea un descrittore di deployment per l'applicazione creata in precedenza utilizzando il comando seguente. L'immagine utilizzata qui è quella che hai creato in precedenza e che contiene vulnerabilità critiche e NON contiene l'attestazione firmata.

I controller di ammissione GKE devono conoscere l'immagine esatta da implementare per convalidare in modo coerente la firma. Per farlo, dovrai utilizzare il digest dell'immagine anziché un semplice tag.

Ottieni il digest dell'immagine non valida

CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image


DIGEST
=$(gcloud container images describe ${CONTAINER_PATH}:bad \
   
--format='get(image_summary.digest)')

Utilizzare il digest nella configurazione di Kubernetes

cat > deploy.yaml << EOM
apiVersion
: v1
kind
: Service
metadata
:
  name
: deb-httpd
spec
:
  selector
:
    app
: deb-httpd
  ports
:
   
- protocol: TCP
      port
: 80
      targetPort
: 8080
---
apiVersion
: apps/v1
kind
: Deployment
metadata
:
  name
: deb-httpd
spec
:
  replicas
: 1
  selector
:
    matchLabels
:
      app
: deb-httpd
 
template:
    metadata
:
      labels
:
        app
: deb-httpd
    spec
:
      containers
:
     
- name: deb-httpd
        image
: ${CONTAINER_PATH}@${DIGEST}
        ports
:
       
- containerPort: 8080
        env
:
         
- name: PORT
            value
: "8080"

EOM

Tenta di eseguire il deployment dell'app in GKE

kubectl apply -f deploy.yaml

Esamina il carico di lavoro nella console e prendi nota dell'errore che indica che il deployment è stato negato:

No attestations found that were valid and signed by a key trusted by the attestor

Esegui il deployment di un'immagine firmata

Ottieni il digest dell'immagine non valida

CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image


DIGEST
=$(gcloud container images describe ${CONTAINER_PATH}:good \
   
--format='get(image_summary.digest)')

Utilizzare il digest nella configurazione di Kubernetes

cat > deploy.yaml << EOM
apiVersion
: v1
kind
: Service
metadata
:
  name
: deb-httpd
spec
:
  selector
:
    app
: deb-httpd
  ports
:
   
- protocol: TCP
      port
: 80
      targetPort
: 8080
---
apiVersion
: apps/v1
kind
: Deployment
metadata
:
  name
: deb-httpd
spec
:
  replicas
: 1
  selector
:
    matchLabels
:
      app
: deb-httpd
 
template:
    metadata
:
      labels
:
        app
: deb-httpd
    spec
:
      containers
:
     
- name: deb-httpd
        image
: ${CONTAINER_PATH}@${DIGEST}
        ports
:
       
- containerPort: 8080
        env
:
         
- name: PORT
            value
: "8080"

EOM

Esegui il deployment dell'app in GKE

kubectl apply -f deploy.yaml

Esamina il workload nella console e prendi nota del deployment riuscito dell'immagine.

10. Complimenti!

Complimenti, hai completato il codelab.

Argomenti trattati:

  • Come attivare la scansione automatica
  • Come eseguire la scansione on demand
  • Come integrare la scansione in una pipeline di compilazione
  • Come firmare le immagini approvate
  • Come utilizzare i controller di ammissione GKE per bloccare le immagini
  • Come configurare GKE per consentire solo le immagini approvate firmate

Passaggi successivi

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

Elimina il progetto

Il modo più semplice per eliminare la fatturazione è eliminare il progetto che hai creato per il tutorial.