Protezione delle build di container

1. Introduzione

ead1609267034bf7.png

Le vulnerabilità del software sono punti deboli che possono causare un guasto accidentale del sistema o fornire agli utenti malintenzionati un mezzo per compromettere il software. Container Analysis offre due tipi di analisi del sistema operativo per individuare le vulnerabilità nei container:

  • L'API On-Demand Scanning ti consente di eseguire manualmente la scansione delle immagini container per rilevare le vulnerabilità del sistema operativo, a livello locale sul computer o da remoto in Container Registry o Artifact Registry.
  • L'API Container Scanning ti consente di automatizzare il rilevamento delle vulnerabilità del sistema operativo, eseguendo la scansione ogni volta che esegui il push di un'immagine in Container Registry o Artifact Registry. L'abilitazione di questa API abilita inoltre le analisi dei pacchetti di linguaggio per rilevare le vulnerabilità di Go e Java.

L'API On-Demand Scanning ti consente di eseguire la scansione delle immagini archiviate localmente sul tuo computer o da remoto in Container Registry o Artifact Registry. Questo ti offre un controllo granulare sui container che vuoi analizzare alla ricerca di vulnerabilità. Puoi utilizzare la scansione on demand per scansionare le immagini nella pipeline CI/CD prima di decidere se archiviarle in un registro.

Cosa imparerai a fare

In questo lab imparerai a:

  • Creare immagini con Cloud Build
  • Utilizza Artifact Registry per i container
  • Utilizza l'analisi automatica delle vulnerabilità
  • Configura la scansione on demand
  • Aggiungi la scansione delle immagini in CICD in Cloud Build

2. Configurazione e requisiti

Configurazione dell'ambiente autogestito

  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 progetto è il nome visualizzato dei partecipanti del progetto. Si tratta di una stringa di caratteri non utilizzata dalle API di Google. Puoi aggiornarla in qualsiasi momento.
  • L'ID progetto è univoco in tutti i progetti Google Cloud ed è immutabile (non può essere modificato dopo essere stato impostato). La console Cloud genera automaticamente una stringa univoca. di solito non ti importa cosa sia. Nella maggior parte dei codelab, dovrai fare riferimento all'ID progetto (in genere è identificato come PROJECT_ID). Se l'ID generato non ti soddisfa, puoi generarne un altro casuale. In alternativa, puoi provarne una personalizzata per verificare se è disponibile. Non può essere modificato dopo questo passaggio e rimarrà 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. Eseguire questo codelab non dovrebbe costare molto. Per arrestare le risorse in modo da non incorrere in fatturazione al termine di 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$.

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 

3. Creazione di immagini con Cloud Build

In questa sezione creerai una pipeline di build automatizzata che creerà l'immagine container, la analizzerai e valuterai i risultati. Se non vengono rilevate vulnerabilità CRITICHE, l'immagine verrà inviata al repository. Se vengono trovate vulnerabilità CRITICAL, la build non riesce e viene chiusa.

Fornisci 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"

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 denominato 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 la pipeline di Cloud Build

Il comando seguente creerà nella tua directory un file cloudbuild.yaml che verrà utilizzato per il processo automatizzato. Per questo esempio i passaggi sono limitati al processo di creazione del container. Nella pratica, tuttavia, dovresti includere istruzioni e test specifici per l'applicazione in aggiunta ai passaggi del container.

Crea il file con il comando seguente.

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: ['-']


EOF

Esegui la pipeline CI

Invia la build per l'elaborazione

gcloud builds submit

Rivedi i dettagli della build

Una volta avviato il processo di compilazione, controlla l'avanzamento nella dashboard di Cloud Build.

  1. Apri Cloud Build nella console Cloud
  2. Fai clic sulla build per visualizzarne i contenuti

4. Artifact Registry per container

Crea repository Artifact Registry

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

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

Aggiorna la pipeline di Cloud Build

Modifica la pipeline di compilazione per eseguire il push dell'immagine risultante in Artifact Registry

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: ['-']

# push 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']

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

Esegui la pipeline CI

Invia la build per l'elaborazione

gcloud builds submit

5. Analisi automatizzata delle vulnerabilità

La scansione degli artefatti 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 esaminerai l'immagine che hai appena creato e di cui hai eseguito il push su Artifact Registry ed esplorerai i risultati relativi alle vulnerabilità.

Rivedi dettagli immagine

Una volta completata la procedura di compilazione precedente, controlla l'immagine e i risultati relativi alle vulnerabilità nella dashboard di Artifact Registry.

  1. Apri Artifact Registry nella console Cloud
  2. Fai clic sull'artefatto-scanning-repo per visualizzare i contenuti
  3. Fai clic sui dettagli dell'immagine
  4. Fai clic sull'ultima sintesi 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

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

6. Scansione on demand

Esistono diversi scenari in cui potrebbe essere necessario 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 agire sui risultati.

Crea un'immagine

In questo passaggio utilizzerai il 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 dell'immagine. I risultati della scansione vengono archiviati in un server di metadati. Il job viene completato con una 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

Rivedi 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à nell'immagine.

Segnala problemi critici

È raro che gli esseri umani utilizzino direttamente i dati memorizzati 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

7. Scansione in CICD con Cloud Build

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"

Aggiorna 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 comando seguente.

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 le interruzioni della build quando viene rilevata una vulnerabilità di gravità CRITICA.

gcloud builds submit

Rivedi errore build

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

Esamina l'errore della build 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.

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

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 valida

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

gcloud builds submit

Esamina la riuscita della compilazione

La build che hai appena inviato avrà esito positivo perché l'immagine aggiornata non contiene vulnerabilità CRITICAL.

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 sull'artefatto-scanning-repo per visualizzare i contenuti
  3. Fai clic sui dettagli dell'immagine
  4. Fai clic sull'ultima sintesi della tua immagine
  5. Fai clic sulla scheda Vulnerabilità per l'immagine.

8. Complimenti!

Complimenti, hai completato il codelab.

Argomenti trattati:

  • Creazione di immagini con Cloud Build
  • Artifact Registry per container
  • Analisi automatizzata delle vulnerabilità
  • Scansione on demand
  • Scansione in CICD con Cloud Build

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.

Ultimo aggiornamento: 21/03/23