|

AWS SSO + Terraform: seguridad sin claves estáticas

Migrar desde credenciales IAM compartidas a AWS SSO (ahora IAM Identity Center) en Terraform elimina los riesgos de seguridad que vienen con claves estáticas almacenadas en secrets. El cambio permite auditoría individual, rotación automática de credenciales temporales y compatibilidad nativa con multi-cuenta, tanto en desarrollo local como en CI/CD con GitHub Actions o GitLab.

En 30 segundos

  • Cambiar de usuario IAM compartido a SSO elimina la falta de accountability en CloudTrail (hoy muestra solo “deployment user”, mañana muestra quién realmente fue)
  • AWS SSO genera credenciales temporales que expiran automáticamente (por defecto cada 12 horas), sin necesidad de rotación manual
  • En CI/CD, usá OIDC (OpenID Connect) con GitHub Actions para obtener tokens temporales sin almacenar secrets estáticos
  • Terraform asume roles multi-cuenta de forma nativa con assume_role_arn, reemplazando el modelo antiguo de un usuario compartido
  • La migración toma ~1-2 horas por setup (configuración SSO + permisos + providers + workflows), sin downtime

Qué es AWS SSO y por qué Terraform lo necesita

AWS SSO, rebrandizado en 2022 como IAM Identity Center, es el gestor centralizado de identidades y acceso de Amazon. En lugar de crear usuarios IAM individuales con access keys estáticas, configurás un único directorio de usuarios (en AWS o sincronizado desde tu AD corporativo) que pueden asumir roles específicos en cada cuenta.

Para Terraform, esto significa que vos —el ingeniero— autenticás una sola vez contra SSO, obtenés credenciales temporales, y Terraform las usa para interactuar con AWS sin que nunca una clave estática toque un secrets manager, un .env, o un commit accidental en git.

El problema: credenciales compartidas en Terraform

Ponele que tu equipo tiene un setup clásico multi-cuenta: una cuenta shared (donde vive el S3 backend de Terraform, DynamoDB locks, módulos), una dev, una production. Hoy día, tenés un usuario IAM llamado “terraform-deployer” (o directamente “terraform-shared”, depende) con un access key guardado en los secrets de GitHub.

El usuario tiene permiso de asumir un rol en dev y otro en prod. Cuando GitHub Actions corre terraform apply, usa ese access key estático para autenticarse. El problema:

  • No hay accountability. CloudTrail muestra que “terraform-deployer” hizo el cambio, pero no quién lo disparó. ¿Fue María desde una rama feature? ¿Fue García desde el merge a main? No sabés.
  • Una fuga = compromiso total. Si alguien filtra o commits accidentalmente el access key, tiene acceso permanente a todas las cuentas hasta que rotes la clave. Y rotar significa actualizar secrets en GitHub, en local, en todos lados.
  • Compliance no te deja. HIPAA, PCI DSS, SOC 2 exigen trazabilidad individual. Una clave compartida automáticamente falla auditoría.
  • Credenciales que nunca mueren. El access key sigue siendo válido hasta que lo revokes explícitamente. Si se filtra y no te enteras, está activa.

Dicho esto, el setup funciona. Muchas compañías lo usan. Pero cuando algo se rompe, o cuando Security llega con un audit, es dolor de cabeza.

Por qué las claves estáticas son un problema de seguridad real

No es que “podrían ser” un problema. Lo son. Acá van los detalles que importan:

  • Imposible revocar por usuario. Si María se va, revocas el access key y pierden acceso todos. Incluida García que sigue siendo del equipo.
  • Historial mezclado. CloudTrail muestra “terraform-deployer” para todo. ¿Quién agregó ese módulo roto en prod? Ni idea. No hay forma de investigar.
  • Commits accidentales. Git grep “AKIA” en el historio completo de la empresa. Vas a encontrar access keys en comments, en configfiles olvidados, en branches feature que alguien pushó sin querer.
  • Rotación manual = error humano. Cada 90 días (si tu política es estricta) generás una clave nueva, actualizás GitHub secrets, avisás al equipo, esperas a que todos actualicen local. Alguien se olvida. Ahora tenés dos claves flotando.
  • Compatibilidad con HIPAA / PCI / SOC 2. Si trabajás con clientes que tienen compliance requirements, la auditoría falla. Necesitas trazabilidad por usuario, rotación automática, y credenciales corta vida. Las claves estáticas fallan las tres.

