Lab : Implémentation d’un Pipeline de Build Sécurisé avec Tekton et Tekton Chains

Présentation

Tekton est un puissant framework open source natif de Kubernetes permettant de créer des systèmes d’intégration continue et de livraison continue (CI/CD). Il s’exécute sous forme de Custom Resource Definitions (CRDs) sur n’importe quel cluster Kubernetes, vous permettant de définir des pipelines sous forme de YAML déclaratif, portables d’un environnement à l’autre.

Tekton Chains est un projet complémentaire qui ajoute automatiquement la sécurité de la chaîne d’approvisionnement à vos pipelines Tekton. Une fois installé, Chains surveille les TaskRuns terminés, signe automatiquement leurs résultats à l’aide de Cosign ou d’autres outils de signature, et génère des attestations de provenance SLSA — le tout sans nécessiter aucune modification de vos définitions de pipeline existantes.

Dans ce lab pratique, vous allez :

  • Déployer Tekton Pipelines et Tekton Chains sur un cluster Kubernetes local
  • Configurer Chains pour signer automatiquement les artefacts et générer la provenance in-toto
  • Construire une image de conteneur via un Pipeline Tekton
  • Vérifier la signature générée automatiquement et la provenance SLSA
  • Ajouter une étape d’analyse de vulnérabilités au pipeline
  • Explorer la signature sans clé avec Sigstore Fulcio
  • Appliquer des politiques d’images signées au moment du déploiement

À la fin de ce lab, vous disposerez d’un pipeline de build sécurisé entièrement fonctionnel qui produit des images de conteneurs signées et attestées avec une provenance vérifiable — atteignant automatiquement la conformité SLSA Level 2.

Prérequis

Avant de commencer ce lab, assurez-vous que les outils suivants sont installés sur votre poste de travail :

  • Cluster Kubernetes — Nous utiliserons kind (Kubernetes in Docker) pour un cluster local. Alternativement, minikube fonctionne également.
  • kubectl — L’interface en ligne de commande Kubernetes, version 1.26 ou ultérieure.
  • Helm — Le gestionnaire de paquets Kubernetes, version 3.x.
  • tkn — Le CLI Tekton, utilisé pour interagir avec les ressources Tekton.
  • Cosign — Fait partie du projet Sigstore, utilisé pour signer et vérifier les images de conteneurs.
  • jq — Un processeur JSON en ligne de commande pour inspecter les charges utiles de provenance.
  • Un registre de conteneurs — Un registre vers lequel vous pouvez pousser des images, tel que GitHub Container Registry (GHCR) ou Docker Hub. Vous aurez besoin d’un accès en écriture et d’identifiants valides.

Ce lab suppose une familiarité avec les bases de Kubernetes (pods, namespaces, configmaps) et les concepts généraux de CI/CD.

Mise en Place de l’Environnement

Étape 1 : Créer un Cluster kind

Commencez par créer un cluster Kubernetes neuf avec kind :

kind create cluster --name tekton-lab
kubectl cluster-info --context kind-tekton-lab

Confirmez que le cluster est en cours d’exécution :

kubectl get nodes
# NAME                       STATUS   ROLES           AGE   VERSION
# tekton-lab-control-plane   Ready    control-plane   30s   v1.31.0

Étape 2 : Installer Tekton Pipelines

Installez la dernière version de Tekton Pipelines :

kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

Attendez que les pods Tekton Pipelines soient prêts :

kubectl get pods -n tekton-pipelines --watch

Vous devriez voir les pods tekton-pipelines-controller et tekton-pipelines-webhook en cours d’exécution :

NAME                                           READY   STATUS    RESTARTS   AGE
tekton-pipelines-controller-7f6b9b5b95-xk2rj   1/1     Running   0          45s
tekton-pipelines-webhook-6c4f8b7d4f-m9nlp      1/1     Running   0          45s

Étape 3 : Installer Tekton Chains

Installez Tekton Chains dans son propre namespace :

kubectl apply --filename https://storage.googleapis.com/tekton-releases/chains/latest/release.yaml

