1. Introduction
Container Analysis fournit une analyse des failles et un stockage de métadonnées pour les conteneurs. Le service d'analyse effectue des analyses des failles sur les images dans Artifact Registry et Container Registry, puis stocke les métadonnées obtenues et les met à disposition via une API. Le stockage de métadonnées vous permet de stocker des informations provenant de différentes sources, y compris l'analyse des failles, les services Google Cloud et les fournisseurs tiers.
L'analyse des failles peut s'effectuer automatiquement ou à la demande:
- Lorsque l'analyse automatique est activée, l'analyse se déclenche automatiquement chaque fois que vous transférez une nouvelle image vers Artifact Registry ou Container Registry. Les informations sur les failles sont mises à jour en permanence lorsque de nouvelles failles sont découvertes.
- Lorsque l'analyse à la demande est activée, vous devez exécuter une commande pour analyser une image locale ou une image dans Artifact Registry ou Container Registry. L'analyse à la demande vous offre une certaine flexibilité concernant l'analyse des conteneurs. Par exemple, vous pouvez analyser une image créée localement et corriger les failles avant de la stocker dans un registre. Les résultats sont disponibles jusqu'à 48 heures après la fin de l'analyse. Les informations sur les failles ne sont pas mises à jour après l'analyse.
Grâce à Container Analysis intégré à votre pipeline CI/CD, vous pouvez prendre des décisions en fonction de ces métadonnées. Par exemple, vous pouvez utiliser l'autorisation binaire pour créer des stratégies de déploiement qui n'autorisent que les déploiements d'images conformes provenant de registres de confiance.
Points abordés
- Activer l'analyse automatique
- Effectuer une analyse à la demande
- Intégrer l'analyse dans un pipeline de compilation
- Signer les images approuvées
- Utiliser les contrôleurs d'admission GKE pour bloquer les images
- Configurer GKE pour n'autoriser que les images approuvées signées
2. Préparation
Configuration de l'environnement d'auto-formation
- Connectez-vous à la console Google Cloud, puis créez un projet ou réutilisez un projet existant. (Si vous ne possédez pas encore de compte Gmail ou Google Workspace, vous devez en créer un.)
- Le nom du projet est le nom à afficher pour les participants au projet. Il s'agit d'une chaîne de caractères non utilisée par les API Google. Vous pouvez le modifier à tout moment.
- L'ID du projet est unique parmi tous les projets Google Cloud et non modifiable une fois défini. La console Cloud génère automatiquement une chaîne unique. généralement, vous ne vous souciez
pas de ce que c’est. Dans la plupart des ateliers de programmation, vous devrez référencer l'ID du projet (il est généralement identifié comme
PROJECT_ID
). Si l'ID généré ne vous convient pas, vous pouvez en générer un autre au hasard. Vous pouvez également essayer la vôtre pour voir si elle est disponible. Il ne peut pas être modifié après cette étape et restera actif pendant toute la durée du projet. - Pour votre information, il existe une troisième valeur, le numéro de projet, utilisé par certaines API. Pour en savoir plus sur ces trois valeurs, consultez la documentation.
- Vous devez ensuite activer la facturation dans la console Cloud pour utiliser les ressources/API Cloud. L'exécution de cet atelier de programmation est très peu coûteuse, voire sans frais. Pour arrêter les ressources afin d'éviter que des frais ne vous soient facturés au-delà de ce tutoriel, vous pouvez supprimer les ressources que vous avez créées ou l'ensemble du projet. Les nouveaux utilisateurs de Google Cloud peuvent participer au programme d'essai gratuit pour bénéficier d'un crédit de 300 $.
Démarrer l'éditeur Cloudshell
Cet atelier a été conçu et testé pour être utilisé avec l'éditeur Google Cloud Shell. Pour accéder à l'éditeur,
- Accédez à votre projet Google à l'adresse https://console.cloud.google.com.
- En haut à droite, cliquez sur l'icône de l'éditeur Cloud Shell.
- Un nouveau volet s'ouvre au bas de la fenêtre.
Configuration de l'environnement
Dans Cloud Shell, définissez l'ID et le numéro de votre projet. Enregistrez-les en tant que variables PROJECT_ID
et PROJECT_ID
.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
--format='value(projectNumber)')
Activer les services
Activez tous les services nécessaires :
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
Créer un dépôt Artifact Registry
Dans cet atelier, vous allez stocker et analyser vos images à l'aide d'Artifact Registry. Créez le dépôt à l'aide de la commande suivante.
gcloud artifacts repositories create artifact-scanning-repo \
--repository-format=docker \
--location=us-central1 \
--description="Docker repository"
Configurez Docker pour utiliser vos identifiants gcloud lorsque vous accédez à Artifact Registry.
gcloud auth configure-docker us-central1-docker.pkg.dev
3. Analyse automatisée
L'analyse des artefacts se déclenche automatiquement chaque fois que vous transférez une nouvelle image vers Artifact Registry ou Container Registry. Les informations sur les failles sont mises à jour en permanence lorsque de nouvelles failles sont découvertes. Dans cette section, vous allez transférer une image vers Artifact Registry et explorer les résultats.
Créer un répertoire professionnel et y accéder
mkdir vuln-scan && cd vuln-scan
Définir un exemple d'image
Créez un fichier nommé Dockerfile avec le contenu suivant.
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
Créez un fichier nommé main.py avec le contenu suivant :
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
Créer l'image et la transférer en RA
Utilisez Cloud Build pour créer votre conteneur et le transférer automatiquement vers Artifact Registry. Notez le tag bad
sur l'image. Cela vous aidera à l'identifier pour les étapes suivantes.
gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad
Examiner les détails de l'image
Une fois le processus de compilation terminé, examinez l'image et les résultats de failles dans le tableau de bord Artifact Registry.
- Ouvrez Artifact Registry dans la console Cloud
- Cliquez sur artifact-scanning-repo pour afficher le contenu
- Cliquez sur les détails de l'image.
- Cliquez sur le dernier condensé de votre image.
- Une fois l'analyse terminée, cliquez sur l'onglet des failles de l'image.
Dans l'onglet des failles, vous pouvez voir les résultats de l'analyse automatique de l'image que vous venez de créer.
L'automatisation de l'analyse est activée par défaut. Explorez les paramètres d'Artifact Registry pour découvrir comment activer et désactiver l'analyse automatique.
4. On-Demand Scanning
Il existe différents scénarios dans lesquels vous pouvez avoir besoin d'exécuter une analyse avant de transférer l'image vers un dépôt. Par exemple, un développeur de conteneurs peut analyser une image et résoudre les problèmes avant de transmettre du code au contrôle source. Dans l'exemple ci-dessous, vous allez créer et analyser l'image localement avant d'agir sur les résultats.
Créer une image
Au cours de cette étape, vous allez utiliser un Dockerfile local pour créer l'image dans votre cache local.
docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image .
Scanner l'image
Une fois l'image créée, demandez une analyse. Les résultats de l'analyse sont stockés sur un serveur de métadonnées. La tâche se termine avec un emplacement des résultats dans le serveur de métadonnées.
gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--format="value(response.scan)" > scan_id.txt
Examiner le fichier de sortie
Prenez quelques instants pour examiner le résultat de l'étape précédente, stocké dans le fichier scan_id.txt. Notez l'emplacement du rapport contenant les résultats de l'analyse sur le serveur de métadonnées.
cat scan_id.txt
Examiner les résultats d'analyse détaillés
Pour afficher les résultats réels de l'analyse, utilisez la commande list-vulnerabilities
à l'emplacement du rapport indiqué dans le fichier de sortie.
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt)
Le résultat contient une quantité importante de données sur toutes les failles présentes dans l'image.
Signaler des problèmes critiques
Il est rare que les humains utilisent directement les données stockées dans le rapport. Les résultats sont généralement utilisés par un processus automatisé. Utilisez les commandes ci-dessous pour lire les détails du rapport et consigner les failles CRITICAL détectées.
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
Le résultat de cette commande sera
Failed vulnerability check for CRITICAL level
5. Analyse du pipeline de compilation
Dans cette section, vous allez créer un pipeline de compilation automatisé qui va compiler votre image de conteneur, l'analyser, puis évaluer les résultats. Si aucune faille CRITICAL n'est détectée, l'image est transférée dans le dépôt. Si des failles CRITICAL sont détectées, la compilation échouera et se fermera.
Fournir un accès au compte de service Cloud Build
Cloud Build requiert des droits pour accéder à l'API d'analyse à la demande. Accordez l'accès à l'aide des commandes suivantes.
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"
Créer le pipeline Cloud Build
La commande suivante crée un fichier cloudbuild.yaml dans votre répertoire qui sera utilisé par le processus automatisé. Dans cet exemple, les étapes sont limitées au processus de compilation du conteneur. En pratique, vous devez toutefois inclure des tests et des instructions spécifiques à l'application en plus des étapes relatives au conteneur.
Créez le fichier à l'aide de la commande suivante.
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
Exécuter le pipeline CI
Envoyez la compilation pour traitement afin de vérifier qu'elle ne fonctionne plus lorsqu'une faille de gravité critique est détectée.
gcloud builds submit
Examiner l'échec de la compilation
La compilation que vous venez d'envoyer échouera, car l'image contient des failles CRITICAL.
Examinez l'échec de la compilation sur la page Historique Cloud Build.
Corriger la faille
Mettez à jour le Dockerfile pour utiliser une image de base ne contenant pas de failles CRITICAL.
Écrasez le Dockerfile pour utiliser l'image Debian 10 avec la commande suivante :
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
Exécuter le processus CI avec la bonne image
Envoyez la compilation pour traitement afin de vérifier qu'elle aboutit si aucune faille de gravité critique n'est détectée.
gcloud builds submit
Évaluer le succès de la compilation
Le build que vous venez d'envoyer va réussir, car l'image mise à jour ne présente aucune faille CRITICAL.
Examinez la réussite de la compilation sur la page Historique Cloud Build.
Examiner les résultats de l'analyse
Examiner l'image correcte dans Artifact Registry
- Ouvrez Artifact Registry dans la console Cloud
- Cliquez sur artifact-scanning-repo pour afficher le contenu
- Cliquez sur les détails de l'image.
- Cliquez sur le dernier condensé de votre image.
- Cliquez sur l'onglet des failles de l'image.
6. Signature d'images
Créer une note du certificateur
Une note du certificateur est simplement un petit bit de données qui sert d’étiquette pour le type de signature appliqué. Par exemple, une note peut indiquer une analyse des failles, tandis qu'une autre peut être utilisée pour l'approbation du contrôle qualité. La note sera référencée lors du processus de signature.
Créer une note
cat > ./vulnz_note.json << EOM
{
"attestation": {
"hint": {
"human_readable_name": "Container Vulnerabilities attestation authority"
}
}
}
EOM
Stocker la note
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}"
Vérifier la note
curl -vvv \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
Créer un certificateur
Les certificateurs sont utilisés pour effectuer le processus de signature d'image et attachent une occurrence de la note à l'image pour une vérification ultérieure. Créez le certificateur pour une utilisation ultérieure.
Créer un certificateur
ATTESTOR_ID=vulnz-attestor
gcloud container binauthz attestors create $ATTESTOR_ID \
--attestation-authority-note=$NOTE_ID \
--attestation-authority-note-project=${PROJECT_ID}
Valider le certificateur
gcloud container binauthz attestors list
Notez que la dernière ligne indique NUM_PUBLIC_KEYS: 0
. Vous fournirez des clés lors d'une prochaine étape
Notez également que Cloud Build crée automatiquement le certificateur built-by-cloud-build
dans votre projet lorsque vous exécutez une compilation qui génère des images. La commande ci-dessus renvoie donc deux certificateurs, vulnz-attestor
et built-by-cloud-build
. Une fois les images créées, Cloud Build signe et crée automatiquement des attestations pour celles-ci.
Ajouter un rôle IAM
Le compte de service de l'autorisation binaire doit disposer de droits pour afficher les notes d'attestation. Accordez l'accès à l'aide de l'appel d'API suivant :
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
Utiliser le fichier pour créer la stratégie 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"
Ajouter une clé KMS
Le certificateur a besoin de clés cryptographiques pour joindre la note et fournir des signatures vérifiables. Au cours de cette étape, vous allez créer et stocker des clés dans KMS pour que Cloud Build puisse y accéder ultérieurement.
Commencez par ajouter des variables d'environnement pour décrire la nouvelle clé
KEY_LOCATION=global
KEYRING=binauthz-keys
KEY_NAME=codelab-key
KEY_VERSION=1
Créer un trousseau pour contenir un ensemble de clés
gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"
Créer une paire de clés de signature asymétrique pour le certificateur
gcloud kms keys create "${KEY_NAME}" \
--keyring="${KEYRING}" --location="${KEY_LOCATION}" \
--purpose asymmetric-signing \
--default-algorithm="ec-sign-p256-sha256"
Votre clé doit apparaître sur la page KMS de la console Google Cloud.
À présent, associez la clé à votre certificateur via la commande 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}"
Si vous imprimez à nouveau la liste des autorités, vous devriez maintenant voir une clé enregistrée:
gcloud container binauthz attestors list
Créer une attestation signée
À ce stade, vous disposez des fonctionnalités configurées qui vous permettent de signer des images. Utilisez le certificateur que vous avez créé précédemment pour signer l'image de conteneur avec laquelle vous travaillez
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)')
Vous pouvez maintenant utiliser gcloud pour créer votre attestation. La commande récupère simplement les détails de la clé que vous souhaitez utiliser pour la signature, ainsi que l'image de conteneur spécifique que vous souhaitez approuver.
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}"
Dans le cas de Container Analysis, cela crée une occurrence et l'associe à la note du certificateur. Pour vous assurer que tout a fonctionné comme prévu, vous pouvez lister vos attestations
gcloud container binauthz attestations list \
--attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}
7. Signer avec Cloud Build
Vous avez activé la signature d'image et utilisé manuellement le certificateur pour signer votre exemple d'image. En pratique, vous devrez appliquer des attestations au cours de processus automatisés tels que les pipelines CI/CD.
Dans cette section, vous allez configurer Cloud Build pour attester automatiquement les images.
Rôles
Attribuez le rôle "Lecteur des certificateurs de l'autorisation binaire" au compte de service Cloud Build :
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/binaryauthorization.attestorsViewer
Attribuez le rôle "Signataire/Validateur de CryptoKeys Cloud KMS" au compte de service Cloud Build (signature basée sur KMS) :
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/cloudkms.signerVerifier
Attribuez le rôle "Agent d'association de notes Container Analysis" au compte de service Cloud Build :
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/containeranalysis.notes.attacher
Préparer l'étape de compilation personnalisée Cloud Build
Vous allez utiliser une étape de compilation personnalisée dans Cloud Build pour simplifier le processus d'attestation. Google propose cette étape de compilation personnalisée qui contient des fonctions d'assistance pour simplifier le processus. Avant d'être utilisé, le code de l'étape de compilation personnalisée doit être intégré à un conteneur et transféré vers Cloud Build. Pour ce faire, exécutez les commandes suivantes:
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
Ajouter une étape de signature à votre fichier cloudbuild.yaml
Au cours de cette étape, vous allez ajouter l'étape d'attestation au pipeline Cloud Build que vous avez créé précédemment.
- Examinez la nouvelle étape que vous allez ajouter.
Avis uniquement. Ne pas copier
#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'
- Remplacez le fichier cloudbuild.yaml par le pipeline complet mis à jour.
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
Exécuter le build
gcloud builds submit
Examiner la compilation dans l'historique Cloud Build
Ouvrez la console Cloud sur la page Historique Cloud Build, puis examinez la dernière compilation et l'exécution réussie des étapes de compilation.
8. Règles concernant le contrôle des admissions
L'autorisation binaire est une fonctionnalité de GKE et de Cloud Run qui permet de valider des règles avant qu'une image de conteneur ne soit autorisée à s'exécuter. La validation s'exécute sur n'importe quelle requête d'exécution d'une image, que ce soit à partir d'un pipeline CI/CD approuvé ou lorsqu'un utilisateur tente manuellement de déployer une image. Cette fonctionnalité vous permet de sécuriser vos environnements d'exécution plus efficacement que les seules vérifications de pipeline CI/CD.
Pour comprendre cette fonctionnalité, vous allez modifier la stratégie GKE par défaut afin d'appliquer une règle d'autorisation stricte.
Créer le cluster GKE
Créez le cluster GKE :
gcloud beta container clusters create binauthz \
--zone us-central1-a \
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE
Autorisez Cloud Build à déployer sur ce cluster:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/container.developer"
Règle "Tout autoriser"
Vérifiez d'abord l'état de la règle par défaut et votre capacité à déployer n'importe quelle image
- Examiner les règles existantes
gcloud container binauthz policy export
- Notez que la règle d'application est définie sur
ALWAYS_ALLOW
evaluationMode: ALWAYS_ALLOW
- Déployez un exemple pour vérifier que vous pouvez déployer tout ce que vous voulez
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- Vérifier que le déploiement a fonctionné
kubectl get pods
La sortie suivante s'affiche :
- Supprimer le déploiement
kubectl delete pod hello-server
Règle "Tout refuser"
Modifiez maintenant la stratégie pour interdire toutes les images.
- Exporter la stratégie actuelle dans un fichier modifiable
gcloud container binauthz policy export > policy.yaml
- Modifier les règles
Dans un éditeur de texte, remplacez la valeur du mode d'évaluation ALWAYS_ALLOW par ALWAYS_DENY.
edit policy.yaml
Le fichier YAML de stratégie doit ressembler à ceci :
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_DENY enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
- Ouvrez le terminal, appliquez la nouvelle règle et attendez quelques secondes pour que la modification soit appliquée.
gcloud container binauthz policy import policy.yaml
- Tentative de déploiement de l'exemple de charge de travail
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- Échec du déploiement avec le message suivant
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
Rétablissez la règle pour tout autoriser
Avant de passer à la section suivante, assurez-vous d'annuler les modifications apportées aux règles
- Modifier les règles
Dans un éditeur de texte, remplacez la valeur du mode d'évaluation ALWAYS_DENY par ALWAYS_ALLOW.
edit policy.yaml
Le fichier YAML de stratégie doit ressembler à ceci :
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_ALLOW enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
- Appliquer la règle annulée
gcloud container binauthz policy import policy.yaml
9. Bloquer les failles dans GKE
Dans cette section, vous allez combiner ce que vous avez appris jusqu'à présent en implémentant un pipeline CI/CD avec Cloud Build qui analyse les images, puis recherche les failles avant de signer l'image et de tenter de la déployer. GKE utilisera l'autorisation binaire pour vérifier que l'image possède une signature issue de l'analyse des failles avant d'autoriser l'exécution de l'image.
Mettre à jour la stratégie GKE pour exiger une attestation
Exiger que les images soient signées par votre certificateur en ajoutant clusterAdmissionRules à votre règle GKE BinAuth
Remplacez la règle par la configuration mise à jour à l'aide de la commande ci-dessous.
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
Appliquer la règle
gcloud beta container binauthz policy import binauth_policy.yaml
Tentative de déploiement de l'image non signée
Créez un descripteur de déploiement pour l'application que vous avez créée précédemment à l'aide de la commande suivante. L'image utilisée ici est l'image que vous avez créée précédemment. Elle contient des failles critiques et NE contient PAS l'attestation signée.
Les contrôleurs d'admission GKE doivent connaître l'image exacte à déployer pour valider la signature de manière cohérente. Pour ce faire, vous devez utiliser le condensé de l'image et un simple tag.
Obtenir le condensé de l'image incorrecte
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)')
Utiliser le condensé dans la configuration 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
Essayer de déployer l'application sur GKE
kubectl apply -f deploy.yaml
Examinez la charge de travail dans la console et notez l'erreur indiquant que le déploiement a été refusé:
No attestations found that were valid and signed by a key trusted by the attestor
Déployer une image signée
Obtenir le condensé de l'image incorrecte
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)')
Utiliser le condensé dans la configuration 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
Déployer l'application sur GKE
kubectl apply -f deploy.yaml
Examinez la charge de travail dans la console et notez le déploiement de l'image.
10. Félicitations !
Félicitations, vous avez terminé cet atelier de programmation.
Points abordés
- Activer l'analyse automatique
- Effectuer une analyse à la demande
- Intégrer l'analyse dans un pipeline de compilation
- Signer les images approuvées
- Utiliser les contrôleurs d'admission GKE pour bloquer les images
- Configurer GKE pour n'autoriser que les images approuvées signées
Étapes suivantes :
- Sécuriser les déploiements d'images sur Cloud Run et Google Kubernetes Engine | Documentation Cloud Build
- Démarrage rapide: Configurer une stratégie d'autorisation binaire avec GKE | Google Cloud
Effectuer un nettoyage
Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez chaque ressource individuellement.
Supprimer le projet
Le moyen le plus simple d'empêcher la facturation est de supprimer le projet que vous avez créé pour ce tutoriel.