La realidad es que si usás claves compartidas, estás diciendo “confío en que nadie commitea un secret, confío en que nadie deja acceso abierto cuando se va, confío en que nadie usa la clave en un lado que no debería”. Eso es fe, no seguridad.

Introducción a AWS SSO e IAM Identity Center

AWS rebrandizó SSO a IAM Identity Center en 2022. Técnicamente el producto es el mismo, pero la UI, features, y documentación mejoraron. Si tu AWS Organization está en una cuenta principal (management account), configurás un único directorio de usuarios en Identity Center.

Cada usuario tiene credenciales que nunca toca. En vez de eso, usá un browser o CLI para autenticarse contra SSO, generás una sesión temporal, y obtenés credenciales que expiran (por defecto entre 1 y 12 horas, vos elegís). En ejecutar agentes sin almacenar credenciales profundizamos sobre esto.

Para multi-cuenta: configurás “Permission Sets” — básicamente templates de IAM policies que asignás a usuarios en cuentas específicas. Un usuario puede tener admin en dev pero reader en prod. Y lo mejor: cada acción que ese usuario hace en una cuenta asumiendo el rol de SSO aparece en CloudTrail con su nombre real, no un usuario compartido.

La diferencia con el setup anterior:

AspectoIAM estático (hoy)AWS SSO (propuesto)
CredencialesAccess key + secret key permanentesTemporales que expiran automáticamente (1-12h)
RotaciónManual cada 90 díasAutomática sin intervención
AccountabilityCloudTrail muestra “terraform-deployer”CloudTrail muestra el usuario real (ej: ariel.blanco)
Revocar accesoGenerar clave nueva, actualizar todos los placesEliminar usuario de Permission Set, listo
Multi-cuentaUsuario asume roles via AssumeRolePermission Sets definen qué roles asume el usuario en cada cuenta
CI/CD sin secretsAlmacenar access key en GitHub secretsOIDC: GitHub obtiene token, lo intercambia por credenciales sin guardar secrets
Compliance (HIPAA/PCI)Falla auditoríaPasa auditoría: trazabilidad + rotación automática
aws sso terraform seguro diagrama explicativo

Configurar AWS SSO con Terraform localmente

Primero, un asueto: si ya tenés SSO configurado en tu AWS Organization, saltá este paso. Si no, necesitás:

1. Habilitá Identity Center en tu account management. Abrí AWS Console → Identity Center → Enable (toma ~10 minutos).

2. Creá tu usuario: Identity Center → Users → Add user. Podés sincronizar desde tu AD corporativo también si tenés.

3. Creá Permission Sets: vos definis qué permisos tiene el usuario en cada cuenta. Ejemplo: “Terraform-Admin-Dev” (todos los permisos en dev), “Terraform-Readonly-Prod” (solo read en prod).

4. Asignás el usuario a las cuentas con los Permission Sets. Ojo: no estás asignando un usuario a una cuenta. Estás asignando usuario + permission set a cuenta + rol.

Ahora, en local. Abrís terminal y hacés:

aws configure sso

Te pregunta por:

  • SSO session name: inventá uno, ej “dev” o “prod” (lo usás después en comandos)
  • SSO start URL: sacá de Identity Center dashboard, algo como https://d-xxxxxxxx.awsapps.com/start
  • SSO region: donde está tu Identity Center, ej us-east-1
  • SSO registration scopes: dejá default

Te abre un browser, loguéas con tu usuario SSO, le das permisos a la CLI. Listo.

Ahora tu ~/.aws/config tiene algo así:

[sso-session dev] sso_start_url = https://d-xxxxxxxx.awsapps.com/start sso_region = us-east-1 sso_registration_scopes = sso:account:access [profile development] sso_session = dev sso_account_id = 111111111111 sso_role_name = Terraform-Admin-Dev region = us-east-1 Ya lo cubrimos antes en proteger credenciales en tus pipelines.

Y en Terraform, especificás el profile:

terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } provider "aws" { profile = "development" region = var.aws_region assume_role { role_arn = "arn:aws:iam::111111111111:role/Terraform-Admin-Dev" } }

Cuando corres terraform plan, Terraform ve que necesita credenciales, revisa tu profile, nota que estás en SSO, genera un token temporal (o lo re-usa si está vigente), y usa eso para hablar con AWS. Sin ni una clave estática.

Error común acá: si tu config tiene sso_session en el profile, pero Terraform sigue pidiendo credenciales, check que tenés aws-cli/v2. La v1 no soporta sso_session

Migración en arquitectura multi-cuenta