Vérifiez que Chains est en cours d’exécution :

kubectl get pods -n tekton-chains
# NAME                                        READY   STATUS    RESTARTS   AGE
# tekton-chains-controller-5f4b7c8d6f-r7t2x   1/1     Running   0          30s

À ce stade, Tekton Pipelines et Tekton Chains sont tous deux en cours d’exécution sur votre cluster.

Exercice 1 : Configurer Tekton Chains pour la Signature avec Cosign

Tekton Chains a besoin d’une clé de signature et d’une configuration pour savoir comment et où stocker les signatures et les attestations. Dans cet exercice, vous allez générer une paire de clés Cosign et configurer Chains pour utiliser le stockage OCI avec le format d’attestation in-toto.

Générer une Paire de Clés Cosign

Cosign peut générer une paire de clés et la stocker directement comme un Secret Kubernetes dans le namespace tekton-chains :

cosign generate-key-pair k8s://tekton-chains/signing-secrets

Vous serez invité à entrer un mot de passe pour la clé privée. Pour ce lab, vous pouvez appuyer sur Entrée pour le laisser vide. Cosign crée un Secret nommé signing-secrets contenant la clé privée, la clé publique et le mot de passe.

Vérifiez que le secret a été créé :

kubectl get secret signing-secrets -n tekton-chains
# NAME              TYPE     DATA   AGE
# signing-secrets   Opaque   3      10s

Configurer le Stockage et le Format de Chains

Ensuite, configurez Chains pour stocker les signatures dans le registre OCI aux côtés de l’image et pour générer la provenance au format in-toto :

kubectl patch configmap chains-config -n tekton-chains \
  -p='{"data":{"artifacts.oci.storage":"oci","artifacts.taskrun.format":"in-toto","artifacts.taskrun.storage":"oci"}}'

Cette configuration indique à Chains de :

  • artifacts.oci.storage: oci — Stocker les signatures d’artefacts OCI dans le registre OCI
  • artifacts.taskrun.format: in-toto — Générer les attestations au format in-toto, qui est le standard pour la provenance SLSA
  • artifacts.taskrun.storage: oci — Stocker les attestations de TaskRun dans le registre OCI

Redémarrer le Contrôleur Chains

Après avoir modifié la configuration, redémarrez le contrôleur Chains pour qu’il prenne en compte les nouveaux paramètres :

kubectl rollout restart deployment tekton-chains-controller -n tekton-chains
kubectl rollout status deployment tekton-chains-controller -n tekton-chains

Fonctionnement de Chains

Avec Chains configuré, voici ce qui se passe automatiquement chaque fois qu’un TaskRun se termine :

  1. Le contrôleur Chains détecte le TaskRun terminé.
  2. Il inspecte les résultats du TaskRun pour trouver les références d’images OCI (spécifiquement les résultats nommés IMAGE_URL et IMAGE_DIGEST).
  3. Il signe l’image à l’aide de la clé Cosign stockée dans le Secret signing-secrets.
  4. Il génère une attestation de provenance in-toto capturant les détails du build.
  5. Il pousse la signature et l’attestation vers le registre OCI.
  6. Il annote le TaskRun avec chains.tekton.dev/signed=true.

Rien de tout cela ne nécessite de modification de vos Tasks ou Pipelines.

Exercice 2 : Créer un Pipeline de Build

Vous allez maintenant créer un Pipeline Tekton qui clone un dépôt Git et construit une image de conteneur à l’aide de Kaniko. Commencez par configurer les identifiants du registre pour que Tekton puisse pousser les images.

Configurer les Identifiants du Registre

Créez un Secret Kubernetes avec vos identifiants de registre. Remplacez les valeurs de substitution par les détails réels de votre registre :

export REGISTRY_SERVER=ghcr.io
export REGISTRY_USER=your-username
export REGISTRY_PASSWORD=your-token

kubectl create secret docker-registry registry-credentials \
  --docker-server=$REGISTRY_SERVER \
  --docker-username=$REGISTRY_USER \
  --docker-password=$REGISTRY_PASSWORD

