Reemplaza las claves de AWS de larga duración con OIDC
Tu CI tiene claves de AWS que nunca expiran. Los atacantes también lo saben.
La mayoría de los pipelines todavía se autentican en AWS con un access key ID y un secret de larga duración guardados como secreto de CI. Ese par es un objetivo permanente: funciona desde cualquier lugar, funciona para siempre y usarlo no parece anormal. Fíltralo una vez, en una línea de log, un workflow bifurcado o una action comprometida, y seguirá funcionando hasta que un humano lo note y lo rote. OpenID Connect (OIDC) elimina por completo la credencial guardada.
Por qué las claves permanentes son el problema
Una access key guardada es una credencial al portador, sin expiración ni contexto. Quien tenga la cadena eres tú. Las vías de filtración comunes son aburridas y constantes:
- Un workflow imprime el entorno durante una depuración.
- Una action de terceros que fijaste por tag es secuestrada y exfiltra secretos.
- Un workflow de pull request desde un fork obtiene acceso a los secretos del repositorio.
- La clave termina en un artefacto de build o en una capa de contenedor y se publica.
Como la clave nunca expira, la detección es la única defensa, y la detección es lenta. Estás apostando tu cuenta de la nube a que nadie cometa un error, indefinidamente.
El mecanismo: asunción de rol con OIDC
Con OIDC, tu proveedor de CI (GitHub Actions, GitLab, etc.) emite un token de identidad firmado y de corta duración para cada ejecución del workflow. Configuras un rol de IAM en AWS que confía en ese proveedor y restringe qué repositorio, rama o entorno puede asumirlo. En tiempo de ejecución el workflow intercambia el token por credenciales temporales vía AWS STS.
# GitHub Actions
permissions:
id-token: write # permite al workflow solicitar el token OIDC
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/ci-deploy
aws-region: us-east-1
Ningún aws-access-key-id ni aws-secret-access-key en ninguna parte. La trust policy del rol de IAM lo acota para que solo tu repo en tu rama pueda asumirlo:
{
"Condition": {
"StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" },
"StringLike": { "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:ref:refs/heads/main" }
}
}
El beneficio
| Claves estáticas | Asunción de rol con OIDC | |
|---|---|---|
| Secreto guardado | access key + secret en CI | nada guardado |
| Vida útil | hasta rotación manual | minutos (sesión STS) |
| Alcance | usuario completo, desde cualquier lugar | un rol, un repo/rama |
| Radio de daño ante filtración | funciona para siempre | ya expirado |
No se guarda nada, así que no hay nada que filtrar. Las credenciales expiran solas, así que un token robado no sirve minutos después. Una vez que OIDC esté activo, borra las claves estáticas.
Movidas avanzadas
- Acota la trust policy. Fija
suba una rama o Environment de GitHub específico, no a toda la organización. Un comodín laxo permite que cualquier repo asuma el rol. - Dale al rol el mínimo privilegio. OIDC elimina la clave permanente, pero la policy de IAM del rol sigue definiendo el radio de daño. Concede solo las acciones que el pipeline necesita.
- Acorta la sesión. Ajusta
role-duration-seconds(o la duración máxima de sesión del rol) al valor más pequeño que tu job necesite. - Borra las claves viejas y alerta sobre su uso. Tras migrar, desactiva las claves del usuario de IAM y agrega una alarma de CloudTrail para que cualquier uso futuro sea un incidente, no una sorpresa.
Recursos
- Configuración de OpenID Connect en AWS — GitHub Docs
- Roles de IAM para proveedores de identidad y federación — documentación de AWS
- AWS STS
AssumeRoleWithWebIdentity aws-actions/configure-aws-credentials- GitLab OpenID Connect con AWS
¿Desarrollas sistemas de IA o en la nube? Yeda AI audita y refuerza pipelines de LLM y contenedores en producción. Hablemos · Lee el blog