Lab: Implementacion de un pipeline de construccion seguro con Tekton y Tekton Chains

Descripcion general

Tekton es un potente framework de codigo abierto, nativo de Kubernetes, para crear sistemas de integracion continua y entrega continua (CI/CD). Se ejecuta como un conjunto de Custom Resource Definitions (CRDs) en cualquier cluster de Kubernetes, permitiendote definir pipelines como YAML declarativo que son portables entre entornos.

Tekton Chains es un proyecto complementario que agrega seguridad automatica de la cadena de suministro a tus pipelines de Tekton. Una vez instalado, Chains observa los TaskRuns completados, firma automaticamente sus resultados usando Cosign u otros firmantes, y genera atestaciones de procedencia SLSA — todo sin requerir ningun cambio en tus definiciones de pipeline existentes.

En este laboratorio practico, haras lo siguiente:

  • Desplegar Tekton Pipelines y Tekton Chains en un cluster local de Kubernetes
  • Configurar Chains para firmar automaticamente artefactos y generar procedencia in-toto
  • Construir una imagen de contenedor a traves de un Tekton Pipeline
  • Verificar la firma y la procedencia SLSA generadas automaticamente
  • Agregar un paso de escaneo de vulnerabilidades al pipeline
  • Explorar la firma sin claves con Sigstore Fulcio
  • Aplicar politicas de imagenes firmadas en el momento del despliegue

Al final de este laboratorio, tendras un pipeline de construccion seguro completamente funcional que produce imagenes de contenedor firmadas y atestadas con procedencia verificable — logrando el cumplimiento de SLSA Level 2 automaticamente.

Requisitos previos

Antes de comenzar este laboratorio, asegurate de tener las siguientes herramientas instaladas en tu estacion de trabajo:

  • Cluster de Kubernetes — Usaremos kind (Kubernetes in Docker) para un cluster local. Alternativamente, minikube tambien funciona.
  • kubectl — El CLI de Kubernetes, version 1.26 o posterior.
  • Helm — El gestor de paquetes de Kubernetes, version 3.x.
  • tkn — El CLI de Tekton, utilizado para interactuar con los recursos de Tekton.
  • Cosign — Parte del proyecto Sigstore, utilizado para firmar y verificar imagenes de contenedor.
  • jq — Un procesador JSON de linea de comandos para inspeccionar los payloads de procedencia.
  • Un registro de contenedores — Un registro al que puedas hacer push, como GitHub Container Registry (GHCR) o Docker Hub. Necesitaras acceso de escritura y credenciales validas.

Este laboratorio asume familiaridad con los conceptos basicos de Kubernetes (pods, namespaces, configmaps) y conceptos generales de CI/CD.

Configuracion del entorno

Paso 1: Crear un cluster kind

Comienza creando un cluster de Kubernetes nuevo usando kind:

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

Confirma que el cluster esta en ejecucion:

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

Paso 2: Instalar Tekton Pipelines

Instala la ultima version de Tekton Pipelines:

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

Espera a que los pods de Tekton Pipelines esten listos:

kubectl get pods -n tekton-pipelines --watch

Deberias ver los pods tekton-pipelines-controller y tekton-pipelines-webhook en ejecucion:

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

Paso 3: Instalar Tekton Chains

Instala Tekton Chains en su propio namespace:

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

Verifica que Chains esta en ejecucion:

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

En este punto, tanto Tekton Pipelines como Tekton Chains estan ejecutandose en tu cluster.

Ejercicio 1: Configurar Tekton Chains para firma con Cosign

Tekton Chains necesita una clave de firma y configuracion para saber como y donde almacenar firmas y atestaciones. En este ejercicio, generaras un par de claves Cosign y configuraras Chains para usar almacenamiento OCI con el formato de atestacion in-toto.

Generar un par de claves Cosign

Cosign puede generar un par de claves y almacenarlo directamente como un Secret de Kubernetes en el namespace tekton-chains:

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

Se te pedira que ingreses una contrasena para la clave privada. Para este laboratorio, puedes presionar Enter para dejarla vacia. Cosign crea un Secret llamado signing-secrets que contiene la clave privada, la clave publica y la contrasena.

Verifica que el secret fue creado:

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

Configurar almacenamiento y formato de Chains