kubectl patch serviceaccount default -p '{"secrets": [{"name": "registry-credentials"}]}'

Créer la Task de Build

Créez un fichier nommé build-task.yaml. Cette Task accepte une URL de dépôt Git, un nom d’image cible, et utilise Kaniko pour construire et pousser l’image :

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: git-clone-and-build
spec:
  params:
    - name: repo-url
      type: string
      description: The Git repository URL to clone
    - name: image
      type: string
      description: The image reference to build and push (e.g., ghcr.io/user/app:tag)
  results:
    - name: IMAGE_URL
      description: The image URL that was built
    - name: IMAGE_DIGEST
      description: The digest of the built image
  workspaces:
    - name: source
  steps:
    - name: clone
      image: alpine/git:2.43.0
      script: |
        #!/usr/bin/env sh
        set -eu
        git clone $(params.repo-url) $(workspaces.source.path)/src
        echo "Repository cloned successfully"
    - name: build-and-push
      image: gcr.io/kaniko-project/executor:latest
      args:
        - --dockerfile=$(workspaces.source.path)/src/Dockerfile
        - --context=$(workspaces.source.path)/src
        - --destination=$(params.image)
        - --digest-file=$(results.IMAGE_DIGEST.path)
      securityContext:
        runAsUser: 0
    - name: write-url
      image: alpine:3.19
      script: |
        #!/usr/bin/env sh
        set -eu
        echo -n "$(params.image)" > "$(results.IMAGE_URL.path)"
        echo "Image URL written: $(params.image)"

Appliquez la Task :

kubectl apply -f build-task.yaml

Créer la Task d’Analyse de Vulnérabilités (Pour Utilisation Ultérieure)

Créez vuln-scan-task.yaml — vous l’ajouterez au pipeline dans un exercice ultérieur :

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: vulnerability-scan
spec:
  params:
    - name: image
      type: string
      description: The image reference to scan
  steps:
    - name: scan
      image: anchore/grype:latest
      args:
        - $(params.image)
        - --fail-on
        - critical
        - --output
        - table

Créer le Pipeline

Créez build-pipeline.yaml qui enchaîne les étapes de clonage et de build :

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: secure-build
spec:
  params:
    - name: repo-url
      type: string
    - name: image
      type: string
  workspaces:
    - name: shared-workspace
  tasks:
    - name: build
      taskRef:
        name: git-clone-and-build
      params:
        - name: repo-url
          value: $(params.repo-url)
        - name: image
          value: $(params.image)
      workspaces:
        - name: source
          workspace: shared-workspace

Appliquez le Pipeline :

kubectl apply -f build-pipeline.yaml

Exécuter le Pipeline

Créez un PipelineRun pour exécuter le pipeline. Remplacez la référence de l’image par votre registre :

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  generateName: secure-build-run-
spec:
  pipelineRef:
    name: secure-build
  params:
    - name: repo-url
      value: "https://github.com/GoogleContainerTools/kaniko.git"
    - name: image
      value: "ghcr.io/your-username/tekton-lab:v1"
  workspaces:
    - name: shared-workspace
      volumeClaimTemplate:
        spec:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 1Gi

Enregistrez ceci sous pipelinerun.yaml et créez-le :

kubectl create -f pipelinerun.yaml

Surveillez l’exécution du pipeline :

tkn pipelinerun logs -f --last
# [build : clone] Cloning into '/workspace/source/src'...
# [build : clone] Repository cloned successfully
# [build : build-and-push] INFO[0001] Resolved base image golang:1.22
# [build : build-and-push] ...
# [build : build-and-push] INFO[0045] Pushing image to ghcr.io/your-username/tekton-lab:v1
# [build : write-url] Image URL written: ghcr.io/your-username/tekton-lab:v1

Le build devrait se terminer avec succès. Vous pouvez également vérifier le statut du PipelineRun :

tkn pipelinerun list
# NAME                     STARTED        DURATION   STATUS
# secure-build-run-x7k2p   1 minute ago   1m 15s     Succeeded

