Stocker et vérifier ses images de container

Lecture 12 min. ‱


Table des matiĂšres

Bonjour Ă  toutes et tous

Aujourd’hui je vais ouvrir une boüte Pandore 🧐

Depuis quelques mois, je me suis plongĂ© profondĂ©ment dans l’écosystĂšme du cloud native, Docker, images, containers et Kubernetes.

Jusqu’à maintenant je ne m’étais pas rĂ©ellement prĂ©occupĂ© de la sĂ©curitĂ© de ce que je faisais.

Mes images Ă©taient basĂ©es sur les images officielles que l’on pouvait trouver sur docker hub et je les considĂ©rais comme sĂ©curisĂ©es.

Ce que je n’avais pas compris ou fait semblant de ne pas comprendre, c’est que les images sont une reprĂ©sentation figĂ©e de l’état d’un systĂšme de fichier. Et donc par consĂ©quent les failles de sĂ©curitĂ© ne sont pas corrigĂ©es, il faut sans cesse vĂ©rifier si de nouvelles images sont crĂ©es et encore on est complĂštement dĂ©pendant du bon vouloir des Ă©diteurs d’images pour les sĂ©curiser.

Dans cet article, je vais vous proposer deux maniĂšres de vĂ©rifier le niveau de sĂ©curitĂ© de vos images Docker. La premiĂšre mĂ©thode se fera sur le site Gilab.com et la deuxiĂšme via un projet open-source qui peut s’auto-hĂ©berger poussĂ© par VMware.

Pour chacune des deux maniĂšres je vais vous montrer comment les mettre en place, pour bĂ©nĂ©ficier d’une automatisation vĂ©rification des images qui seront poussĂ©s sur le registry Docker.

C’est parti ! :D

Méthode Gitlab.com

Gitlab propose un outil de vĂ©rification de containers et d’images directement intĂ©grĂ© au sytĂšme de CI.

Pour cela, il vous faut un compte sur gitlab.com, celui ci est gratuit et vous permet de bĂ©nĂ©ficier de fonctionnalitĂ©s avancĂ©es qui ne sont disponibles normalement que dans les paliers payants d’abonnements.

Dans ces fonctionnalitĂ©s nous avons par exemple, la visualisation des failles de sĂ©curitĂ© dans l’interface de contrĂŽle des merge-requests.

Je considĂšre que vous savez crĂ©er un projet sur Gitlab, dans le cas contraire la documentation est extrĂȘmement fournie.

Dans ce projet à la racine vous aller créer 2 fichiers

Dockerfile

FROM ubuntu:20.04

Ce sera celui qui sera utilisĂ© pour construire l’image que l’on dĂ©sire tester.

.gitlab-ci.yml

variables:
  DOCKER_DRIVER: overlay2

stages:
  - build
  - test

build:
  image: docker:stable
  stage: build
  services:
    - docker:19.03.12-dind
  variables:
    IMAGE: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
  script:
    - docker info
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
    - docker build -t $IMAGE .
    - docker push $IMAGE

include:
  - template: Container-Scanning.gitlab-ci.yml

Ce pipeline est composé de deux étapes:

L’étape de vĂ©rification est entiĂšrement contenue dans la ligne surlignĂ©e.

Elle inclue tout la logique du systÚme de contrÎle de sécurité.

Aujourd’hui celui-ci est basĂ© sur un projet nommĂ© Clair. Mais dans l’avenir si le systĂšme change, votre pipeline n’aura pas besoin d’ĂȘtre modifiĂ©.

Pour tester le systÚme, créez une branche peut importe le nom, je vais appeler la mienne dev.

Créez ensuite une merge-request de dev sur master.

Allez sur la branche dev

Modifiez le Dockerfile

FROM ubuntu

Puis committez les changements.

AprĂšs un petit moment vous devriez voir apparaĂźtre dans votre merge-request, une nouvelle ligne qui vous indique le nombre de failles.

Ici l’image busybox:latest ne contient ( et heureusement ) aucune failles de sĂ©curitĂ©s

Il est possible de visualiser le dĂ©tail de ces vulnĂ©rabilitĂ©s en cliquant sur le bouton “View full report”.

On peut essayer avec plusieurs images:

