Módulo 6: Supply Chain Sbom And Signing

1. Introducción: la cadena de suministro que nadie enseña

Descripción

Los cinco módulos anteriores endurecieron capas distintas de andes-cargo-infra/: identidad federada (M2), secretos (M3), políticas propias sobre el plan (M4), reglas de la comunidad sobre el HCL declarado (M5). Ninguno de los cinco, hasta ahora, se hizo la pregunta que este módulo abre: el .zip que Lambda ejecuta en producción — lambda/function.zip, 890 bytes, el mismo que terraform-and-iac-guide generó con data "archive_file" — ¿cómo sabes que es exactamente el código que tu equipo escribió, y no algo que alguien alteró en el camino entre tu laptop y la nube?

Hoy, la respuesta honesta es: no lo sabes. andes-cargo-infra/ no tiene, todavía, ningún mecanismo que lo garantice. Ese es, literalmente, el hallazgo TM-02 de THREAT-MODEL.md (Módulo 1): "Tampering: function.zip deployment artifact unsigned" — la única fila de cadena de suministro de toda la matriz de riesgos, y la que este módulo cierra.

Conexión con el módulo

Este módulo construye dos cosas distintas que, juntas, responden esa pregunta: un SBOM (Software Bill of Materials, lecciones 2 y 3) — la lista completa y verificable de qué contiene el proyecto que se despliega, incluidas las dependencias que nadie escribió a mano — y una firma criptográfica con cosign/Sigstore (lecciones 4 a 7) sobre el artefacto exacto que Lambda ejecuta, verificable sin depender de ningún registro de pago. La lección 8 integra ambas piezas como un job verify-artifact en el apply.yml heredado de cicd-and-gitops-on-aws-guide — el punto donde, por primera vez en esta guía, un apply puede rechazarse no por lo que el plan dice que va a cambiar (eso ya lo hace conftest, Módulo 4), sino por si el artefacto que se está a punto de desplegar es, de verdad, el que alguien firmó.


La cita que motiva este módulo, completa

src/paths/aws-cloud-ecosystem/VALIDACION.md — la misma auditoría de mercado que fija el peso de cada módulo de esta guía — no deja ambigüedad sobre dónde está parada la competencia frente a esto:

"IAM y radio de explosión son consenso en foros y la habilidad de seguridad que sí se usa a diario; el vector dominante de 2026 ya no es el humano descuidado sino el agente con credenciales [...]. Y el hueco de competencia es total: Seguridad de cadena de suministro: cero. Ningún temario menciona SBOM, firma de imágenes (cosign/Sigstore), escaneo (Trivy) ni —lo más grave— autenticación OIDC de GitHub Actions hacia AWS en lugar de claves de larga vida. Se sigue enseñando el antipatrón."

Léelo con precisión: no dice que la competencia enseña esto "de forma superficial" o "sin profundidad". Dice cero — ningún temario relevado menciona ninguna de las tres piezas (SBOM, firma con cosign/Sigstore, escaneo con Trivy). El Módulo 5 ya cerró la pieza de escaneo. Este módulo cierra las dos que quedan: SBOM y firma. Cuando termines la lección 8, vas a tener, en tu propio portfolio, exactamente lo que la auditoría dice que no existe en ningún temario de la competencia.


Lo que ya construiste, y lo que todavía falta: dónde vive TM-02

RISK-MAP.md (Módulo 1, lección 8) llega a este módulo con cinco de siete filas resueltas:

  1  TM-01  Spoofing                 Long-lived pipeline credentials     Resolved (M2)
  2  TM-07  Elevation of privilege   AppServerRole broader than needed   Resolved (M2.7)
  3  TM-05  Information disclosure   Plaintext credentials on disk       Resolved (M3)
  4  TM-04  Information disclosure   S3 bucket, no public-access block   Resolved (M4.7)
  5  TM-06  Denial of service        No control blocks destroy(Shipments)Resolved (M4.6)
  6  TM-02  Tampering                function.zip deployment unsigned    Open        ← este módulo
  7  TM-03  Repudiation              No CloudTrail trail                 Open        (M7)

El Módulo 5, como ya sabes por su propia introducción, no cierra ninguna fila — su valor es cobertura de reglas de la comunidad, no resolución de un hallazgo propio de Andes Cargo. Este módulo sí cierra una: TM-02, la única fila de la categoría Tampering (manipulación) de todo el modelo de amenazas. Al final de la lección 8, RISK-MAP.md va a mostrar seis de siete filas resueltas — solo TM-03 (CloudTrail, Módulo 7) va a seguir abierta.


Por qué este riesgo importa más de lo que parece a primera vista

Es fácil subestimar TM-02 porque, a diferencia de un bucket público (TM-04) o una tabla sin protección contra destroy (TM-06), no hay una consola donde "ver" el problema — el .zip simplemente existe en disco, se sube, y Lambda lo ejecuta. Pero considera la cadena completa de manos por las que pasa ese archivo antes de ejecutarse: tu editor lo escribe, git lo versiona, un runner de CI lo empaqueta con terraform plan, ese mismo runner (u otro distinto, en apply.yml) lo aplica contra AWS. En cualquiera de esos puntos —una dependencia de npm/pip comprometida en el runner, un Action de terceros con una versión maliciosa, un compañero de equipo con acceso de escritura al repositorio que no debería tenerlo— el contenido de ese .zip puede cambiar sin que nadie lo note, y Lambda lo ejecutaría de todas formas, sin preguntar.

Este es, literalmente, el mismo patrón de ataque que la lección 5 de cicd-and-gitops-on-aws-guide (Módulo 2) ya nombró sin resolverlo del todo:

"Fijar por SHA protege contra dos escenarios reales [...]: un mantenedor legítimo comete un error y publica una versión rota [...]. Un ataque de cadena de suministro: si la cuenta de un mantenedor se ve comprometida, quien tenga acceso puede reasignar un tag público [...] a un commit malicioso [...]. Lo que esta lección NO construye: un sistema completo de gestión de cadena de suministro —verificación de firmas, SBOM [...], herramientas como Dependabot [...]—. Eso es contenido de cloud-security-and-guardrails-guide, vinculada y no reescrita aquí."

Esa lección te dejó con una mitad del problema resuelta —las Actions de terceros que tu workflow invoca están fijadas por SHA, no por tag móvil— pero con la otra mitad abierta: nada, hasta este módulo, protege el artefacto que tu propio pipeline produce. Fijar por SHA evita que el código de un tercero cambie bajo tus pies; firmar con cosign evita que tu propio artefacto cambie bajo los pies de quien lo despliega. Son dos capas de la misma disciplina, y este módulo practica ambas: cada Action nueva que este módulo agrega al apply.yml heredado —vas a verla en la lección 8— está fijada por SHA de commit completo, exactamente como esa lección enseñó, no por un tag @v4 conveniente.


Las ocho lecciones de este módulo

   CONCEPTUAL              MANOS A LA OBRA (SBOM)      CONCEPTUAL              MANOS A LA OBRA (FIRMA)
   ──────────              ───────────────────────      ──────────              ───────────────────────
   1. Esta introducción     3. Generando el SBOM         4. Sigstore: keyless    5. cosign + keypair local
                                de Andes Cargo               vs. keypair            6. Firmar y verificar
   2. Qué es un SBOM                                                              7. Rompiendo la cadena
      y por qué importa                                                             a propósito

                              8. Proyecto: el paquete de cadena de suministro
                                 (SBOM + firma + verify-artifact en apply.yml)
  1. Esta introducción — el hueco de mercado, la conexión con TM-02 y con cicd-and-gitops-on-aws-guide M2.5.
  2. Qué es un SBOM y por qué importa — SPDX/CycloneDX, la analogía de la lista de ingredientes, qué responde un SBOM que un requirements.txt de un desarrollador no responde.
  3. Manos a la obra: generando el SBOM de Andes Cargotrivy fs --format cyclonedx, ejecutado de verdad sobre lambda/, con salida literal.
  4. Qué resuelve Sigstore: keyless frente a keypair — por qué esta guía firma con un keypair local, no con identidad OIDC efímera.
  5. Manos a la obra: instalando cosign y un keypair localcosign generate-key-pair, la password interactiva resuelta sin bloquear la automatización.
  6. Manos a la obra: firmando y verificando el artefacto de desplieguecosign sign-blob/verify-blob sobre lambda/function.zip, 100% offline, Verified OK.
  7. Manos a la obra: rompiendo la cadena a propósito — el .zip alterado después de firmado, la verificación fallando en vivo.
  8. Proyecto: el paquete de cadena de suministro de Andes Cargo — SBOM + firma + un job verify-artifact nuevo en apply.yml, corrido con act, cerrando TM-02.

Lo que este módulo NO construye