Exercice 3 : Vérifier la Signature Automatique

Une fois le PipelineRun terminé, Tekton Chains détecte automatiquement le TaskRun complété, signe l’image construite et annote le TaskRun. Tout cela se passe en arrière-plan — aucune modification du pipeline n’est nécessaire.

Attendre la Signature par Chains

Chains traite les TaskRuns terminés de manière asynchrone. Attendez quelques instants, puis vérifiez les annotations du TaskRun :

# Obtenir le nom du TaskRun à partir du PipelineRun
TASKRUN=$(kubectl get taskrun -l tekton.dev/pipeline=secure-build -o name --sort-by=.metadata.creationTimestamp | tail -1)
echo $TASKRUN

# Vérifier si Chains l'a signé
kubectl get $TASKRUN -o jsonpath='{.metadata.annotations.chains\.tekton\.dev\/signed}'

La sortie devrait être :

true

Si elle est encore vide, attendez quelques secondes et réessayez — Chains a besoin de temps pour traiter la signature.

Vérifier la Signature avec Cosign

Vérifiez maintenant la signature de l’image en utilisant la clé publique de la paire de clés Cosign que vous avez générée précédemment :

cosign verify \
  --key k8s://tekton-chains/signing-secrets \
  ghcr.io/your-username/tekton-lab:v1

Vous devriez voir une sortie confirmant que la vérification a réussi :

Verification for ghcr.io/your-username/tekton-lab:v1 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - The signatures were verified against the specified public key

[{"critical":{"identity":{"docker-reference":"ghcr.io/your-username/tekton-lab"},"image":{"docker-manifest-digest":"sha256:abc123..."},"type":"cosign container image signature"},"optional":{}}]

Inspecter les Annotations du TaskRun

Chains annote le TaskRun avec des métadonnées riches sur l’opération de signature :

kubectl get $TASKRUN -o jsonpath='{.metadata.annotations}' | jq .

Les annotations clés incluent :

{
  "chains.tekton.dev/signed": "true",
  "chains.tekton.dev/transparency": "https://rekor.sigstore.dev/api/v1/log/entries?logIndex=...",
  "chains.tekton.dev/signature-taskrun-...": "..."
}

L’annotation chains.tekton.dev/signed=true confirme que Chains a traité et signé ce TaskRun avec succès. Si un journal de transparence est configuré, vous verrez également une référence vers une entrée du journal Rekor.

Exercice 4 : Inspecter la Provenance SLSA

Au-delà des simples signatures, Tekton Chains génère des attestations de provenance SLSA complètes. Ces attestations décrivent comment l’artefact a été construit — quelle source a été utilisée, quelles étapes de build ont été exécutées et quels outils ont été impliqués.

Récupérer l’Attestation de Provenance

Utilisez Cosign pour vérifier et récupérer l’attestation in-toto :

cosign verify-attestation \
  --key k8s://tekton-chains/signing-secrets \
  --type slsaprovenance \
  ghcr.io/your-username/tekton-lab:v1 | jq -r '.payload' | base64 -d | jq .

Comprendre la Structure de la Provenance

L’attestation de provenance suit le format in-toto Statement avec un prédicat SLSA Provenance. Voici une analyse des champs clés :

{
  "_type": "https://in-toto.io/Statement/v0.1",
  "predicateType": "https://slsa.dev/provenance/v0.2",
  "subject": [
    {
      "name": "ghcr.io/your-username/tekton-lab",
      "digest": {
        "sha256": "abc123def456..."
      }
    }
  ],
  "predicate": {
    "builder": {
      "id": "https://tekton.dev/chains/v2"
    },
    "buildType": "tekton.dev/v1beta1/TaskRun",
    "invocation": {
      "configSource": {},
      "parameters": {
        "repo-url": "https://github.com/GoogleContainerTools/kaniko.git",
        "image": "ghcr.io/your-username/tekton-lab:v1"
      }
    },
    "buildConfig": {
      "steps": [
        {
          "entryPoint": "...",
          "arguments": null,
          "environment": {
            "container": "clone",
            "image": "alpine/git:2.43.0@sha256:..."
          }
        },
        {
          "entryPoint": "...",
          "environment": {
            "container": "build-and-push",
            "image": "gcr.io/kaniko-project/executor:latest@sha256:..."
          }
        }
      ]
    },
    "materials": [
      {
        "uri": "oci://alpine/git:2.43.0",
        "digest": { "sha256": "..." }
      },
      {
        "uri": "oci://gcr.io/kaniko-project/executor:latest",
        "digest": { "sha256": "..." }
      }
    ]
  }
}