A continuacion, configura Chains para almacenar firmas en el registro OCI junto con la imagen y para generar procedencia en el formato 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"}}'

Esta configuracion le indica a Chains que:

  • artifacts.oci.storage: oci — Almacene las firmas de artefactos OCI en el registro OCI
  • artifacts.taskrun.format: in-toto — Genere atestaciones en el formato in-toto, que es el estandar para la procedencia SLSA
  • artifacts.taskrun.storage: oci — Almacene las atestaciones de TaskRun en el registro OCI

Reiniciar el controlador de Chains

Despues de cambiar la configuracion, reinicia el controlador de Chains para que aplique los nuevos ajustes:

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

Como funciona Chains

Con Chains configurado, esto es lo que sucede automaticamente cada vez que un TaskRun se completa:

  1. El controlador de Chains detecta el TaskRun completado.
  2. Inspecciona los resultados del TaskRun en busca de referencias de imagenes OCI (especificamente resultados llamados IMAGE_URL e IMAGE_DIGEST).
  3. Firma la imagen usando la clave Cosign almacenada en el Secret signing-secrets.
  4. Genera una atestacion de procedencia in-toto que captura los detalles de la construccion.
  5. Sube la firma y la atestacion al registro OCI.
  6. Anota el TaskRun con chains.tekton.dev/signed=true.

Nada de esto requiere ninguna modificacion a tus Tasks o Pipelines.

Ejercicio 2: Crear un pipeline de construccion

Ahora crearas un Tekton Pipeline que clona un repositorio Git y construye una imagen de contenedor usando Kaniko. Primero, configura las credenciales del registro para que Tekton pueda hacer push de imagenes.

Configurar credenciales del registro

Crea un Secret de Kubernetes con tus credenciales del registro. Reemplaza los valores de ejemplo con los datos reales de tu registro:

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"}]}'

Crear el Task de construccion

Crea un archivo llamado build-task.yaml. Este Task acepta una URL de repositorio Git, un nombre de imagen destino, y usa Kaniko para construir y subir la imagen:

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)"

Aplica el Task:

kubectl apply -f build-task.yaml

Crear el Task de escaneo de vulnerabilidades (para uso posterior)

Crea vuln-scan-task.yaml — lo agregaras al pipeline en un ejercicio posterior:

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

Crear el Pipeline

Crea build-pipeline.yaml que encadena los pasos de clonacion y construccion:

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

Aplica el Pipeline:

kubectl apply -f build-pipeline.yaml

Ejecutar el Pipeline

Crea un PipelineRun para ejecutar el pipeline. Reemplaza la referencia de imagen con tu registro:

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

Guarda esto como pipelinerun.yaml y crealo:

kubectl create -f pipelinerun.yaml

Monitorea la ejecucion del 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

La construccion deberia completarse exitosamente. Tambien puedes verificar el estado del PipelineRun:

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

Ejercicio 3: Verificar la firma automatica

Una vez que el PipelineRun se completa, Tekton Chains detecta automaticamente el TaskRun completado, firma la imagen construida y anota el TaskRun. Todo esto sucede en segundo plano — no se necesitan cambios en el pipeline.

Esperar a que Chains firme

Chains procesa los TaskRuns completados de forma asincrona. Espera unos momentos, luego verifica las anotaciones del TaskRun:

# Get the TaskRun name from the PipelineRun
TASKRUN=$(kubectl get taskrun -l tekton.dev/pipeline=secure-build -o name --sort-by=.metadata.creationTimestamp | tail -1)
echo $TASKRUN

# Check if Chains has signed it
kubectl get $TASKRUN -o jsonpath='{.metadata.annotations.chains\.tekton\.dev/signed}'

La salida deberia ser:

true

Si aun muestra vacio, espera unos segundos e intenta de nuevo — Chains necesita tiempo para procesar la firma.

Verificar la firma con Cosign

Ahora verifica la firma de la imagen usando la clave publica del par de claves Cosign que generaste anteriormente:

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

Deberias ver una salida confirmando que la verificacion fue exitosa:

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":{}}]

Inspeccionar las anotaciones del TaskRun

Chains anota el TaskRun con metadatos detallados sobre la operacion de firma:

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

Las anotaciones clave incluyen:

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

