2026/06/13
8 min. de lectura
---

Autenticación en AWS con GitHub Actions mediante OIDC

AWSTerraformSecurityCI/CD
Hero image for Autenticación en AWS con GitHub Actions mediante OIDC

En los flujos de trabajo tradicionales de Integración y Despliegue Continuo (CI/CD), la práctica común para permitir que un pipeline interactúe con los recursos de AWS consiste en generar un usuario IAM, crear un par de claves de acceso estáticas (AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY) y almacenarlas como secretos en el repositorio.

Esta estrategia introduce un vector de riesgo crítico: las credenciales son de larga duración y carecen de un mecanismo automático de rotación. Si el repositorio o la plataforma de automatización se ven comprometidos, las claves filtradas otorgan un acceso persistente y potencialmente irrestricto a la infraestructura de la nube. Para mitigar esta vulnerabilidad, la arquitectura moderna de DevOps adopta la federación de identidades.

Diagrama oidc con aws y gh actions
Diagrama oidc con aws y gh actions

Mecánica de OpenID Connect (OIDC)

OpenID Connect (OIDC) permite que los flujos de trabajo de GitHub Actions se autentiquen directamente en AWS sin necesidad de almacenar secretos compartidos de AWS. En su lugar, se establece una relación de confianza criptográfica entre AWS (como proveedor de la nube) y GitHub (como Proveedor de Identidad o IdP).

El intercambio de credenciales ocurre de forma totalmente dinámica y efímera en cada ejecución del pipeline siguiendo este flujo:

  1. Solicitud de Token: Al iniciar un job, el runner de GitHub Actions solicita un token OIDC firmado en formato JWT (JSON Web Token) al proveedor de identidad de GitHub.
  2. Intercambio en AWS STS: El flujo de trabajo envía este JWT a AWS STS (Security Token Service) mediante la acción correspondiente, solicitando asumir un rol específico de IAM (sts:AssumeRoleWithWebIdentity).
  3. Validación y Emisión: AWS verifica la autenticidad de la firma del token utilizando las claves públicas de GitHub y evalúa las condiciones restrictivas del rol (como el identificador de la organización, repositorio y rama). Si la validación es exitosa, STS emite credenciales temporales que expiran automáticamente al finalizar el job.

Implementación de la Infraestructura con Terraform

Para automatizar esta configuración de forma declarativa, estructuraremos nuestro código de Terraform en tres componentes esenciales: el proveedor OIDC, el rol de IAM con sus políticas de confianza, y la política de permisos de ejecución adjunta.

# 1. Definición del Proveedor OIDC de GitHub (Uno por cuenta de AWS)
resource "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [] # Opcional desde julio 2023: AWS confía en las CAs raíz de GitHub
}

# 2. Definición del Rol de IAM y Política de Confianza (Trust Policy)
resource "aws_iam_role" "github_actions_deploy" {
name = "github-actions-deploy-role"
description = "Rol asumido por GitHub Actions para despliegues automatizados mediante OIDC"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Federated = aws_iam_openid_connect_provider.github.arn
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
}
StringLike = {
# Restricción estricta por organización/usuario y repositorio
"token.actions.githubusercontent.com:sub" = "repo:Pool1541/tu-repositorio-aws:*"
}
}
}
]
})
}

# 3. Política de Privilegios Mínimos (Ejemplo acotado para S3 y CloudFront)
resource "aws_iam_policy" "deploy_policy" {
name = "github-actions-deploy-policy"
description = "Permisos específicos asignados al pipeline de CI/CD"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject"
]
Resource = [
"arn:aws:s3:::tu-bucket-de-despliegue",
"arn:aws:s3:::tu-bucket-de-despliegue/*"
]
},
{
Effect = "Allow"
Action = [
"cloudfront:CreateInvalidation"
]
Resource = "arn:aws:cloudfront::123456789012:distribution/E1ABCDEF123456" # Reemplazar con el ARN real de la distribución
}
]
})
}

# 4. Vinculación de la Política al Rol de IAM
resource "aws_iam_role_policy_attachment" "attach_deploy" {
role = aws_iam_role.github_actions_deploy.name
policy_arn = aws_iam_policy.deploy_policy.arn
}

Configuración del Workflow en GitHub Actions

Para consumir de forma correcta el rol de IAM aprovisionado, el archivo de definición del pipeline (.github/workflows/deploy.yml) debe declarar explícitamente el bloque de permisos permissions. Sin la asignación de escritura sobre el id-token, el runner omitirá la generación del JWT.

name: Deployment Pipeline

on:
push:
branches:
- main

# Declaración mandatoria para la generación de tokens OIDC
permissions:
id-token: write # Permite solicitar el token JWT a GitHub
contents: read # Requerido por acciones nativas como actions/checkout

jobs:
aws-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Source Code
uses: actions/checkout@v4

# Autenticación transparente mediante OpenID Connect
- name: Authenticate to AWS via OIDC
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy-role # Reemplazar con el ARN real
aws-region: us-east-1

- name: Verify Authentication
run: aws sts get-caller-identity

- name: Terraform Plan
run: |
terraform init
terraform plan -out=tfplan

- name: Terraform Apply
run: terraform apply -auto-approve tfplan

Consideraciones de Seguridad y Buenas Prácticas

1. Acotación Estricta del Sub Claim (sub)

El uso de comodines generales como repo:mi-organizacion/* debe evitarse por completo en entornos de producción. Cualquier repositorio creado bajo esa organización heredará automáticamente los permisos para alterar la infraestructura. Restringe el acceso al repositorio específico y, preferiblemente, limita la asunción del rol a ramas estables o etiquetas de producción:

# Ejemplo restrictivo solo para la rama principal
"token.actions.githubusercontent.com:sub" = "repo:Pool1541/tu-repositorio-aws:ref:refs/heads/main"

2. Aislamiento de Entornos (Multi-cuenta)

En arquitecturas empresariales u orientadas a una correcta segregación de funciones, se recomienda el despliegue de roles de IAM independientes distribuidos en múltiples cuentas de AWS (por ejemplo, Staging y Production). Estos roles se asocian a entornos protegidos en GitHub (GitHub Environments), exigiendo aprobaciones manuales antes de disparar el intercambio de tokens STS.

3. Principio de Privilegio Mínimo

La asignación de la política administrada por AWS AdministratorAccess anula los beneficios de una arquitectura de CI/CD segura. Se debe auditar minuciosamente qué recursos (como buckets S3, funciones Lambda, o distribuciones de CloudFront) requiere manipular el pipeline y mapear únicamente las acciones estrictamente necesarias dentro de la política de IAM gestionada por Terraform.

Conclusión

La implementación de OIDC entre GitHub Actions y AWS reemplaza un modelo basado en secretos compartidos y vulnerables por una arquitectura basada en identidades dinámicas y federadas de corta duración. Al centralizar la configuración de la confianza criptográfica mediante Terraform, elevamos la postura de seguridad de la infraestructura sin añadir fricción operativa al ciclo de vida del desarrollo.