Passons en revue chaque champ :

  • subject — L’artefact qui a été produit, identifié par son URL de registre et son condensé SHA-256. C’est ce dont la provenance témoigne.
  • builder.id — Identifie le système de build. Tekton Chains définit cette valeur à https://tekton.dev/chains/v2.
  • buildConfig.steps — Enregistre chaque étape qui a été exécutée dans le TaskRun, y compris les images de conteneurs exactes utilisées (épinglées par condensé).
  • materials — Liste les artefacts d’entrée consommés pendant le build, tels que les images de base. Chaque matériau inclut un condensé pour la reproductibilité.
  • invocation.parameters — Capture les paramètres passés au TaskRun, montrant exactement quelles entrées ont piloté le build.

Ces données de provenance satisfont les exigences du SLSA Level 2 : le processus de build est défini dans un service de build (Tekton), et la provenance est générée automatiquement par Tekton Chains (et non par le script de build lui-même). La provenance est signée, fournissant une preuve de non-altération.

Exercice 5 : Ajouter une Task d’Analyse de Vulnérabilités

Un pipeline sécurisé ne devrait pas seulement signer les artefacts, mais aussi vérifier qu’ils sont exempts de vulnérabilités connues avant le déploiement. Dans cet exercice, vous allez ajouter une étape d’analyse de vulnérabilités Grype au pipeline.

Appliquer la Task d’Analyse

Appliquez la Task d’analyse de vulnérabilités que vous avez créée précédemment :

kubectl apply -f vuln-scan-task.yaml

Mettre à Jour le Pipeline

Mettez à jour build-pipeline.yaml pour inclure l’analyse de vulnérabilités après l’étape de build :

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: secure-build
spec:
  params:
    - name: repo-url
      type: string
    - name: image
      type: string
  workspaces:
    - name: shared-workspace
  tasks:
    - name: build
      taskRef:
        name: git-clone-and-build
      params:
        - name: repo-url
          value: $(params.repo-url)
        - name: image
          value: $(params.image)
      workspaces:
        - name: source
          workspace: shared-workspace
    - name: vulnerability-scan
      runAfter:
        - build
      taskRef:
        name: vulnerability-scan
      params:
        - name: image
          value: $(params.image)

Appliquez le pipeline mis à jour :

kubectl apply -f build-pipeline.yaml

Tester avec une Image Vulnérable

Pour démontrer la détection de vulnérabilités par l’analyse, créez un Dockerfile qui utilise une image de base connue comme vulnérable et poussez un dépôt ou modifiez les paramètres en conséquence. Si l’image contient des vulnérabilités critiques, Grype fera échouer l’étape :

tkn pipelinerun logs -f --last
# [vulnerability-scan : scan] NAME             INSTALLED  FIXED-IN  TYPE  VULNERABILITY   SEVERITY
# [vulnerability-scan : scan] libcrypto3       3.0.12     3.0.13    apk   CVE-2024-0727   Critical
# [vulnerability-scan : scan] 1 critical vulnerability found
# [vulnerability-scan : scan] ERROR: failed to pass severity threshold
#
# TaskRun failed: step "scan" exited with code 1

Le pipeline échoue correctement à l’étape d’analyse, empêchant une image vulnérable d’être promue.

Tester avec une Image Corrigée

Exécutez maintenant le pipeline avec un dépôt contenant une image de base à jour. Lorsqu’aucune vulnérabilité critique n’est trouvée, l’analyse réussit :

