1. Introduzione
Container Analysis fornisce analisi delle vulnerabilità e 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 il consumo tramite un'API. L'archiviazione dei metadati consente di archiviare informazioni provenienti da diverse fonti, tra cui l'analisi delle vulnerabilità, servizi Google Cloud e provider di terze parti.
L'analisi delle vulnerabilità può avvenire automaticamente o on demand:
- Se è abilitata la scansione automatica, l'analisi si attiva automaticamente ogni volta che esegui il push di una nuova immagine su Artifact Registry o Container Registry. Le informazioni sulle vulnerabilità vengono aggiornate continuamente quando vengono scoperte nuove vulnerabilità.
- Quando l'opzione Scansione on demand è abilitata, devi eseguire un comando per scansionare un'immagine locale o un'immagine in Artifact Registry o Container Registry. La scansione on demand offre flessibilità durante l'analisi dei container. Ad esempio, puoi analizzare un'immagine creata in locale e correggere le vulnerabilità prima di archiviarla in un registro. I risultati dell'analisi sono disponibili per un massimo di 48 ore dopo il completamento dell'analisi e le informazioni sulle vulnerabilità non vengono aggiornate dopo l'analisi.
Con Container Analysis integrata 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 il deployment solo per immagini conformi provenienti da registri attendibili.
Cosa imparerai a fare
- Come attivare la scansione automatica
- Come eseguire la scansione on demand
- Come integrare la scansione in una pipeline di build
- Come firmare le immagini approvate
- Come utilizzare i controller di ammissione GKE per bloccare le immagini
- Come configurare GKE in modo da consentire solo le immagini approvate firmate
2. Configurazione e requisiti
Configurazione dell'ambiente autogestito
- 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.
- 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 informazione, c'è un terzo valore, un numero di progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
- Successivamente, dovrai abilitare la fatturazione nella console Cloud per utilizzare risorse/API Cloud. Eseguire questo codelab non dovrebbe costare molto. Per arrestare le risorse in modo da non incorrere in fatturazione oltre questo tutorial, puoi eliminare le risorse che hai creato o eliminare l'intero progetto. I nuovi utenti di Google Cloud sono idonei al programma prova senza costi di 300$.
Avvia editor Cloudshell
Questo lab è stato progettato e testato per l'utilizzo con l'editor di Google Cloud Shell. Per accedere all'editor,
- accedi al tuo progetto Google all'indirizzo https://console.cloud.google.com.
- Nell'angolo in alto a destra, fai clic sull'icona dell'editor di Cloud Shell
- Si aprirà un nuovo riquadro nella parte inferiore della finestra
Configurazione dell'ambiente
In Cloud Shell, imposta l'ID 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
Abilita 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 repository Artifact Registry
In questo lab utilizzerai Artifact Registry per archiviare e scansionare le tue 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 per utilizzare le tue credenziali gcloud durante l'accesso ad Artifact Registry.
gcloud auth configure-docker us-central1-docker.pkg.dev
3. Scansione automatica
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 eseguirai il push di un'immagine in Artifact Registry ed esplorerai i risultati.
Crea e modifica in una directory di lavoro
mkdir vuln-scan && cd vuln-scan
Definisci un'immagine di esempio
Crea un file denominato Dockerfile con il contenuto seguente.
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 ed esegui il push dell'immagine in AR
Utilizza Cloud Build per creare il container ed eseguirne automaticamente il push ad Artifact Registry. Osserva il tag bad
nell'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 dettagli immagine
Al termine del processo di compilazione, esamina l'immagine e i risultati della vulnerabilità nella dashboard di Artifact Registry.
- Apri Artifact Registry nella console Cloud
- Fai clic sull'artefatto-scanning-repo per visualizzare i contenuti
- Fai clic sui dettagli dell'immagine
- Fai clic sull'ultima sintesi della tua immagine
- Al termine della scansione, fai clic sulla scheda Vulnerabilità relativa all'immagine
Nella scheda Vulnerabilità potrai vedere i risultati della scansione automatica dell'immagine che hai appena creato.
La scansione automatica è 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 potrebbe essere necessario eseguire una scansione prima di eseguire il push dell'immagine in un repository. Ad esempio, uno sviluppatore di container potrebbe analizzare un'immagine e risolvere i problemi prima di eseguire il push del codice al 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
Rivedi l'output del passaggio precedente che era memorizzato nel file scan_id.txt. Osserva la posizione del report dei risultati della scansione nel server dei metadati.
cat scan_id.txt
Esamina 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. Usa i comandi seguenti per leggere i dettagli del report e registrare se sono state trovate vulnerabilità CRITICAL
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 pipeline di build
In questa sezione creerai una pipeline di build automatizzata che creerà l'immagine container, la analizzerai e valuterai i risultati. Se non vengono trovate vulnerabilità CRITICAL, verrà eseguito il push dell'immagine nel 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"
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: ['-']
#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 quando viene rilevata una vulnerabilità di gravità CRITICA.
gcloud builds submit
Rivedi errore build
La build che hai appena inviato non riuscirà perché l'immagine contiene vulnerabilità CRITICHE.
Esamina l'errore della build nella pagina Cronologia di Cloud Build
Correggi la vulnerabilità
Aggiorna il Dockerfile in modo che utilizzi un'immagine di base che non contenga vulnerabilità CRITICAL.
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 abbia esito positivo quando non vengono rilevate vulnerabilità con gravità CRITICA.
gcloud builds submit
Revisiona il successo della build
La build che hai appena inviato avrà esito positivo perché l'immagine aggiornata non contiene vulnerabilità CRITICAL.
Esamina l'esito della build nella pagina Cronologia di Cloud Build
Esamina i risultati dell'analisi
Esamina l'immagine corretta in Artifact Registry
- Apri Artifact Registry nella console Cloud
- Fai clic sull'artefatto-scanning-repo per visualizzare i contenuti
- Fai clic sui dettagli dell'immagine
- Fai clic sull'ultima sintesi della tua immagine
- Fai clic sulla scheda Vulnerabilità relativa all'immagine
6. Firma delle immagini
Crea una nota attestatore
Una nota attestatore è semplicemente un piccolo dato che funge da etichetta per il tipo di firma applicata. Ad esempio, una nota potrebbe indicare un'analisi delle vulnerabilità, mentre un'altra potrebbe essere utilizzata per la firma del QA. Verrà fatto riferimento alla nota durante il processo di firma.
Creare una nota
cat > ./vulnz_note.json << EOM
{
"attestation": {
"hint": {
"human_readable_name": "Container Vulnerabilities attestation authority"
}
}
}
EOM
Archivia 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 l'effettivo processo di firma dell'immagine e allegheranno un'occorrenza della nota all'immagine per una 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. Il comando riportato sopra restituisce quindi due attestatori, vulnz-attestor
e built-by-cloud-build
. Una volta create correttamente le immagini, Cloud Build firma e crea automaticamente le attestazioni.
Aggiunta di un ruolo IAM
L'account di servizio di Autorizzazione binaria dovrà disporre 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 archivierai le chiavi in KMS affinché Cloud Build possa 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
Crea un keyring per contenere un set 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à, a questo punto 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 creato in precedenza per firmare l'immagine container che stai utilizzando
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 la tua attestazione. Il comando inserisce semplicemente i dettagli della chiave che vuoi utilizzare per la firma e l'immagine container 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}"
Nei termini di Container Analysis, viene creata una nuova occorrenza che viene allegata alla nota dell'attestatore. Per assicurarti che tutto abbia funzionato 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 abilitato la firma dell'immagine e utilizzato manualmente l'attestatore per firmare la tua immagine di esempio. In pratica è consigliabile applicare le attestazioni durante i processi automatizzati, come le pipeline CI/CD.
In questa sezione configurerai Cloud Build per Attestare automaticamente le immagini
Ruoli
Aggiungi il ruolo Visualizzatore attestatore 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/Verificatore CryptoKey Cloud KMS 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 Autore associazione note di Container Analysis 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 della build personalizzata in Cloud Build per semplificare il processo di attestazione. Google fornisce questo passaggio di Creazione personalizzata che contiene funzioni helper per semplificare il processo. Prima dell'uso, il codice per il passaggio di build personalizzato deve essere incorporato in un container e sottoposto a push a Cloud Build. Per farlo, esegui questi 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 al file cloudbuild.yaml
In questo passaggio aggiungerai il passaggio di attestazione alla pipeline Cloud Build che hai creato in precedenza.
- Rivedi il nuovo passaggio che stai aggiungendo.
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'
- 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
Rivedi la build nella cronologia di Cloud Build
Apri la pagina Cronologia di Cloud Build nella console Cloud e rivedi l'ultima build e la riuscita esecuzione dei relativi passaggi.
8. Norme sul controllo di ammissione
Autorizzazione binaria è una funzionalità di GKE e Cloud Run che offre la possibilità di convalidare le regole prima che sia consentita l'esecuzione di un'immagine container. La convalida viene eseguita su qualsiasi richiesta di esecuzione di un'immagine, che si tratti di una pipeline CI/CD attendibile o di un utente che tenta manualmente di eseguire il deployment di un'immagine. Questa funzionalità consente di proteggere gli ambienti di runtime in modo più efficace rispetto ai soli controlli della pipeline CI/CD.
Per comprendere questa funzionalità modificherai il criterio GKE predefinito in modo da 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"
Consenti tutti i criteri
Prima verifica lo stato del criterio predefinito e la tua possibilità di eseguire il deployment di qualsiasi immagine
- Esamina il criterio esistente
gcloud container binauthz policy export
- Tieni presente che il criterio di applicazione è impostato su
ALWAYS_ALLOW
evaluationMode: ALWAYS_ALLOW
- Esegui il deployment di Sample per verificare che sia possibile eseguire il deployment di qualsiasi cosa
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- Verifica che il deployment sia stato eseguito correttamente
kubectl get pods
Verrà visualizzato l'output seguente
- Elimina deployment
kubectl delete pod hello-server
Nega tutti i criteri
Ora aggiorna la norma per non consentire tutte le immagini.
- Esporta il criterio corrente in un file modificabile
gcloud container binauthz policy export > policy.yaml
- Modifica la norma
In un editor di testo, cambia il valore assessmentMode da ALWAYS_ALLOW a ALWAYS_DENY.
edit policy.yaml
Il file YAML del criterio dovrebbe essere visualizzato come segue:
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_DENY enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
- Apri Terminale, applica il nuovo criterio e attendi alcuni secondi per la propagazione della modifica
gcloud container binauthz policy import policy.yaml
- Prova il deployment del carico di lavoro di esempio
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- Il deployment ha esito negativo 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 tutte
Prima di passare alla sezione successiva, assicurati di annullare le modifiche alle norme
- Modifica la norma
In un editor di testo, modifica il valore assessmentMode da ALWAYS_DENY a ALWAYS_ALLOW.
edit policy.yaml
Il file YAML del criterio dovrebbe essere visualizzato come segue:
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_ALLOW enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
- Applica il criterio ripristinato
gcloud container binauthz policy import policy.yaml
9. Blocca le vulnerabilità in GKE
In questa sezione combinerai ciò che hai imparato finora implementando una pipeline CI/CD con Cloud Build che analizza le immagini, quindi verifica la presenza di vulnerabilità prima di firmare l'immagine e tentare di eseguire il deployment. GKE utilizzerà Autorizzazione binaria per confermare che l'immagine ha una firma dall'analisi delle vulnerabilità prima di consentire l'esecuzione dell'immagine.
Aggiorna il criterio GKE per richiedere l'attestazione
Richiedi che le immagini vengano firmate dall'attestatore aggiungendo clusterAdmissionRules al tuo criterio BinAuth GKE
Sovrascrivi 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 che hai creato in precedenza utilizzando il comando seguente. L'immagine utilizzata qui è quella che hai creato in precedenza, che contiene vulnerabilità critiche e NON contiene l'attestazione firmata.
I controller di ammissione GKE devono conoscere l'immagine esatta di cui eseguire il deployment per convalidare in modo coerente la firma. A questo scopo, dovrai utilizzare il digest dell'immagine e un tag semplice.
Ottieni il digest dell'immagine per l'immagine di scarsa qualità
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)')
Utilizza 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
Tentativo di eseguire il deployment dell'app su GKE
kubectl apply -f deploy.yaml
Esamina il carico di lavoro nella console e annota l'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 per l'immagine di scarsa qualità
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)')
Utilizza 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 carico di lavoro nella console e prendi nota del corretto deployment 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 build
- Come firmare le immagini approvate
- Come utilizzare i controller di ammissione GKE per bloccare le immagini
- Come configurare GKE in modo da consentire solo le immagini approvate firmate
Passaggi successivi
- Protezione dei deployment delle immagini in Cloud Run e Google Kubernetes Engine | Documentazione di Cloud Build
- Guida rapida: configura un criterio di Autorizzazione binaria con GKE | Google Cloud
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 è quello di eliminare il progetto che hai creato per il tutorial.