La anotacion chains.tekton.dev/signed=true confirma que Chains proceso y firmo exitosamente este TaskRun. Si se configuro un log de transparencia, tambien veras una referencia a una entrada del log de Rekor.

Ejercicio 4: Inspeccionar la procedencia SLSA

Mas alla de las firmas simples, Tekton Chains genera atestaciones completas de procedencia SLSA. Estas atestaciones describen como se construyo el artefacto — que fuente se uso, que pasos de construccion se ejecutaron y que herramientas estuvieron involucradas.

Obtener la atestacion de procedencia

Usa Cosign para verificar y recuperar la atestacion 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 .

Comprender la estructura de la procedencia

La atestacion de procedencia sigue el formato in-toto Statement con un predicado de procedencia SLSA. Aqui hay un desglose de los campos clave:

{
  "_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": "..." }
      }
    ]
  }
}

Veamos cada campo en detalle:

  • subject — El artefacto que se produjo, identificado por su URL de registro y digest SHA-256. Esto es sobre lo que trata la procedencia.
  • builder.id — Identifica el sistema de construccion. Tekton Chains establece esto como https://tekton.dev/chains/v2.
  • buildConfig.steps — Registra cada paso que se ejecuto en el TaskRun, incluyendo las imagenes de contenedor exactas utilizadas (fijadas por digest).
  • materials — Lista los artefactos de entrada consumidos durante la construccion, como las imagenes base. Cada material incluye un digest para la reproducibilidad.
  • invocation.parameters — Captura los parametros pasados al TaskRun, mostrando exactamente que entradas impulsaron la construccion.

Estos datos de procedencia satisfacen los requisitos de SLSA Level 2: el proceso de construccion se define en un servicio de construccion (Tekton), y la procedencia es generada automaticamente por Tekton Chains (no por el script de construccion en si). La procedencia esta firmada, proporcionando evidencia contra manipulaciones.

Ejercicio 5: Agregar un Task de escaneo de vulnerabilidades

Un pipeline seguro no solo debe firmar artefactos, sino tambien verificar que estan libres de vulnerabilidades conocidas antes del despliegue. En este ejercicio, agregaras un paso de escaneo de vulnerabilidades Grype al pipeline.

Aplicar el Task de escaneo

Aplica el Task de escaneo de vulnerabilidades que creaste anteriormente:

kubectl apply -f vuln-scan-task.yaml

Actualizar el Pipeline

Actualiza build-pipeline.yaml para incluir el escaneo de vulnerabilidades despues del paso de construccion:

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)

Aplica el pipeline actualizado:

kubectl apply -f build-pipeline.yaml

Probar con una imagen vulnerable

Para demostrar que el escaneo detecta vulnerabilidades, crea un Dockerfile que use una imagen base con vulnerabilidades conocidas y sube un repositorio o modifica los parametros segun corresponda. Si la imagen contiene vulnerabilidades criticas, Grype fallara el paso:

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

El pipeline falla correctamente en el paso de escaneo, evitando que una imagen vulnerable sea promovida.

Probar con una imagen parcheada

Ahora ejecuta el pipeline contra un repositorio con una imagen base actualizada. Cuando no se encuentran vulnerabilidades criticas, el escaneo pasa:

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

El flujo del pipeline ahora es: git-clone → build-push → vulnerability-scan. Solo las imagenes que pasan el escaneo de vulnerabilidades son firmadas por Tekton Chains, porque Chains solo procesa TaskRuns exitosos.

Ejercicio 6: Firma sin claves con Fulcio (Avanzado)

Gestionar claves de firma de larga duracion introduce complejidad operativa y riesgo de seguridad. Fulcio de Sigstore proporciona firma sin claves emitiendo certificados de corta duracion vinculados a una identidad OIDC. En este ejercicio, configuraras Tekton Chains para usar firma sin claves.

Actualizar la configuracion de Chains

Modifica la configuracion de Chains para habilitar la firma sin claves:

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"
}}'

Tambien necesitas eliminar o renombrar el secret signing-secrets existente para que Chains recurra al modo sin claves:

kubectl delete secret signing-secrets -n tekton-chains

Reinicia el controlador de Chains:

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

Configurar OIDC para Chains