tkn pipelinerun logs -f --last
# [vulnerability-scan : scan] No critical vulnerabilities found
# PipelineRun completed successfully

Le flux du pipeline est désormais : git-clone → build-push → vulnerability-scan. Seules les images qui passent l’analyse de vulnérabilités sont signées par Tekton Chains, car Chains ne traite que les TaskRuns réussis.

Exercice 6 : Signature sans Clé avec Fulcio (Avancé)

La gestion de clés de signature à longue durée de vie introduit de la complexité opérationnelle et des risques de sécurité. Fulcio de Sigstore fournit une signature sans clé en émettant des certificats de courte durée liés à une identité OIDC. Dans cet exercice, vous allez configurer Tekton Chains pour utiliser la signature sans clé.

Mettre à Jour la Configuration de Chains

Modifiez la configuration de Chains pour activer la signature sans clé :

kubectl patch configmap chains-config -n tekton-chains -p='{"data":{
  "signers.x509.fulcio.enabled": "true",
  "signers.x509.fulcio.address": "https://fulcio.sigstore.dev",
  "transparency.enabled": "true",
  "transparency.url": "https://rekor.sigstore.dev"
}}'

Vous devez également supprimer ou renommer le secret signing-secrets existant pour que Chains bascule en mode sans clé :

kubectl delete secret signing-secrets -n tekton-chains

Redémarrez le contrôleur Chains :

kubectl rollout restart deployment tekton-chains-controller -n tekton-chains

Configurer OIDC pour Chains

Chains a besoin d’un jeton OIDC pour s’authentifier auprès de Fulcio. Sur un service Kubernetes géré (GKE, EKS, AKS), vous pouvez utiliser l’identité de charge de travail (workload identity). Pour un cluster kind local, vous pouvez configurer Spiffe/SPIRE ou utiliser un fournisseur OIDC ambiant. La documentation de Tekton Chains fournit des instructions de configuration pour chaque environnement.

Pour une configuration de production GKE, le compte de service est automatiquement fédéré :

# Exemple : liaison d'identité de charge de travail GKE
gcloud iam service-accounts add-iam-policy-binding \
  tekton-chains-sa@your-project.iam.gserviceaccount.com \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:your-project.svc.id.goog[tekton-chains/tekton-chains-controller]"

Exécuter le Pipeline avec la Signature sans Clé

Déclenchez un nouveau PipelineRun :

kubectl create -f pipelinerun.yaml

Après l’achèvement, vérifiez avec la vérification sans clé en spécifiant l’identité attendue et l’émetteur OIDC :

cosign verify \
  --certificate-identity "https://kubernetes.io/namespaces/tekton-chains/serviceaccounts/tekton-chains-controller" \
  --certificate-oidc-issuer "https://your-oidc-issuer" \
  ghcr.io/your-username/tekton-lab:v2

La vérification repose désormais sur la chaîne de certificats de Fulcio plutôt que sur une paire de clés statique. Cette approche élimine entièrement la gestion des clés : chaque opération de signature obtient un certificat frais et de courte durée, et l’événement de signature est enregistré dans le journal de transparence Rekor pour l’auditabilité.

Exercice 7 : Appliquer les Images Signées au Déploiement

Signer les images n’est utile que si vous appliquez la vérification des signatures au moment du déploiement. Dans cet exercice, vous allez déployer le policy-controller de Sigstore pour rejeter toute image de conteneur qui ne possède pas de signature Tekton Chains valide.

Installer le Policy Controller de Sigstore

helm repo add sigstore https://sigstore.github.io/helm-charts
helm repo update

helm install policy-controller sigstore/policy-controller \
  --namespace cosign-system \
  --create-namespace \
  --set webhook.configMapName=policy-controller-config

Attendez que le policy controller soit prêt :

kubectl get pods -n cosign-system --watch

Créer une Politique d’Image

Créez une ClusterImagePolicy qui exige que les images soient signées par votre clé Tekton Chains. Enregistrez ceci sous image-policy.yaml :

apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
  name: tekton-chains-signed
