Sécuriser les builds de conteneurs

Sécuriser les builds de conteneurs

À propos de cet atelier de programmation

subjectDernière mise à jour : mars 23, 2023
account_circleRédigé par Christopher Grant

1. Introduction

ead1609267034bf7.png

Les vulnérabilités logicielles sont des faiblesses qui peuvent entraîner une défaillance accidentelle du système ou fournir à des acteurs malintentionnés un moyen de compromettre votre logiciel. Container Analysis propose deux types d'analyse de l'OS pour détecter les failles dans les conteneurs:

  • L'API On-Demand Scanning vous permet d'analyser manuellement les images de conteneurs à la recherche de failles de système d'exploitation, soit localement sur votre ordinateur, soit à distance dans Container Registry ou Artifact Registry.
  • L'API Container Scanning vous permet d'automatiser la détection des failles du système d'exploitation, en effectuant une analyse chaque fois que vous transférez une image vers Container Registry ou Artifact Registry. L'activation de cette API permet également d'analyser les packages de langage pour détecter les failles Go et Java.

L'API On-Demand Scanning vous permet d'analyser des images stockées localement sur votre ordinateur, ou à distance dans Container Registry ou Artifact Registry. Vous disposez ainsi d'un contrôle précis sur les conteneurs pour lesquels vous souhaitez analyser les failles. Vous pouvez utiliser l'analyse à la demande pour analyser les images de votre pipeline CI/CD avant de décider de les stocker dans un registre.

Points abordés

Dans cet atelier, vous allez apprendre à réaliser les opérations suivantes :

  • Créer des images avec Cloud Build
  • Utiliser Artifact Registry pour les conteneurs
  • Utiliser l'analyse automatisée des failles
  • Configurer l'analyse à la demande
  • Ajouter l'analyse d'images dans la CI/CD dans Cloud Build

2. Préparation

Configuration de l'environnement d'auto-formation

  1. 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.)

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 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.
  1. 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 $.

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

3. Créer des images avec Cloud Build

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


EOF

Exécuter le pipeline CI

Envoyer la compilation pour traitement

gcloud builds submit

Vérifier les informations sur le build

Une fois le processus de compilation lancé, examinez la progression dans le tableau de bord Cloud Build.

  1. Ouvrez Cloud Build dans la console Cloud.
  2. Cliquez sur la compilation pour afficher son contenu

4. Artifact Registry pour les conteneurs

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

Mettre à jour le pipeline Cloud Build

Modifier votre pipeline de compilation pour transférer l'image obtenue vers 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

Exécuter le pipeline CI

Envoyer la compilation pour traitement

gcloud builds submit

5. Analyse automatique des failles

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 examiner l'image que vous venez de créer et de transférer vers Artifact Registry, et d'explorer les résultats des failles.

Examiner les détails de l'image

Une fois le processus de compilation précédent terminé, examinez l'image et les résultats de failles dans le tableau de bord Artifact Registry.

  1. Ouvrez Artifact Registry dans la console Cloud
  2. Cliquez sur artifact-scanning-repo pour afficher le contenu
  3. Cliquez sur les détails de l'image.
  4. Cliquez sur le dernier condensé de votre image.
  5. 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.

361be7b3bf293fca.png

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.

6. Recherche à la demande

Il existe différents scénarios dans lesquels vous pouvez avoir besoin d'effectuer 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

7. Analyser des données en CI/CD avec Cloud Build

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"

Mettre à jour 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

  1. Ouvrez Artifact Registry dans la console Cloud
  2. Cliquez sur artifact-scanning-repo pour afficher le contenu
  3. Cliquez sur les détails de l'image.
  4. Cliquez sur le dernier condensé de votre image.
  5. Cliquez sur l'onglet des failles de l'image.

8. Félicitations !

Félicitations, vous avez terminé cet atelier de programmation.

Points abordés

  • Créer des images avec Cloud Build
  • Artifact Registry pour les conteneurs
  • Analyse automatique des failles
  • Recherche à la demande
  • Analyser des données en CI/CD avec Cloud Build

Étapes suivantes :

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.

Dernière mise à jour: 21/03/2023