Módulo 4: Secrets Environments And Identity

1. Introducción: quién puede aplicar qué, y con qué llave

Descripción

El Módulo 3 dejó ci.yml corriendo fmt, validate y plan en cada Pull Request, contra el mismo LocalStack de siempre. Si miraste ese archivo con cuidado, ya viste algo que este módulo va a nombrar de frente: el bloque env: de terraform-checks tiene AWS_ACCESS_KEY_ID: test y AWS_SECRET_ACCESS_KEY: test escritos directamente en el YAML, en texto plano, dentro de un archivo que ya está commiteado al historial de Git. Funciona porque son las credenciales dummy de LocalStack, inofensivas por diseño. Pero la forma de ese bloque —una credencial escrita directamente donde cualquiera con acceso al repositorio puede leerla— es exactamente el antipatrón que, según la auditoría de mercado que motiva esta guía entera, ninguna competencia enseña cómo evitar.

Este módulo responde tres preguntas, en orden: ¿por qué una credencial nunca debería vivir donde vive ahora mismo en ci.yml? ¿Qué mecanismo ofrece GitHub para sacarla de ahí sin romper nada? Y ¿qué existe más allá de "sacarla del YAML" —la federación OIDC, que evita por completo que exista una clave de larga vida que guardar? Al terminar, vas a haber migrado el ci.yml real de Andes Cargo para que lea sus credenciales desde un Secret en vez de tenerlas escritas en el archivo, vas a entender por qué eso sigue sin ser la solución completa que usaría un pipeline de producción contra una cuenta AWS real, y vas a saber nombrar esa solución completa —OIDC— aunque esta guía no la construya de punta a punta aquí.

Conexión con el módulo

Las lecciones 2 a 4 construyen el vocabulario y el porqué: qué antipatrón exacto señala la auditoría de mercado (lección 2), cómo GitHub organiza los Secrets que ya usas desde el Módulo 2 con act --secret-file (lección 3), y qué es la federación OIDC en concepto, antes de ver una sola línea de YAML de producción (lección 4). La lección 5 muestra ese YAML completo —el patrón que usaría un pipeline real contra una cuenta AWS real— etiquetado, desde la primera línea, como representativo: no corre en esta guía, con la razón técnica exacta. La lección 6 hace lo mismo con los Environments de GitHub y la aprobación humana como control de despliegue. Las lecciones 7 y 8 vuelven a terreno ejecutado: migras ci.yml para leer sus credenciales de un .secrets gitignorado en vez de tenerlas escritas en el archivo, con salida real de act confirmando que el cambio no rompe nada.


El mapa de este módulo: las 8 lecciones

   MÓDULO 4 — SECRETOS, AMBIENTES E IDENTIDAD

   L1  Introducción (esta)               el mapa, la brecha citada por el mercado
   L2  Por qué una credencial nunca       el antipatrón exacto; qué pasa cuando
       vive en el repo                    se filtra en un commit
   L3  GitHub Secrets: repo vs.           Settings → Secrets and variables;
       environment                        secrets.AWS_ACCESS_KEY_ID en el YAML
   L4  Qué es la federación OIDC          conceptual: JWT de corta vida,
                                          trust policy de IAM
   L5  El patrón OIDC en YAML,            REPRESENTATIVO — act no emite
       nombrado                           tokens OIDC (verificado, citado)
   L6  Environments: dev y prod           required reviewers — REPRESENTATIVO,
                                          act ignora environment: (citado)
   L7  Manos a la obra: credenciales      EJECUTADO — .secrets migrado a ci.yml,
       dummy para LocalStack              salida real de act
   L8  Proyecto: el plan de secretos      EJECUTADO (parte LocalStack) +
       y ambientes de Andes Cargo         documento del despliegue real
#LecciónQué practicas
1Introducción (esta)El mapa completo; por qué esta es la brecha de seguridad más citada de la competencia
2Por qué una credencial nunca vive en el repoEl antipatrón exacto; el historial de Git como el verdadero problema, no el archivo
3GitHub Secrets: repo vs. environmentSettings → Secrets and variables; secrets.AWS_ACCESS_KEY_ID en YAML
4Qué es la federación OIDCJWT de corta vida, permissions: id-token: write, trust policy de IAM
5El patrón OIDC en YAML, nombradoRepresentativo: aws-actions/configure-aws-credentials + role-to-assume, explicado paso a paso
6Environments: dev y prodRepresentativo: required reviewers como control de aprobación
7Manos a la obra: credenciales dummy para LocalStackEjecutado: .secrets migrado a ci.yml, corrido con act
8Proyecto: el plan de secretos y ambientes de Andes CargoEjecutado (LocalStack) + el plan de despliegue real, sin construirlo

Por qué este módulo existe: la brecha más citada

DISENO.md de esta guía no inventa esta prioridad — la copia, casi textual, de la auditoría de mercado del ecosistema completo (src/paths/aws-cloud-ecosystem/VALIDACION.md, jul-2026, confianza de evidencia "alta"). Sobre el hueco de seguridad específico de esta guía, la cita es así de directa:

"Ningún temario menciona autenticación OIDC de GitHub Actions hacia AWS en lugar de claves de acceso de larga vida. Se sigue enseñando el antipatrón."

No es una cita aislada. La misma auditoría señala que esta frase, casi palabra por palabra, aparece dos veces, en la evidencia de dos guías independientes de este mismo ecosistema: aquí, y en cloud-security-and-guardrails-guide. Dos lentes de investigación distintas llegaron, por separado, a la misma conclusión: el mercado de formación en CI/CD y en seguridad de nube comparte el mismo punto ciego. Eso no es casualidad — es la señal de que el problema es real y de que nadie más lo está resolviendo con la honestidad que exige.

La razón por la que esto importa tanto no es abstracta. Una clave de acceso de AWS (AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY) de un usuario IAM tradicional no caduca por sí sola. Puede vivir activa durante años, en la laptop de alguien, en un archivo .env, en un Secret de GitHub — y si termina expuesta (un commit accidental, un log que la imprime, un repositorio que pasa de privado a público sin que nadie se acuerde de rotarla), sigue siendo válida hasta que alguien, activamente, la revoca. La federación OIDC —el tema central de las lecciones 4 y 5— ataca exactamente ese problema desde la raíz: en vez de una clave que vive para siempre hasta que alguien la mata, emite un token que nace ya caducado en minutos, cada vez que un workflow lo necesita, sin que exista ninguna clave que guardar, filtrar ni rotar.


Qué vas a construir en este módulo, ejecutado vs. representativo

Misma regla dura de las tres guías anteriores: nada se etiqueta como ejecutado si no corrió de verdad. Este módulo tiene dos piezas representativas —cada una con su razón técnica exacta, investigada y citada, no asumida—:

PiezaLecciónEstadoRazón técnica exacta
.secrets migrado a ci.yml (secrets.AWS_ACCESS_KEY_ID)3, 7, 8EjecutadoEs exactamente el mecanismo que ya usaste en el Módulo 2, lección 7 — act --secret-file — ahora aplicado al pipeline real
El patrón OIDC completo, YAML de producción5Representativoact no implementa emisión de tokens OIDC (confirmado, nektos/act discussion #2029); tampoco hay una cuenta AWS real contra la cual federar
Environments con required reviewers6Representativoact ignora por completo el campo environment: (confirmado, nektos/act issue #1714, abierto, etiquetado confirmed/not-planned) — corre el job igual, sin esperar aprobación

Las lecciones 5 y 6 no se saltan el YAML por pereza — lo muestran completo, línea por línea, porque es exactamente lo que escribirías en un pipeline real. Lo que no hacen es fingir que act lo ejecuta cuando la propia herramienta, verificada, no puede.


Errores comunes

Pensar que "credenciales dummy de LocalStack" significa "el antipatrón no aplica aquí" (conceptual). Qué pasa: alguien ve AWS_ACCESS_KEY_ID: test en ci.yml y concluye que, como no es una clave real, no hay nada que aprender de seguridad en este módulo. Por qué pasa: el riesgo real —una clave de AWS de verdad, capaz de borrar producción— no está presente en este laboratorio, y es fácil confundir "el peligro concreto no existe aquí" con "el patrón no importa". Cómo detectarlo: si tu razonamiento es "esto es solo un ejercicio, en la vida real yo nunca escribiría una clave en un YAML". Cómo corregirlo: la lección 2 muestra, con el ci.yml real de Andes Cargo, que la forma del antipatrón ya está en tu proyecto — el hecho de que la credencial concreta sea inofensiva no cambia la estructura del problema. Este módulo te enseña a corregir la forma, no solo a evitarla cuando el contenido es peligroso.

Esperar que este módulo construya OIDC de punta a punta contra AWS real (de expectativa). Qué pasa: alguien, motivado por la cita de VALIDACION sobre el antipatrón, espera terminar este módulo con un rol IAM real, un identity provider configurado, y un role-to-assume que efectivamente funcione. Por qué pasa: es la conclusión lógica de "esta guía va a resolver el hueco más citado del mercado" — pero resolver el hueco conceptualmente y en YAML no es lo mismo que construirlo contra una cuenta real. Cómo detectarlo: si al llegar a la lección 5 esperas correr un comando y ver un rol asumido de verdad. Cómo corregirlo: la lección 5 es explícita, desde su primera línea, sobre por qué eso no ocurre aquí — y apunta a cloud-security-and-guardrails-guide, la guía que sí construye OIDC de punta a punta contra una cuenta AWS real.


Ejercicios

Ejercicio 1 — Localiza el antipatrón en tu propio ci.yml. Abre el ci.yml que construiste en el Módulo 3. Sin mirar la lección 2 todavía, identifica exactamente qué línea o líneas tienen la forma del antipatrón que señala VALIDACION, aunque el contenido sea inofensivo.

Ver solución

El bloque env: del job terraform-checks en ci.yml:

env:
  AWS_ACCESS_KEY_ID: test
  AWS_SECRET_ACCESS_KEY: test

Estas dos líneas tienen la forma exacta del antipatrón: una credencial de acceso a AWS, escrita en texto plano, directamente dentro de un archivo YAML que ya forma parte del historial de Git del repositorio. Que el valor sea la palabra literal test —la credencial dummy que LocalStack acepta sin validar— no cambia la estructura: si alguien copiara este mismo patrón en un pipeline real y escribiera ahí una clave de AWS de verdad, el problema sería exactamente el mismo, solo que con consecuencias reales.

Ejercicio 2 — Predice la diferencia entre "sacar la credencial del YAML" y "eliminar la necesidad de una credencial". En dos frases, explica la diferencia conceptual entre lo que vas a construir en la lección 3 (mover la credencial a un Secret) y lo que solo vas a nombrar en la lección 5 (OIDC). ¿Por qué OIDC es un salto cualitativo, no solo "un lugar más seguro para guardar lo mismo"?

Ver solución

Una respuesta completa suena, más o menos, así: "Mover la credencial a un Secret de GitHub saca la clave del archivo YAML, pero la clave sigue existiendo — sigue siendo una credencial de larga vida, guardada en algún lugar, que alguien con el permiso correcto podría filtrar o usar mal. OIDC es distinto: no hay ninguna clave de larga vida que guardar en ningún lado — el pipeline recibe, en el momento exacto en que corre, un token que GitHub firma y que caduca en minutos, y ese token es lo único que existe para autenticar esa corrida específica." La diferencia es entre "esconder mejor la misma llave" y "dejar de necesitar una llave que se pueda perder".

Ejercicio 3 — Nombra las dos piezas representativas de este módulo, de memoria. Sin mirar hacia atrás en esta lección, nombra las dos cosas que este módulo etiqueta como representativas, en qué lección aparece cada una, y la razón técnica exacta de cada una.

Ver solución

Lección 5, el patrón OIDC completo: representativo porque act no implementa emisión de tokens OIDC (confirmado contra nektos/act discussion #2029), y porque esta guía no tiene una cuenta AWS real contra la cual federar. Lección 6, los Environments con required reviewers: representativo porque act ignora por completo el campo environment: de un job (confirmado contra nektos/act issue #1714, abierto), así que no hay forma de demostrar el bloqueo de aprobación bajo act — solo de describirlo con el camino de clics real.


Resumen y siguiente paso

En esta lección viste el mapa de las 8 lecciones de este módulo, y la cita exacta de la auditoría de mercado que justifica por qué existe: el antipatrón de credenciales de larga vida en vez de OIDC federado es el hueco de seguridad más citado de la competencia, señalado dos veces, por dos guías independientes de este ecosistema. También viste, en tu propio ci.yml, exactamente dónde vive ese antipatrón hoy, en su forma más inofensiva posible.

Antes de avanzar deberías poder: citar, de memoria, la frase exacta de VALIDACION sobre el antipatrón de OIDC; señalar la línea exacta de ci.yml que tiene su forma; y nombrar las dos piezas representativas de este módulo con su razón técnica.

La lección 2 se detiene en la pregunta que este módulo entero responde: ¿qué pasa, exactamente, cuando una credencial se filtra en un commit? La respuesta no es "se borra el archivo" — es mucho más incómoda que eso.

Recursos

  1. src/paths/aws-cloud-ecosystem/VALIDACION.md (NIEVA, auditoría de mercado, jul-2026) — la fuente de la cita sobre el antipatrón de OIDC, citada dos veces por evidencia independiente.
  2. GitHub Docs — Security hardening for GitHub Actions — el índice oficial de prácticas de seguridad que este módulo desarrolla, incluida la sección de OIDC.
  3. nektos/act discussion #2029 — la confirmación técnica, por un mantenedor del proyecto, de que act no implementa emisión de tokens OIDC. Citada a fondo en la lección 5.
  4. nektos/act issue #1714 — la confirmación técnica, abierta y etiquetada confirmed/not-planned, de que act ignora el campo environment:. Citada a fondo en la lección 6.