Le chiffrement d’une image de container est un sujet assez peu évoqué. Les premiers exemples de solution n’apparaissant qu’à partir de 2019, poussé en particulier par Brandon Lum de IBM.
Le support de ces fonctionnalités ne semble pas très répandu pour le moment. Du côté des outils, nous parlons actuellement de buildah
et skopeo
pour la partie build, containerd
et cri-o
pour la partie runtime et enfin docker distribution pour la partie registry. A priori, il ne semble pas y avoir de support dans docker, mais un commentaire au détour d’une issue GitHub semblait indiquer que cela sera le cas. Je n’ai en revanche pas trouvé d’annonce ou de roadmap permettant de valider ce point.
Voici à la suite, les étapes de mon test de chiffrement d’une image de container, réalisé sous ArchLinux, mais transposable à toute autre distribution, à condition de pouvoir installer l’ensemble de dépendances.
Préparation
Installation des Dépendances
Sous ArchLinux, installation des composants:
$ sudo pacman -S docker containerd buildah podman minikube kubectl helm $ sudo systemctl start docker $ sudo gpasswd -a <user> docker
Registre d’image local
Démarrage d’un registre local pour y stocker l’image chiffrée que je vais générer.
$ sudo systemctl start docker $ sudo systemctl status docker $ sudo docker run -d -p 5000:5000 --restart=always --name registry registry:2
Génération du couple de clé
$ openssl genrsa -out testKey.pem 2048 $ openssl rsa -in testKey.pem -pubout -out testKey.pub.pem
Création d’une image basique
$ mkdir app $ cd app $ nano Dockerfile $ nano secret-file
Avec pour contenu du Dockerfile
:
FROM nginx:latest
COPY secret-file /secret-file
Et secret-file
, un simple fichier texte contenant une chaîne de caractère aléatoire.
Construction de l’image
$ sudo buildah bud -t encrypted-test .
Export
Export vers le registre local.
$ sudo buildah push --tls-verify=false --encryption-key jwe:../testKey.pub.pem encrypted-test localhost:5000/vvision/encrypted-test:latest
Export local dans une archive oci.
$ sudo buildah push --encryption-key jwe:../testKey.pub.pem encrypted-test oci-archive:encrypted-test:latest
Nettoyage
Suppression de toutes les images locales.
$ sudo buildah rmi --all
Récupération de l’image
$ sudo buildah pull --tls-verify=false --decryption-key keys/testKey.pem localhost:5000/vvision/encrypted-test
Exécution
$ sudo podman run -it localhost:5000/vvision/encrypted-test
/bin/bashroot@3e3c1ccde93c:/# cat secret-file
ASecretSecret
Vérification
Tentative de récupération de l’image depuis le registre local, sans préciser la clef.
$ sudo buildah pull --tls-verify=false localhost:5000/vvision/encrypted-test Getting image source signatures Copying blob 302a0c0a162e [--------------------------------------] 0.0b / 914.0b Copying blob 83e2b8dcdf4b [--------------------------------------] 0.0b / 27.1MiB Copying blob 9b30e9f5d77e [--------------------------------------] 0.0b / 617.0b Copying blob 0f9f80250abf [--------------------------------------] 0.0b / 134.0b Copying blob 7c9b3bc4d85b [--------------------------------------] 0.0b / 26.3MiB Copying blob 538a8875d492 [--------------------------------------] 0.0b / 678.0b Error decrypting layer sha256:83e2b8dcdf4bfca8bea0b23e771e84074e4cc308bf892bd6d63b3a0c9dab0564: missing private key needed for decryption
Utilisation dans Kubernetes
Démarrage d’un cluster Kubernetes avec minikube
.
$ minikube start --network-plugin=cni --enable-default-cni --container-runtime=cri-o --bootstrapper=kubeadm --insecure-registry="<local_ip_addr>:5000" $ minikube dashboard
Mécanisme de synchronisation des clefs
Installation du composant responsable déploiement de la clef de déchiffrement.
$ git clone https://github.com/IBM/k8s-enc-image-operator.git $ cd k8s-enc-image-operator $ kubectl create namespace enc-key-sync $ helm install --namespace=enc-key-sync k8s-enc-image-operator ./helm-operator/helm-charts/enckeysync/
Ajout de la clé dans Kubernetes Secret
$ kubectl create -n enc-key-sync secret generic --type=key --from-file=testKey.pem test-decryption-key
Déploiement du container
$ kubectl run test-enc --image=localhost:5000/vvision/encrypted-test
Conclusion
Au moment de mes premiers tests, je ne crois pas avoir rencontré de difficulté à récupérer l’image dans le registre local. Néanmoins, lors de tests plus récents, je n’ai pas réussi à reproduire ce fonctionnement sur d’autres plateformes. En revanche, une récupération depuis le registre docker, ou celui proposé dans la Google Cloud Plateform fonctionne.
Il me reste maintenant à reproduire ce mécanisme sur un cas réel complet, c’est-à-dire, de l’intégration au processus et aux outils de CI/CD, à la configuration du cluster Kubernetes cible, avec pour objectif un déploiement de la solution en production.
Sources
- Encrypted container images for container image security at rest
- Advancing container image security with encrypted container images
- DockerCon2019 – 05/2019 – Enabling High Assurance/Sensitive Container Workloads with Encrypted Images – Support visuel
- Open Source Summit – 07/2019 – Protecting Sensitive Code with Encrypted Container Images on Kubernetes – Brandon Lum & Harshal Patil, IBM
- Cloud Native Computing Foundation – Webinar 07/2020 – Advancing image security and compliance through Container Image Encryption!
- KubeCon2020 – 09/2020 – Where Are Your Images Running? Stop Worrying and Start Encrypting! – Brandon Lum & Harshal Patil – Support visuel
- Encrypting container images with skopeo – 01/2020