ubuntu:21.04

De mĂȘme, occupe vulnĂ©rabilitĂ© Ă  dĂ©plorer :D

ubuntu:20.04

On voit déjà quelques vulnérabilités mais elles sont considérées comme modérées.

On peut visualiser le dĂ©tail d’une CVE en particulier en cliquant sur le bouton information (flĂšche rouge)

Une description de l’exploit vous indique l’impact de la faille sur le systùme.

A vous de juger si l’image doit ĂȘtre ou non corrigĂ©e.

tomcat:10.0-jdk11-openjdk

Commençons par une image particuliÚrement vulnérable

On est sur un nombre trÚs importants de vulnérabiltés (106)!

Il est vivement recommandé de patcher ces vulnérabilités.

Comme pour tout Ă  l’heure on peut vĂ©rifier les dĂ©tails.

tomcat:10.0-jdk11-corretto

Modifier l’image de base permet de diminuer de maniĂšre drastique les failles de sĂ©curitĂ© prĂ©sentes dans l’image.

Il y en a toujours mais elles sont bien moins nombreuses et bien moins dangeureuses qu’avec la version openjdk basĂ©e sur debian 10.

Et c’est Ă  peu prĂšs tout ce que vous devez faire sur Gitlab.com pour avoir l’assurance de la sĂ©curitĂ© de vos images.

AprĂšs tout systĂšme est imparfait, Clair se base sur une base de donnĂ©es limitĂ© pour vĂ©rifier les diffĂ©rentes CVE et comme celles-ci apparaissent tous les jours c’est une course perdue d’avance. Tout ce qu’on peut faire c’est limitĂ© les risques.

Passons à la seconde méthode. :)

Méthode Harbor

Harbor est un service de registry d’images de container et de charts helm.

Le projet est opensource, gratuit, permet de pouvoir stocker, vérifier et distribuer ses images.

Il dispose aussi d’un systĂšme d’ACL assez poussĂ© et de tout un tas de fonctionnalitĂ© sympas.

L’une d’elle va nous intĂ©resser tout particuliĂšrement: il s’agit de l’intĂ©gration Trivy.

Comme son github l’indique, le rĂŽle de Trivy est de scanner les vulnĂ©rabilitĂ©s des containers et de rĂ©aliser un rapport dĂ©taillĂ© et lisible afin qu’un humain puisse comprendre les problĂšmes et les fixer si besoin est.

Exactement comme pour la méthode gitlab.

Mais vous vous demandez surement pourquoi je vous parle de Harbor alors que le scan des images est trĂšs facile sur Gitlab.

Et bien, il y a une subtilité : en version auto-hébergée, Gitlab gratuit propose bien le scan des images mais pas la jolie interface de rapport.

Tout ce que vous aurez dans l’interface de votre merge request c’est un lien pour tĂ©lĂ©charger le rapport au format JSON.

Mais on doit se l’avouer c’est presque inutilisable, surtout lorsque le nombre de vulnĂ©rabilitĂ©s est grand.

On sait d’expĂ©rience que si un outil n’est pas pratique on ne l’utilise pas. Et ce fichier JSON Ă  tĂ©lĂ©charger est l’exemple type !

C’est pour cette raison je propose d’installer le service Harbor.

Installer Harbor

Heureusement pour nous Harbor est trĂšs facile Ă  installer. Il se prĂ©sente sous une collection d’images docker rassemblĂ© sous un docker-compose.

Les prĂ©-requis sont donc d’avoir une machine possĂ©dant docker et docker-compose.

Il vous faut aussi un nom de domaine, soit vous avez un enregistrement DNS soit vous modifiez votre /etc/hosts.

Je ferai mon installation sur une ubuntu 20.04.

Vous pouvez récupérer la derniÚre release sur cette page.

La version online est infiniment plus lĂ©gĂšre que la offline et donc je propose de l’utiliser, le rĂ©sultat sera le mĂȘme de toute façon. :)

Avant tout on va récupérer un certificat.

Si vous n’avez pas de nom de domaine rĂ©el, vous pouvez utiliser un certificat auto-signĂ©, mais attention, vous risquez d’avoir des alertes de sĂ©curitĂ© pour plusieurs choses.

Nous allons prĂ©fĂ©rer l’utilisation de Let’s Encrypt qui permet d’obtenir des certificats signĂ©s par une autoritĂ© et donc parfaitement reconnu sans les problĂšmes de sĂ©curitĂ©s dont je vous ai mentionnĂ© l’existence plus haut.

Pour cela il existe un utilitaire extrĂȘmement pratique nommĂ© certbot.

On l’installe.

snap install certbot --classic

J’utilise snap car le package apt est Ă  une version bien infĂ©rieure.

VĂ©rifiez bien que votre nom de domaine rĂ©sout bien l’IP de votre serveur harbor.

Vous pouvez vous aidez de:

nslookup harbor.example.com

Ensuite on génÚre le certificat

certbot certonly -m me@example.com --agree-tos --standalone -d harbor.example.com

AprĂšs quelques instants vous devriez

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/harbor.example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/harbor.example.com/privkey.pem
   Your certificate will expire on 2021-07-10. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Téléchargez la release:

wget https://github.com/goharbor/harbor/releases/download/v2.2.1/harbor-online-installer-v2.2.1.tgz

Modifier la version si besoin est.

DĂ©compressez l’archive

tar xzvf harbor-online-installer-v2.2.1.tgz -C /opt

Copiez le fichier de configuration

cp /opt/harbor/harbor.yml.tmpl /opt/harbor/harbor.yml

Modifier le fichier /opt/harbor/harbor.yml.

Pour faire correspondre Ă  votre nom de domaine et aux chemins des certificats.

hostname: harbor.example.com
https:
    port: 443
    certificate: /etc/letsencrypt/live/harbor.example.com/fullchain.pem
    private_key: /etc/letsencrypt/live/harbor.example.com/privkey.pem

Vous pouvez aussi modifier les mots de passes, je vais les laisser tel quel mais en production c’est Ă©videmment une trĂšs mauvaise idĂ©e !!

Nous allons installer Harbor avec 3 composants supplémentaires:

cd /opt/harbor
./install.sh --with-notary --with-trivy --with-chartmuseum

Ce script à pour rÎle de télécharger les images docker de Harbor, de configurer tout ce qui est à configurer et de lancer le tout.

AprĂšs quelques instants, vous pouvez vous rendre sur https://harbor.example.com.

Connectez vous avec les identifiants:

Par défaut:

user: admin
password: Harbor12345

Vous arrivez sur l’interfaces des projets, dans le jargon de Harbor, le projet est une isolation qui permet de limiter les accùs aux images à un certain nombre d’utilisateurs.

Par défaut un projet library est déjà présent.

Cliquez sur le lien en bleu library.

Dans configuration coché la case Automatically scan images on push

Ceci va permettre de lancer automatiquement des scan de sécurité des images.

On va créer un utilisateur robot qui nous permettra de pousser nos images sur le repository.

  1. Cliquez dans la side-bar sur Robot accounts.
  2. Cliquez sur New Robot Account
  3. Donnez un nom à votre compte. Modifiez l’expiration du token si besoin
  4. Donnez les droits au robot sur le projet library

Le token ne sera plus remontrĂ©. Stockez-le quelque part. Il va ĂȘtre rĂ©utilisĂ© tout de suite.

Et pour la forme je vous montre que trivy tourne bien ^^

Configurer Gitlab

On va modifier notre pipeline Gitlab défini à la partie précédente.

Tout d’abord on se créé une nouvelle branche dĂ©rivĂ©e de master.

puis on modifie ainsi le docker-compose.yml

stages:
  - build

build:
  stage: build
  image: 
    name: gcr.io/kaniko-project/executor:debug
    entrypoint: [""]
  variables:
    IMAGE: ubuntu:21.04
    REGISTRY: harbor.laforge.works
  script:
  - cat $HARBOR_ROBOT_AUTH_FILE > /kaniko/.docker/config.json
  - | 
      /kaniko/executor \
      --context=$CI_PROJECT_DIR \
      --dockerfile=$CI_PROJECT_DIR/Dockerfile \
      --destination=$REGISTRY/library/$IMAGE \
      --build-arg=IMAGE=$IMAGE

On utilise un projet appelé kaniko, celui ci remplace avantageusement le runtime docker par une solution plus rapide, plus légÚre moins contraignante et plus sécurisée.

En effet, kaniko, ne nécéssite pas de container privilégié pour construire les images puis les pousser dans un registry, ici pour nous notre Harbor.

On modifie aussi notre Dockerfile.

ARG $IMAGE=busybox:latest
FROM $IMAGE

Cette modification permet de ne changer l’image que dans la variable de lancement du pipeline.

Il nous manque juste l’authentification de notre robot sur harbor.

Rendez-vous dans l’interface de gestion des varaibles de CI/CD.

Et ajoutez une nouvelle variable.

  1. Dans le champ key indiqué la chaßne de caractÚres HARBOR_ROBOT_AUTH_FILE.

  2. Dans value

Remplissez la avec:

{
   "auths":{
      "harbor.example.com":{
         "username":"robot$$gitlab",
         "password":"***********************"
      }
   }
}

Modifiez harbor.example.com par le domaine de votre instance Harbor et le veillez bien Ă  doubler le symbole dollar $$ sinon la deuxiĂšme partie sera considĂ©rĂ© comme une variable d’environnement.

  1. Modifiez le type par File.

  2. Décochez le Protect variable

  3. Ajoutez la variable.

C’est bon on est prĂȘt Ă  tester notre pipeline :D

Tests des images

Pour lancer un pipeline de construction et d’upload de notre image, vous devez vous rendre dans la section CI/CD -> Pipelines de notre projet Gitlab.

Puis

  1. Modifier la branche utiliser comme source
  2. Ajouter une varible appelée IMAGE
  3. Ajouter un nom d’image à construire ici par exemple: busybox:latest
  4. Lancer votre pipeline

AprĂšs quelques instants vous pouvez retourner sur Harbor dans le projet library.

Vous y trouverez une image busybox, et comme vous le constatez 0 vulnérabilté à constater.

ubuntu:21.04

RĂ©itĂ©rez les steps du dessus avec comme l’image ubuntu:21.04 comme valeur de IMAGE

Comme pour les checks Gitlab, aucune vulnérabilité à signaler.

ubuntu:20.04

On essaie avec une ubuntu:20.04.

Cette fois, pour l’image ubuntu:20.04 on voit un M jaune. Cela signifie que l’image possĂšde des vulnĂ©rabilitĂ©s de sĂ©vĂ©ritĂ© modĂ©rĂ©es.

En cliquant sur le sha1 de l’ubuntu:20.04 on peut visualiser les dĂ©tails des vulnĂ©rabilitĂ©s.

Comme on peut le voir, chaque vulnérabilité possÚde sa CVE et donc le détail du problÚme de sécurité.

Avec la flĂšche on peut mĂȘme bĂ©nĂ©ficier d’un abstract du problĂšme.

tomcat:10.0-jdk11-openjdk

Allons y pour notre image trouée la tomcat:10.0-jdk11-openjdk

Elle nous donne le résultat suivant

Et les dĂ©tails sont encore plus alarmants
 😹

Le rĂ©sultat est clair, il ne faut pas utiliser sous aucun prĂ©texte cette image en production! 😡

tomcat:10.0-jdk11-corretto

Réparons tout ça avec la tomcat:10.0-jdk11-corretto

Ouf :D

Sur Harbor il existe tout un systĂšme de Harbor de webhooks, je planche actuellement sur une intĂ©gration Mattermost pour m’avertir lorsqu’une vulnĂ©rabilitĂ© apparaĂźt sur une image.

Je ferai un article sur le sujet quand j’aurai un peu plus avancĂ© ^^

Conclusion

Cet article devait ĂȘtre court et ce ne fut pas le cas 😁

Ce que je vous est montrĂ© aujourd’hui je l’utilise dĂ©sormais tous les jours.

Dans un prochain article sur la sĂ©curitĂ©, je vous expliquerai comment crĂ©er des images extrĂȘmement lĂ©gĂšres et donc avec une surface d’attaque extrĂȘmement rĂ©duite.

Cette mĂ©thode s’appelle le multi-stage building et l’utilisation de scratch comme base.

Je vous remercie de m’avoir lu et je vous dis à la prochaine :)