Caso real (del artículo original en dev.to): un equipo con tres cuentas AWS. Shared account (state, locks, módulos), dev, prod. Hoy tienen un usuario "terraform-deployer" que asume roles en dev y prod desde la shared account.

El plan de migración:

  • Paso 1: Habilitar Identity Center en management account. Configurá tus usuarios reales ahí (ej: María, García, vos).
  • Paso 2: Crear Permission Sets. Ej: "Terraform-Admin-Dev", "Terraform-Admin-Prod", "Terraform-Readonly-Prod". Cada uno corresponde a un rol en cada cuenta.
  • Paso 3: Asignar usuarios a cuentas. María y vos tienen "Terraform-Admin-Dev" en la dev, pero solo "Terraform-Readonly-Prod" en prod.
  • Paso 4: Crear roles en dev y prod. Estos roles tienen trust relationship con Identity Center. Cuando una sesión SSO asume el rol, funciona.
  • Paso 5: Actualizar providers en Terraform. En lugar de un único usuario "terraform-deployer", cada developer usa su perfil SSO.
  • Paso 6: Actualizar GitHub Actions. En lugar de almacenar access keys, configurás OIDC (abajo).
  • Paso 7: Deshabilitar o revocar el usuario "terraform-deployer". Ojo: verificá que no queda nada que lo use. Grep en todos los repos.

El tiempo de downtime es cero. Hoy coexisten ambos: algunos developers usan SSO, otros siguen con claves estáticas. Cuando estés seguro, apagas las viejas.

AWS SSO con CI/CD: GitHub Actions sin secrets estáticos

Acá viene lo complicado, porque CI/CD no tiene navegador. No podés hacer aws configure sso en un workflow.

Opción 1 (simple, pero no ideal): almacenar las credenciales de SSO generadas localmente en GitHub secrets. Funciona, pero son temporales y expiran. Tedioso. Cubrimos ese tema en detalle en herramientas modernas de automatización.

Opción 2 (profesional): OIDC con GitHub Actions. GitHub genera un JWT (token), se lo pasa a AWS, AWS verifica que es legítimo (sin almacenar secrets), y devuelve credenciales temporales.

Cómo configurar OIDC:

  • Paso 1: Crear una identidad OIDC en AWS. Vá a IAM → Identity Providers → Add → OpenID Connect. URL: https://token.actions.githubusercontent.com, Audience: sts.amazonaws.com.
  • Paso 2: Crear un rol con trust policy OIDC. Este rol permite que GitHub Actions asuma credenciales. La trust policy verifica que el JWT venga desde tu repo específico.
  • Paso 3: Asignar permisos al rol. Incluí permisos de Terraform (S3 state, DynamoDB locks, etc) si la shared account los necesita, o AssumeRole para dev/prod.
  • Paso 4: Agregar el workflow de GitHub Actions. Usá aws-actions/configure-aws-credentials con role-to-assume.

Ejemplo de workflow:

name: Terraform Apply on: push: branches: [main] jobs: terraform: runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - uses: actions/checkout@v4 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::111111111111:role/github-actions-terraform aws-region: us-east-1 - name: Terraform init run: terraform init - name: Terraform apply run: terraform apply -auto-approve

Sin un solo secret almacenado en GitHub. GitHub genera el JWT, lo verifica AWS, y listo. Si el token expira o algo falla, GitHub simplemente rechaza el request. No hay credenciales flotando.

Errores comunes en la migración

Error 1: Mantener credenciales estáticas activas "por si acaso".

Creás los users en SSO, configurás todo bonito, pero dejas el access key del usuario "terraform-deployer" ahí "por si algo falla". Obvio: algo va a fallar. Un workflow de back a claves estáticas, algunos developers siguen usando clave, y ya tenés dos sistemas conviviendo. Compliance falla. Solución: cuando migrés, desactivá el access key inmediatamente (no lo deletees aún, en caso de rollback urgente, pero desactivá). Probá todo en staging primero, luego mové a prod.

Error 2: Confundir sso vs sso_session en ~/.aws/config.

Antiguo (v1 de AWS CLI):

[profile dev] sso_account_id = 111111111111 sso_role_name = Admin sso_region = us-east-1 sso_start_url = https://d-xxxxxxxx.awsapps.com/start

Nuevo (v2+):

[sso-session dev] sso_start_url = https://d-xxxxxxxx.awsapps.com/start sso_region = us-east-1 [profile development] sso_session = dev sso_account_id = 111111111111 sso_role_name = Admin

Si mezclás formatos, Terraform se confunde. Borrá ~/.aws/sso (caché de sesiones) y rehacé la config desde cero con aws configure sso. Esto se conecta con lo que analizamos en elegir tu plataforma de CI/CD.

Error 3: Las credenciales de SSO expiran en CI/CD.

Almacenaste las credenciales temporales en un secret de GitHub. Funciona 1 semana, luego expiran. Workflows fallan sin contexto claro. Solución: no almacenes credenciales temporales. Usá OIDC (arriba) o, si no podés, regenerá los secrets semanales (no scalea).

Error 4: Asignar permisos demasiado amplios a los roles SSO.

Si el role de Terraform en dev tiene permisos de borrar DynamoDB, CloudTrail, o cambiar IAM, y alguien roba tu sesión SSO (ej: una XSS que captura el token), pueden hacer daño. Principio de mínimo privilegio: Terraform en dev solo puede crear/editar/destruir los recursos que dev realmente tiene (EC2, RDS, S3 data buckets). Excluí IAM, KMS, CloudTrail, Secret Manager, a menos que específicamente lo necesites.

Error 5: No revocar claves viejas inmediatamente.

Desactivaste el access key del usuario "terraform-deployer", pero no lo borraste. Tres meses después, alguien que se fue sigue teniendo el repo clonado con esa clave en .git/config. La revisa, la usa en otra compañía. Solución: cuando desactivés, programá un recordatorio para borrar en 30 días. Después, antes de 30 días, verificá que nada la usa (logs de acceso en CloudTrail).

Preguntas Frecuentes

¿Cómo configuro Terraform para usar AWS SSO en lugar de claves IAM?

Ejecutá aws configure sso en terminal (proporciona SSO URL, región, nombre de sesión). Luego, en tu provider de Terraform, usá profile = "profile-name" y assume_role { role_arn = "..." }. Terraform automáticamente genera credenciales temporales cuando las necesita.

¿Cuáles son los riesgos de usar credenciales compartidas en Terraform?

No hay trazabilidad (CloudTrail muestra un usuario genérico, no quién realmente hizo el cambio), rotación manual que falla (alguien se olvida de actualizar), imposibilidad de revocar acceso individual, y problemas con compliance (HIPAA, PCI, SOC 2 requieren auditoría por usuario). Si la clave se filtra, compromete todas las cuentas hasta que la rotas.

¿Cómo elimino claves de acceso compartidas y migro a SSO en multi-cuenta?

Habilitá Identity Center, creá Permission Sets (admin en dev, readonly en prod), asignales a usuarios en cada cuenta, creá roles con trust policy OIDC en cada cuenta, actualizá tus providers de Terraform, mové CI/CD a OIDC (sin secrets), y luego desactivá/eliminá las claves viejas.

¿Cómo configuro GitHub Actions con Terraform y AWS SSO de forma segura?

Configurá OIDC entre GitHub y AWS, creá un role con trust policy que verifique los JWTs de GitHub, y usá aws-actions/configure-aws-credentials@v4 con role-to-assume. Sin almacenar secrets en GitHub, sin credenciales estáticas.

¿Qué diferencia hay entre AWS SSO e IAM Identity Center para Terraform?

Son el mismo producto. AWS rebrandizó SSO a IAM Identity Center en 2022 para reflejar que es un gestor de identidades completo, no solo SSO. Para Terraform, funcionan idéntico: el nombre técnico en ~/.aws/config y permisos IAM es el mismo.

Conclusión

Migrar desde credenciales IAM compartidas a AWS SSO en Terraform no es opcional si querés escalabilidad, seguridad, y auditoría seria. La realidad de hoy es que una clave compartida expone el equipo a liability que aumenta con cada hire, cada salida, cada audit.

El setup de SSO + OIDC toma ~1-2 horas. No hay downtime. Terraform soporta SSO nativamente. GitHub Actions soporta OIDC. AWS compliance mejora automáticamente.

Si trabajás en infraestructura web (hosting, servidores, multi-region), ya sabés que separar entornos es crítico. SSO fuerza esa separación a nivel de credenciales. María en dev no puede tocar prod ni por error, porque su sesión SSO solo le asume el rol dev.

Lo que hacer ahora: habilitá Identity Center si no lo tenés. Creá Permission Sets. Migrá uno o dos developers a SSO (local). Ajustá. Luego GitHub Actions con OIDC. Finalmente, eliminá las claves viejas.

Fuentes

Te puede interesar...