Chains necesita un token OIDC para autenticarse con Fulcio. En un servicio de Kubernetes gestionado (GKE, EKS, AKS), puedes usar workload identity. Para un cluster kind local, puedes configurar Spiffe/SPIRE o usar un proveedor OIDC ambiental. La documentacion de Tekton Chains proporciona instrucciones de configuracion para cada entorno.

Para una configuracion de produccion en GKE, la cuenta de servicio se federa automaticamente:

# Example: GKE workload identity binding
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]"

Ejecutar el Pipeline con firma sin claves

Lanza un nuevo PipelineRun:

kubectl create -f pipelinerun.yaml

Despues de completarse, verifica con verificacion sin claves especificando la identidad esperada y el emisor 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 verificacion ahora se basa en la cadena de certificados de Fulcio en lugar de un par de claves estatico. Este enfoque elimina completamente la gestion de claves: cada operacion de firma obtiene un certificado nuevo de corta duracion, y el evento de firma se registra en el log de transparencia de Rekor para auditabilidad.

Ejercicio 7: Aplicar imagenes firmadas en el despliegue

Firmar imagenes solo es util si aplicas la verificacion de firmas en el momento del despliegue. En este ejercicio, desplegaras el policy-controller de Sigstore para rechazar cualquier imagen de contenedor que carezca de una firma valida de Tekton Chains.

Instalar el 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

Espera a que el policy controller este listo:

kubectl get pods -n cosign-system --watch

Crear una politica de imagenes

Crea una ClusterImagePolicy que requiera que las imagenes esten firmadas por tu clave de Tekton Chains. Guarda esto como 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"

Reemplaza la clave publica con la clave publica de Cosign que generaste anteriormente:

# Extract the public key
kubectl get secret signing-secrets -n tekton-chains -o jsonpath='{.data.cosign\.pub}' | base64 -d

Aplica la politica:

kubectl apply -f image-policy.yaml

Aplicar la politica en un namespace

Etiqueta un namespace para habilitar la aplicacion de la politica:

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

Prueba: Desplegar una imagen firmada

Despliega la imagen que fue firmada por Tekton Chains:

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

El despliegue tiene exito porque la imagen tiene una firma valida y una atestacion de procedencia.

Prueba: Desplegar una imagen sin firmar

Ahora intenta desplegar una imagen que no fue firmada:

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

El webhook de admision rechaza correctamente la imagen sin firmar. Esto cierra el ciclo: las imagenes se firman automaticamente durante la construccion, y solo las imagenes firmadas pueden ser desplegadas.

Limpieza

Cuando hayas terminado con el laboratorio, limpia los recursos:

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

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

# Delete the policy controller
helm uninstall policy-controller -n cosign-system
kubectl delete namespace cosign-system

# Delete the kind cluster
kind delete cluster --name tekton-lab

Conclusiones clave

  • Tekton Chains proporciona seguridad de la cadena de suministro sin configuracion adicional. Una vez instalado y configurado, firma automaticamente cada resultado de TaskRun y genera procedencia SLSA — sin necesidad de modificar los pipelines.
  • La procedencia SLSA conecta los artefactos con su proceso de construccion. La atestacion in-toto registra exactamente que fuente, pasos y herramientas produjeron un artefacto, creando una cadena de custodia auditable.
  • La verificacion con Cosign es sencilla. Un solo comando valida que una imagen fue firmada por tu instancia de Tekton Chains y que no ha sido manipulada desde entonces.
  • La firma sin claves elimina la gestion de claves. Al integrarse con Fulcio y Rekor, puedes firmar artefactos con certificados de corta duracion vinculados a la identidad del workload, eliminando la carga de rotar y asegurar claves de larga duracion.
  • El escaneo de vulnerabilidades como puerta del pipeline previene despliegues inseguros. Agregar Grype o un escaner similar como paso del pipeline asegura que solo las imagenes libres de vulnerabilidades criticas procedan a la firma y el despliegue.
  • El control de admision aplica la politica. Usar el policy-controller de Sigstore como webhook de admision de Kubernetes asegura que solo las imagenes debidamente firmadas y atestadas puedan ejecutarse en tu cluster, cerrando el ciclo de seguridad desde la construccion hasta el despliegue.

Proximos pasos

Continua fortaleciendo tus conocimientos sobre seguridad de la cadena de suministro con estas guias relacionadas: