Módulo 8: Capstone The Andes Cargo Security Gate
1. Introducción al capstone
Descripción
Siete módulos construyeron siete piezas por separado. Este último módulo no agrega una octava pieza — las encadena. Vas a tomar conftest (Módulo 4), Trivy (Módulo 5) y cosign (Módulo 6) y convertirlos en tres jobs de un mismo pipeline de GitHub Actions, corridos en orden, cada uno condicionado a que el anterior haya pasado. Al final de este módulo, andes-cargo-infra/ tiene un security gate real: un cambio no llega a apply sin atravesar política, escaneo y firma, en ese orden, sin excepción.
Conexión con el módulo
Esta es la lección que responde una pregunta que las siete anteriores dejaron abierta a propósito: cada módulo construyó y verificó su control de forma aislada —conftest test corrido a mano, trivy config corrido a mano, cosign verify-blob corrido a mano—. Ninguno, hasta ahora, corrió en secuencia, dentro de un pipeline, con el poder de detener a los que vienen después. Ese es, exactamente, el trabajo de este módulo: no enseñar herramienta nueva, sino demostrar que las tres ya construidas se comportan como un sistema, no como tres comandos sueltos.
Qué se entrega al cerrar este módulo
Cuatro piezas, cada una con su propia lección:
- Un
ci.ymlextendido con tres jobs nombrados y encadenados —policy-check(conftest),iac-scan(Trivy),verify-artifact(cosign) — cada uno conneeds:apuntando al anterior, corridos de verdad conact pull_request. - La prueba de que un cambio inocuo cruza los tres — un cambio real, pequeño, sin ninguna intención maliciosa, atraviesa policy-check, iac-scan y verify-artifact sin fricción, y llega al punto donde
apply.yml(heredado, con el jobverify-artifactque el Módulo 6 ya le agregó) tomaría el relevo. - La prueba de que un cambio malo se detiene, y se detiene rápido — un intento real de ensanchar
AppServerRolees rechazado porpolicy-check, antes de queiac-scanoverify-artifactsiquiera arranquen. No es una promesa: es unact pull_requestcorrido de verdad, con el log completo como evidencia. - Honestidad final, en un solo lugar — qué de esta guía completa corrió de verdad y qué quedó representativo, sin dispersarlo en siete módulos distintos, y hacia dónde apunta cada límite si Andes Cargo alguna vez corre esto contra una cuenta AWS real.
Recordatorio: las piezas de M1-M7, en una sola tabla
No vas a reconstruir nada de esto — cada fila ya está aplicada y verificada en los módulos anteriores. Esta tabla existe para que, al leer el ci.yml de la lección 3, reconozcas de inmediato de dónde viene cada pieza que aparece ahí.
| Módulo | Qué construyó | Dónde vive en andes-cargo-infra/ |
|---|---|---|
| M1 | El modelo de amenazas y el mapa de riesgos | THREAT-MODEL.md, RISK-MAP.md (7/7 filas Resolved al cierre de M7) |
| M2 | Identidad OIDC federada + roles de mínimo privilegio | modules/oidc-provider/, LambdaManifestProcessorRole/AppServerRole recortados |
| M3 | Gestión de secretos gestionada, nunca en texto plano | secrets.tf (aws_ssm_parameter, aws_secretsmanager_secret) |
| M4 | Policy-as-code preventivo, tres políticas Rego | policy/no-destroy-shipments.rego, policy/least-privilege-iam.rego, policy/no-public-buckets.rego |
| M5 | Escaneo de IaC con herramientas de la comunidad | .trivyignore, comentarios #checkov:skip= documentados |
| M6 | Cadena de suministro: SBOM + firma offline | sbom.cyclonedx.json, cosign.key/cosign.pub, manifest.sig |
| M7 | Guardrails preventivos y detectivos, clasificados | GUARDRAILS-MAP.md, permission boundary de AppServerRole, andes-cargo-trail |
Los cinco controles genuinamente nuevos de este módulo no son un octavo concepto — son cinco de los siete de arriba, ahora encadenados en un solo pipeline en vez de vivir como comandos sueltos: OIDC (M2) ya gobierna quién puede correr este pipeline contra una cuenta real; secretos (M3) ya garantiza que nada de esto necesita una credencial en texto plano; conftest (M4), Trivy (M5) y cosign (M6) son los tres jobs literales que la lección 3 agrega a ci.yml. El capstone no inventa un sexto control — demuestra que los cinco, juntos, se comportan como un sistema.
Analogía: los controles en cadena de un aeropuerto
Un aeropuerto no revisa tu pasaporte, tu equipaje y tu identidad en la puerta del avión, todo a la vez, por una sola persona. Los controles están en cadena, y cada uno existe en un punto específico porque detener algo ahí es más barato que detenerlo después: control de documentos primero (¿tienes derecho a viajar?), rayos X de equipaje después (¿traes algo prohibido?), control de puerta al final (¿eres tú, con la tarjeta de embarque correcta?). Si fallas el primero —un pasaporte vencido—, nadie te deja avanzar a hacer cola en el segundo: no tiene sentido escanear el equipaje de alguien que ya no puede viajar.
El security gate de este módulo es exactamente esa cadena. policy-check es el control de documentos: ¿esta política de IAM tiene, siquiera, permiso para existir? Si falla ahí, nadie gasta los segundos de iac-scan escaneando configuración de un cambio que de todos modos no va a pasar. iac-scan es el rayos X: ¿hay algo mal configurado que un ojo humano no vería a simple vista? verify-artifact es el control de puerta: ¿el artefacto que está a punto de desplegarse es, de verdad, el que el equipo aprobó, sin ninguna alteración en el camino? Tres preguntas distintas, en el orden que minimiza el tiempo perdido en una respuesta que ya sabías que iba a ser "no".
El orden importa: por qué policy-check va primero
No es arbitrario. Cada control de este gate tiene un costo distinto en tiempo de ejecución:
policy-check → milisegundos → evalúa un plan ya calculado, sin tocar disco más que para leerlo
iac-scan → segundos → parsea HCL completo, descarga un bundle de reglas
verify-artifact → segundos → instala una herramienta externa, verifica un archivo
Poner el control más barato primero significa que un cambio que de todos modos iba a fallar, falla en el paso que menos tiempo de runner desperdicia — el mismo criterio que el Módulo 5, lección 7, ya aplicó al decidir que el escaneo de Trivy corre antes de terraform init, no después. Este módulo lleva ese mismo criterio un nivel más arriba: no solo "¿en qué punto de un job corre este chequeo?", sino "¿en qué orden corren los jobs mismos?".
Cómo se organiza este módulo
| # | Lección | Qué vas a hacer |
|---|---|---|
| 1 | Esta introducción | Mapa del módulo, recordatorio de M1-M7 |
| 2 | Repaso de arquitectura | El diagrama completo del gate, superpuesto sobre ci.yml/apply.yml |
| 3 | Encadenando el gate en ci.yml | Ejecutado. Los tres jobs, con needs:, corridos con act |
| 4 | Un cambio que cruza el gate | Ejecutado. Un tag nuevo en el bucket, verde de punta a punta |
| 5 | Un cambio que el gate detiene | Ejecutado. AppServerRole ensanchado, detenido en policy-check |
| 6 | Lo que esta guía dejó representativo | Honestidad final, un solo lugar, cada límite con su razón |
| 7 | Lo que Andes Cargo todavía necesita | El mapa hacia el resto del ecosistema |
| 8 | Proyecto final | El repositorio completo como pieza de portfolio |
Errores comunes
Pensar que este módulo construye un cuarto o quinto control de seguridad nuevo. Qué pasa: alguien llega a este módulo esperando aprender una herramienta más, además de conftest/Trivy/cosign. Cómo detectarlo: si tu expectativa al empezar la lección 3 es instalar algo que no conoces todavía. Cómo corregirlo: este módulo no instala nada nuevo — las tres herramientas ya están instaladas desde M4, M5 y M6. El trabajo entero es de orquestación: decidir el orden, declarar las dependencias entre jobs con needs:, y verificar que el conjunto se comporta como uno solo, no como tres piezas sueltas.
Confundir "el gate corrió limpio" con "el proyecto está libre de riesgo". Qué pasa: alguien, al ver los tres jobs en verde en la lección 3, concluye que andes-cargo-infra/ ya no tiene ningún hallazgo de seguridad pendiente. Cómo detectarlo: si tu entendimiento del estado del proyecto viene solo del resultado binario pasa/falla del pipeline, sin revisar RISK-MAP.md o GUARDRAILS-MAP.md. Cómo corregirlo: el gate detecta lo que sabe buscar — tres políticas Rego específicas, las reglas de Trivy, la integridad de un artefacto firmado. GUARDRAILS-MAP.md (Módulo 7) ya documentó, con precisión, qué controles quedan fuera de este gate por completo (SCP, Organizations, GuardDuty, Config) — un pipeline en verde no los reemplaza, y la lección 6 de este módulo lo repite explícitamente para que no quede como una nota perdida en un módulo anterior.
Saltar directamente a la lección 5 (el cambio que falla) sin correr primero la lección 3 (el gate armado). Qué pasa: alguien, impaciente por ver el caso "interesante" de un policy-check fallando, se salta el armado del pipeline. Cómo detectarlo: si intentas correr act pull_request sobre un ci.yml que no tiene los tres jobs con needs: encadenado todavía. Cómo corregirlo: la lección 5 depende, literalmente, de la estructura que la lección 3 construye — sin needs: iac-scan en el job verify-artifact y needs: policy-check en iac-scan, un fallo en policy-check no impediría que los otros dos jobs corrieran de todos modos (act, sin esa declaración, los correría en paralelo, sin ninguna dependencia entre ellos).
Ejercicios
Ejercicio 1 — Antes de leer la lección 2, dibuja de memoria el diagrama del gate. Basándote solo en esta introducción, escribe (en texto, sin mirar ninguna lección posterior) la secuencia de los tres jobs nuevos, con sus nombres exactos y qué herramienta corre cada uno.
Ver solución
policy-check (conftest, evalúa el plan contra policy/) → iac-scan (Trivy, escanea el HCL crudo) → verify-artifact (cosign, verifica lambda/function.zip contra manifest.sig). El orden importa: cada uno depende del anterior vía needs:, así que un fallo en cualquiera detiene a los que le siguen. El punto del ejercicio no es memorizar los tres nombres —eso lo vas a ver una y otra vez en las próximas lecciones— sino confirmar que entendiste, desde esta introducción, que el orden no es alfabético ni arbitrario: es de costo creciente.
Ejercicio 2 — Explica, a alguien que solo hizo M1-M3 de esta guía (no M4-M7), por qué este módulo no le va a servir todavía. ¿Qué prerequisito específico de M4, M5 y M6 hace que este capstone no tenga sentido sin haberlos completado?
Ver solución
Este módulo no construye policy/, no instala Trivy, no genera cosign.key/cosign.pub ni manifest.sig — los toma como ya construidos, exactamente igual que M4.8, M5.8 y M6.8 ya los dejaron. Alguien que solo completó M1-M3 llegaría a la lección 3 sin ninguna de las tres piezas que el ci.yml de esa lección asume que existen: sin policy/, conftest test no tendría contra qué evaluar; sin .trivyignore ya calibrado, trivy config --exit-code 1 fallaría sobre hallazgos que M5 ya resolvió o suprimió con razón documentada; sin manifest.sig, no habría nada que verificar. El capstone asume, literalmente, el estado final de andes-cargo-infra/ al cierre de M7 — es la razón por la que esta guía lo deja para el último módulo, no antes.
Ejercicio 3 — Predice cuál de los tres jobs es el más rápido, y justifica por qué, antes de verlo confirmado con tiempos reales en la lección 3. Usando solo el razonamiento de "el orden importa" de esta lección, ¿cuál de policy-check, iac-scan, verify-artifact esperarías que termine primero, en aislamiento (sin contar el tiempo de instalación de cada herramienta)?
Ver solución
policy-check, en su paso de evaluación pura (conftest test tfplan.json -p policy/), es el más rápido de los tres: evalúa un JSON ya calculado, en memoria, contra cuatro reglas Rego — un trabajo de milisegundos, como ya viste en el Módulo 4. iac-scan parsea HCL completo y descarga un bundle de reglas de Trivy (segundos). verify-artifact necesita instalar cosign desde cero en cada corrida del runner (varios segundos) antes incluso de verificar la firma. La lección 3 confirma esto con tiempos reales de la propia salida de act — pero el razonamiento de esta introducción ya debería haberte llevado a la respuesta correcta sin necesidad de correr nada todavía.
Resumen y siguiente paso
Este módulo no agrega una pieza de seguridad nueva a Andes Cargo — encadena las cinco que M2-M6 ya construyeron en un sistema real: tres jobs nombrados (policy-check, iac-scan, verify-artifact), con needs: declarando el orden, corridos de verdad con act. Vas a ver un cambio inocuo cruzar los tres sin fricción, y un cambio real que ensancha AppServerRole detenido en el primero, antes de que los otros dos siquiera arranquen — la prueba de que "verde no es sinónimo de seguro" (Módulo 1) tiene, ahora, un mecanismo real que lo hace cierto en sentido contrario: rojo en el punto correcto sí es sinónimo de que el gate está haciendo su trabajo.
La lección 2 dibuja el diagrama completo del gate, superpuesto sobre el ci.yml/apply.yml heredado, antes de tocar una sola línea de YAML.
Recursos
- Este curso, Módulos 4, 5 y 6 — el origen de cada una de las tres herramientas que este módulo encadena, con su instalación y su primer uso individual ya verificados.
- Este curso, Módulo 7,
GUARDRAILS-MAP.md— la matriz que este módulo capstone no reemplaza ni repite, solo referencia. cicd-and-gitops-on-aws-guide, Módulo 3 y Módulo 5 — elci.yml/apply.ymloriginal de nueve steps que este módulo extiende sin reescribir.