Aller au contenu
Conteneurs & Orchestration medium

Confiance et provenance Helm : signer vos charts pour sécuriser la supply chain

40 min de lecture

logo helm

La provenance Helm garantit que le chart que vous installez provient bien de l'auteur attendu et n'a pas été modifié. Un fichier .prov contient une signature cryptographique du chart, si le chart est altéré, la vérification échoue. En production, c'est une couche de sécurité essentielle contre les attaques de type supply chain.


Un chart Helm est une archive .tgz téléchargée depuis un dépôt distant, puis appliquée telle quelle sur votre cluster. Rien dans le protocole ne prouve qui l'a produite : le TLS protège le transport, pas le contenu, et un index.yaml compromis suffit à rediriger vers une archive modifiée. La signature déplace la confiance du serveur vers l'auteur, en attachant au chart une preuve cryptographique vérifiable hors ligne.

L'enchaînement type se déroule sans qu'aucune étape ne paraisse anormale côté utilisateur :

  1. Vous utilisez un chart public bitnami/postgresql
  2. Un attaquant compromet le repository ou fait du man-in-the-middle
  3. Vous téléchargez un chart modifié avec un backdoor
  4. Le backdoor s'exécute dans votre cluster → compromission

La signature répond à une question précise : « ce fichier est-il exactement celui qu'a produit le détenteur de cette clé ». Les trois propriétés ci-dessous en découlent directement, et elles ne valent que si vous avez obtenu la clé publique par un canal de confiance, indépendant du dépôt de charts.

AspectGarantie
IntégritéLe chart n'a pas été modifié depuis la signature
AuthenticitéLe chart a été signé par le détenteur de la clé privée
Non-répudiationL'auteur ne peut pas nier avoir signé

Une signature valide n'est pas un certificat de bonne conduite : elle atteste l'origine, pas la qualité ni les intentions. Confondre les deux conduit à installer sans relecture un chart signé qui monte /var/run/docker.sock ou demande le rôle cluster-admin. La signature complète l'analyse du contenu, elle ne la remplace pas.

AspectLimitation
Qualité du codeUn chart signé peut contenir des bugs ou vulnérabilités
Intention malveillanteL'auteur légitime peut publier un chart malveillant
Sécurité de la cléSi la clé privée est compromise, les signatures sont inutiles

La signature Helm repose sur GPG : vous générez une paire de clés, gardez la partie privée pour signer, et diffusez la partie publique pour que d'autres vérifient. Fixez une date d'expiration dès la création, c'est le seul mécanisme qui limite les dégâts si la clé fuit sans que vous le sachiez ; elle reste prolongeable tant que vous détenez la clé. Une passphrase est demandée à la génération : elle protège le fichier de clé privée, mais gêne l'automatisation, d'où la clé dédiée CI/CD évoquée plus bas.

  1. Générer une paire de clés

    Fenêtre de terminal
    gpg --full-generate-key

    Choisissez :

    • Type : RSA and RSA (option 1)
    • Taille : 4096 bits
    • Expiration : 2 ans (recommandé)
    • Identité : Helm Charts <helm@example.com>
  2. Lister les clés disponibles

    Fenêtre de terminal
    gpg --list-secret-keys --keyid-format LONG

    Résultat :

    sec rsa4096/ABCD1234EFGH5678 2026-02-01 [SC] [expires: 2028-02-01]
    Key fingerprint = 1234 5678 ABCD EFGH ...
    uid [ultimate] Helm Charts <helm@example.com>

    Notez l'ID de la clé : ABCD1234EFGH5678

  3. Exporter la clé publique

    Fenêtre de terminal
    gpg --armor --export ABCD1234EFGH5678 > helm-charts.pub.asc

    Ce fichier sera distribué aux utilisateurs pour vérifier vos charts.


La signature n'est pas une étape séparée : elle se fait pendant le packaging, parce que la signature porte sur l'archive .tgz finale. Signer après coup supposerait de recréer exactement la même archive, ce qui n'est pas garanti. Concrètement, helm package --sign remplace votre helm package habituel et produit un fichier de plus.

--key accepte l'identité de la clé (son nom ou son adresse), --keyring désigne le fichier de trousseau contenant la clé privée.

Fenêtre de terminal
# Packager ET signer en une commande
helm package ./my-chart --sign --key "Helm Charts" --keyring ~/.gnupg/secring.gpg

Deux fichiers sont créés :

my-chart-1.2.3.tgz # Le chart packagé
my-chart-1.2.3.tgz.prov # Le fichier de provenance (signature)