spec:
  images:
    - glob: "ghcr.io/your-username/**"
  authorities:
    - key:
        data: |
          -----BEGIN PUBLIC KEY-----
          YOUR_COSIGN_PUBLIC_KEY_HERE
          -----END PUBLIC KEY-----
      attestations:
        - name: must-have-slsa-provenance
          predicateType: "https://slsa.dev/provenance/v0.2"
          policy:
            type: cue
            data: |
              predicateType: "https://slsa.dev/provenance/v0.2"

Remplacez la clé publique par la clé publique Cosign que vous avez générée précédemment :

# Extraire la clé publique
kubectl get secret signing-secrets -n tekton-chains -o jsonpath='{.data.cosign\.pub}' | base64 -d

Appliquez la politique :

kubectl apply -f image-policy.yaml

Appliquer la Politique sur un Namespace

Labellisez un namespace pour activer l’application de la politique :

kubectl create namespace secure-apps
kubectl label namespace secure-apps policy.sigstore.dev/include=true

Test : Déployer une Image Signée

Déployez l’image qui a été signée par Tekton Chains :

kubectl run signed-app \
  --image=ghcr.io/your-username/tekton-lab:v1 \
  --namespace=secure-apps
# pod/signed-app created

Le déploiement réussit car l’image possède une signature et une attestation de provenance valides.

Test : Déployer une Image Non Signée

Essayez maintenant de déployer une image qui n’a pas été signée :

kubectl run unsigned-app \
  --image=ghcr.io/your-username/unsigned-image:latest \
  --namespace=secure-apps
# Error from server (BadRequest): admission webhook "policy.sigstore.dev" denied the request:
# validation failed: failed policy: tekton-chains-signed:
# spec.containers[0].image ghcr.io/your-username/unsigned-image:latest
# signature key validation failed for authority

Le webhook d’admission rejette correctement l’image non signée. Cela boucle la boucle : les images sont automatiquement signées pendant le build, et seules les images signées peuvent être déployées.

Nettoyage

Lorsque vous avez terminé le lab, nettoyez les ressources :

# Supprimer Tekton Chains
kubectl delete -f https://storage.googleapis.com/tekton-releases/chains/latest/release.yaml

# Supprimer Tekton Pipelines
kubectl delete -f https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

# Supprimer le policy controller
helm uninstall policy-controller -n cosign-system
kubectl delete namespace cosign-system

# Supprimer le cluster kind
kind delete cluster --name tekton-lab

Points Clés à Retenir

  • Tekton Chains fournit une sécurité de la chaîne d’approvisionnement sans configuration. Une fois installé et configuré, il signe automatiquement chaque résultat de TaskRun et génère la provenance SLSA — sans aucune modification de pipeline requise.
  • La provenance SLSA relie les artefacts à leur processus de build. L’attestation in-toto enregistre exactement quelle source, quelles étapes et quels outils ont produit un artefact, créant une chaîne de traçabilité auditable.
  • La vérification avec Cosign est simple. Une seule commande valide qu’une image a été signée par votre instance Tekton Chains et n’a pas été altérée depuis.
  • La signature sans clé élimine la gestion des clés. En s’intégrant avec Fulcio et Rekor, vous pouvez signer des artefacts avec des certificats de courte durée liés à l’identité de la charge de travail, supprimant la charge de rotation et de sécurisation des clés à longue durée de vie.
  • L’analyse de vulnérabilités comme porte de contrôle du pipeline empêche les déploiements non sécurisés. L’ajout de Grype ou d’un scanner similaire comme étape de pipeline garantit que seules les images exemptes de vulnérabilités critiques passent à la signature et au déploiement.
  • Le contrôle d’admission applique la politique. L’utilisation du policy-controller de Sigstore comme webhook d’admission Kubernetes garantit que seules les images correctement signées et attestées peuvent s’exécuter dans votre cluster, bouclant la boucle de sécurité du build au déploiement.

Prochaines Étapes

Continuez à renforcer vos connaissances en sécurité de la chaîne d’approvisionnement avec ces guides connexes :