Con la misma honestidad que gobierna toda esta guía: este módulo no firma imágenes de contenedor (Andes Cargo no las tiene — el handler se empaqueta en .zip, no en imagen Docker, tal como aclara la frontera con kubernetes-and-eks-in-production-guide en el diseño de esta guía) ni construye un registro de artefactos propio (no hace falta uno: cosign sign-blob/verify-blob operan sobre el archivo en disco directamente, sin publicarlo en ningún sitio). Tampoco usa la identidad OIDC efímera de Sigstore ("keyless") — la lección 4 explica exactamente por qué, y la razón no es una limitación técnica de esta guía sino una elección deliberada: la misma limitación de LocalStack Hobby que el Módulo 2, lección 6, ya documentó (la validación real de un JWT de GitHub Actions no se puede probar sin una cuenta AWS real) haría que firmar "keyless" en este laboratorio fuera, en el mejor de los casos, una simulación a medias. Un keypair local generado en tu propia máquina evita depender de esa limitación por completo, y sigue siendo Sigstore de verdad: el mismo cosign, la misma especificación de bundle, la misma verificación criptográfica.


Errores comunes

Pensar que "cadena de suministro" es solo sobre las dependencias de terceros (npm, pip), no sobre el código propio (de alcance, el más importante de este módulo). Qué pasa: alguien, al escuchar "supply chain security", asume que este módulo es exclusivamente sobre vulnerabilidades en boto3 o en Actions de terceros. Cómo detectarlo: si tu mapa mental de este módulo no incluye la palabra "firma" aplicada al código que tu propio equipo escribió. Cómo corregirlo: TM-02 —el hallazgo que este módulo cierra— es sobre el .zip que Andes Cargo produce, no sobre una dependencia externa. La cadena de suministro completa incluye ambos extremos: qué entra al proyecto (dependencias, cubierto en parte por el SBOM de la lección 3) y qué sale de él hacia producción (el artefacto firmado, lecciones 5 a 7). Un SBOM sin firma te dice qué hay adentro del paquete, pero no si el paquete es el que tu equipo realmente produjo; una firma sin SBOM te confirma que el paquete no cambió, pero no qué contiene. Este módulo construye las dos.

Esperar que este módulo firme algo que corre en un registro de contenedores (de expectativa, por familiaridad con tutoriales de cosign orientados a Docker). Qué pasa: la mayoría del contenido público sobre cosign en internet usa ejemplos de imágenes de contenedor (cosign sign <imagen>@sha256:...), y alguien llega a este módulo esperando ese mismo flujo. Cómo detectarlo: si buscas, en las lecciones 5 a 7, un paso que hable de un registro OCI o de docker push. Cómo corregirlo: el artefacto que este módulo firma no es una imagen de contenedor sino un archivo .zip en disco (el handler de process-shipment-manifest, empaquetado por Lambda), y el comando correcto es cosign sign-blob/verify-blob (firma de "blobs" genéricos), no cosign sign/verify (el subcomando orientado a imágenes OCI). Son dos familias de comandos distintas dentro de la misma herramienta, para dos tipos de artefacto distintos.


Ejercicios

Ejercicio 1 — Ubica TM-02 en las tres capas de STRIDE que ya construiste. Sin mirar THREAT-MODEL.md, explica por qué TM-02 se clasifica como Tampering y no como alguna de las otras cinco categorías de STRIDE (Spoofing, Repudiation, Information disclosure, Denial of service, Elevation of privilege).

Ver solución

Tampering (manipulación) es, específicamente, la categoría de STRIDE que cubre la alteración no autorizada de datos o código — exactamente el riesgo de que alguien cambie el contenido de function.zip entre el momento en que tu equipo lo escribe y el momento en que Lambda lo ejecuta. No es Spoofing (eso sería alguien haciéndose pasar por una identidad legítima, el riesgo que resolvió el Módulo 2 con OIDC) ni Information disclosure (eso sería una fuga de datos, el riesgo que resolvieron el Módulo 3 y el TM-04 del Módulo 4) ni Repudiation (eso es sobre la ausencia de un registro atribuible, el riesgo que el Módulo 7 va a resolver con CloudTrail). La firma de este módulo responde, punto por punto, a la definición exacta de Tampering: una forma de detectar, matemáticamente, si el contenido de un archivo cambió después de un punto de referencia conocido.

Ejercicio 2 — Explica, con tus propias palabras, la diferencia entre "fijar por SHA" (M2.5 de cicd-and-gitops-on-aws-guide) y "firmar con cosign" (este módulo). Un compañero pregunta si no son, en el fondo, lo mismo: "las dos cosas evitan que algo cambie sin que te des cuenta". ¿Qué le responderías?

Ver solución

Una respuesta completa distingue quién produce cada artefacto y quién lo verifica. Fijar por SHA (uses: actions/checkout@11bd719...) protege contra cambios en código de terceros que tu workflow invoca — el mantenedor del repositorio ajeno podría reasignar un tag, y el SHA fijo evita que eso te afecte; la verificación la hace Git mismo, comparando el SHA que pediste contra el commit real, de forma automática y sin pasos extra. Firmar con cosign protege el artefacto que tu propio equipo produce — nadie más "reasigna" nada, el riesgo es que el .zip se altere en algún punto de tu propia cadena de CI/CD (una dependencia comprometida en el runner, un acceso de escritura indebido); la verificación (cosign verify-blob) es un paso explícito que alguien —o un job de pipeline— tiene que ejecutar deliberadamente, no ocurre de forma automática como con un SHA de Git. Ambas son la misma disciplina de fondo —nunca confiar en un artefacto sin poder demostrar de dónde vino—, aplicada a dos superficies distintas de la misma cadena de suministro.

Ejercicio 3 — Predice qué fila de RISK-MAP.md va a quedar como la única abierta al cerrar este módulo, y por qué. Sin mirar la tabla de arriba otra vez, ¿qué TM- identificador esperarías que siga en Open después de la lección 8 de este módulo, y en qué módulo se resolvería?

Ver solución

TM-03 (Repudiation, la ausencia de un trail de CloudTrail atribuible) es la única fila que sigue Open después de este módulo — se resuelve, hasta donde LocalStack Hobby lo permite, en el Módulo 7 (guardrails detectivos). El razonamiento del propio RISK-MAP.md (Módulo 1, lección 8, sección Alternatives considered) ya lo anticipó: los controles preventivos (identidad, secretos, política, cadena de suministro — M2, M3, M4, M6) se construyen antes que los detectivos (auditoría — M7), porque un control que evita que algo malo ocurra vale más, en el orden de esta guía, que uno que solo deja registro de que ocurrió. El Módulo 5 no cuenta para este ejercicio porque, como ya sabes, no cierra ninguna fila propia.


Resumen y siguiente paso

Esta introducción estableció el terreno completo de este módulo: el hueco de mercado citado textualmente de VALIDACION.md ("cero" en toda la competencia, sobre SBOM, cosign/Sigstore y Trivy juntos), la fila TM-02 de THREAT-MODEL.md que este módulo existe para cerrar, y la conexión directa con la práctica de SHA-pinning que cicd-and-gitops-on-aws-guide (Módulo 2, lección 5) nombró y dejó, explícitamente, para esta guía. Viste el mapa completo de las ocho lecciones: dos conceptuales sobre SBOM, dos conceptuales sobre firma, cuatro manos a la obra que ejecutan de verdad trivy fs y cosign contra el artefacto real de Andes Cargo.

Antes de avanzar deberías poder: explicar por qué TM-02 es la única fila de Tampering en todo el modelo de amenazas; distinguir el propósito de fijar por SHA del propósito de firmar con cosign; y recitar, sin mirar la cita, la frase exacta de VALIDACION.md que motiva este módulo.

La lección 2 abre la primera mitad del módulo: qué es, exactamente, un SBOM, y por qué un archivo requirements.txt escrito a mano no responde las mismas preguntas.

Recursos

  1. src/paths/aws-cloud-ecosystem/VALIDACION.md — la auditoría de mercado citada en esta lección, fuente del hallazgo "cero" en cadena de suministro que motiva este módulo completo.
  2. Este curso, Módulo 1, THREAT-MODEL.md y RISK-MAP.md — el hallazgo TM-02 y su posición en la secuencia de resolución de riesgos que este módulo cierra.
  3. cicd-and-gitops-on-aws-guide, Módulo 2, lección 5 (05-actions-marketplace-uses-and-with.md) — el pinning por SHA de Actions de terceros, la mitad de la disciplina de cadena de suministro que esa guía sí construyó, y el pointer textual hacia esta guía para la otra mitad.
  4. Sigstore — Documentación oficial de cosign — punto de entrada a la documentación que las lecciones 4 a 7 de este módulo citan en detalle.
  5. Trivy — Documentación oficial — la misma herramienta del Módulo 5, aplicada aquí a un propósito distinto: generar un SBOM, no escanear configuración.