Le .prov est un message signé en clair : vous pouvez l'ouvrir dans un éditeur, il reste lisible. C'est ce qui permet de comparer à l'oeil les métadonnées annoncées avec celles du chart avant même de lancer la vérification.

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
apiVersion: v2
appVersion: "2.0.0"
description: My awesome chart
name: my-chart
version: 1.2.3
...
files:
my-chart-1.2.3.tgz: sha256:abc123def456...
-----BEGIN PGP SIGNATURE-----
...
-----END PGP SIGNATURE-----

Le .prov contient :

  • Les métadonnées du chart
  • Le hash SHA256 du tarball
  • La signature GPG de l'ensemble

La vérification est à la charge du consommateur du chart : Helm ne la déclenche pas tout seul. Sans helm verify explicite, ou sans l'option --verify sur helm install, un chart signé s'installe exactement comme un chart non signé, y compris si le fichier .prov est absent. Vérifier suppose deux choses réunies : le .prov téléchargé à côté du .tgz, et la clé publique de l'auteur déjà présente dans votre trousseau.

Ces trois étapes sont à enchaîner dans l'ordre, la vérification devant précéder l'installation.

  1. Importer la clé publique de l'auteur

    Fenêtre de terminal
    gpg --import helm-charts.pub.asc
  2. Vérifier le chart

    Fenêtre de terminal
    helm verify my-chart-1.2.3.tgz

    Succès :

    Signed by: Helm Charts <helm@example.com>
    Using Key With Fingerprint: 1234 5678 ABCD EFGH ...
    Chart Hash Verified: sha256:abc123def456...
  3. Installer si vérifié

    Fenêtre de terminal
    helm install my-release my-chart-1.2.3.tgz -n prod

Un échec ne veut pas dire attaque : dans la majorité des cas, il manque simplement le fichier .prov ou la clé publique. Le message d'erreur permet de trancher, et c'est ce tri qu'il faut faire avant toute autre chose. Une seule des trois situations impose de tout arrêter.

ErreurCause probableAction
Error: could not find a valid signatureFichier .prov manquantContacter l'auteur, télécharger le .prov
Error: signature verification failedChart modifié ou mauvaise cléNe pas installer, télécharger depuis source officielle
Error: key not foundClé publique non importéeImporter la clé de l'auteur

Toute la chaîne repose sur ce point : si vos utilisateurs récupèrent la clé publique au même endroit que le chart, un attaquant qui contrôle le dépôt remplace les deux et la vérification réussit sur un chart falsifié. La clé doit donc emprunter un canal distinct de celui des artefacts. Publiez aussi son empreinte (fingerprint) là où votre identité est déjà établie, elle permet de contrôler que la clé importée est la bonne.

Aucune méthode n'est parfaite, elles se distinguent par le type de compromission qu'elles rendent difficile. En pratique, la combinaison de deux canaux vaut mieux qu'un seul, même excellent.

MéthodeAvantagesInconvénients
README du repoSimple, visiblePeut être modifié par un attaquant
Keyserver publicStandard GPG, décentraliséPeut contenir des clés abandonnées
Site web HTTPSContrôle total, HTTPS = TLSNécessite infra web
DNS (DANE)Très sécuriséComplexe à configurer

L'envoi sur un keyserver public est irréversible : une clé publiée ne peut plus être retirée, seulement révoquée par un certificat de révocation que vous devez générer à l'avance.

Fenêtre de terminal
# Envoyer la clé sur un keyserver public
gpg --keyserver keyserver.ubuntu.com --send-keys ABCD1234EFGH5678

Récupérer une clé par son identifiant ne la rend pas digne de confiance pour autant : n'importe qui peut téléverser une clé portant le nom de votre projet. Comparez l'empreinte obtenue avec celle publiée par l'auteur avant de l'utiliser.

Fenêtre de terminal
# Télécharger la clé depuis un keyserver
gpg --keyserver keyserver.ubuntu.com --recv-keys ABCD1234EFGH5678

Automatiser la signature suppose de donner au pipeline l'accès à une clé privée, donc de la stocker comme secret masqué et jamais dans le dépôt. Le job ci-dessous importe la clé depuis la variable protégée GPG_PRIVATE_KEY, reconstitue le trousseau au format attendu par Helm, puis empaquette et signe. Le point de vigilance est en fin de job : helm push publie l'archive, pas le .prov, qui doit être transmis à part sous peine de livrer un chart que personne ne pourra vérifier.

.gitlab-ci.yml
variables:
GPG_KEY_ID: "ABCD1234EFGH5678"
package-and-sign:
stage: build
script:
# Importer la clé privée depuis les secrets
- echo "$GPG_PRIVATE_KEY" | gpg --import
- gpg --export-secret-keys > ~/.gnupg/secring.gpg
# Packager et signer
- helm package ./charts/my-chart --sign --key "$GPG_KEY_ID" --keyring ~/.gnupg/secring.gpg
# Publier chart + provenance
- helm push my-chart-*.tgz oci://registry.example.com/charts
# Note: le .prov doit être publié séparément ou avec le chart
artifacts:
paths:
- "*.tgz"
- "*.tgz.prov"

La signature GPG native de Helm date d'une époque où les charts se distribuaient par HTTP, avec un index.yaml et des archives posées sur un serveur web. Le passage aux registries OCI a changé la donne : l'artefact et ses métadonnées y vivent ensemble, ce que le modèle du fichier .prov séparé ne sait pas exploiter.

Ces quatre limites relèvent de la conception, pas d'un défaut d'implémentation : aucune ne se corrige par une option. Elles indiquent quand il faut regarder ailleurs.

LimitationImpact
GPG uniquementPas de support natif pour d'autres systèmes (Cosign, Notation)
.prov séparéDoit être distribué en plus du chart
Pas d'intégration OCI nativeLe .prov ne fait pas partie de l'artefact OCI
Gestion des clés manuelleRotation, révocation à gérer vous-même

Cosign (projet Sigstore) permet de signer des artefacts OCI (y compris des charts Helm) :

Fenêtre de terminal
# Signer un chart OCI avec Cosign
cosign sign oci://registry.example.com/charts/my-chart:1.2.3
# Vérifier
cosign verify oci://registry.example.com/charts/my-chart:1.2.3

Avantages de Cosign :

  • Signature intégrée à l'artefact OCI (pas de fichier séparé)
  • Support des clés éphémères (keyless signing via OIDC)
  • Intégration native avec les registries OCI

Objectif : Créer une clé GPG, signer un chart, publier chart + provenance, vérifier l'intégrité avant installation.

Ce lab s'exécute intégralement en local, sans cluster ni registre. Son intérêt tient à l'étape 5 : vous altérez volontairement le chart signé pour constater que helm verify le détecte, ce qui vaut mieux que de le lire. La clé créée expire au bout d'un jour et est générée sans passphrase pour ne pas bloquer le script, ce qui la rend impropre à tout autre usage que ce lab.

  1. Créer une clé de test

    Fenêtre de terminal
    # Clé rapide pour le lab (pas pour production)
    gpg --batch --gen-key <<EOF
    Key-Type: RSA
    Key-Length: 2048
    Name-Real: Helm Lab
    Name-Email: helm-lab@local
    Expire-Date: 1d
    %no-protection
    %commit
    EOF
    # Récupérer l'ID
    GPG_KEY=$(gpg --list-secret-keys --keyid-format LONG | grep sec | awk '{print $2}' | cut -d'/' -f2 | head -1)
    echo "Key ID: $GPG_KEY"
  2. Exporter le keyring

    Fenêtre de terminal
    gpg --export-secret-keys > ~/.gnupg/secring.gpg
  3. Créer et signer un chart

    Fenêtre de terminal
    helm create lab-signed-chart
    helm package lab-signed-chart --sign --key "Helm Lab" --keyring ~/.gnupg/secring.gpg
  4. Vérifier la signature

    Fenêtre de terminal
    # La clé publique est déjà importée (on l'a créée localement)
    helm verify lab-signed-chart-0.1.0.tgz
  5. Simuler une altération

    Fenêtre de terminal
    # Décompresser le chart
    tar -xzf lab-signed-chart-0.1.0.tgz
    # Modifier un fichier
    echo "# Malicious change" >> lab-signed-chart/values.yaml
    # Recompresser
    tar -czf lab-signed-chart-0.1.0.tgz lab-signed-chart
    # Tenter de vérifier → doit échouer
    helm verify lab-signed-chart-0.1.0.tgz
  6. Nettoyer

    Fenêtre de terminal
    rm -rf lab-signed-chart lab-signed-chart-*.tgz*
    gpg --delete-secret-and-public-key "Helm Lab"

Critères de réussite :

  • Clé GPG créée
  • Chart signé avec .prov généré
  • helm verify réussit sur le chart original
  • helm verify échoue sur le chart altéré

  • Provenance = garantie d'intégrité et d'authenticité via signature cryptographique
  • helm package --sign = créer le chart + fichier .prov
  • helm verify = vérifier la signature avant installation
  • Clé privée = secrète, protégée, jamais partagée
  • Clé publique = distribuée aux utilisateurs pour vérification
  • Alternative moderne : Cosign pour les artefacts OCI

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn