AWS SSO: Gestión de Múltiples Cuentas con CLI
📋 Contexto
Gestionar múltiples cuentas AWS con access keys es un dolor: credenciales por todos lados, rotación manual, riesgo de seguridad. AWS SSO (ahora llamado IAM Identity Center) resuelve esto con login centralizado y credenciales temporales. En este post, cómo configurarlo para máxima productividad.
🎯 Problema: Multi-Account Sin SSO
# Antes (nightmare mode)
export AWS_ACCESS_KEY_ID="AKIA..." # Dev account
export AWS_SECRET_ACCESS_KEY="..."
aws s3 ls
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
export AWS_ACCESS_KEY_ID="AKIA..." # Prod account
export AWS_SECRET_ACCESS_KEY="..."
aws s3 ls
# Mantener keys sincronizadas en ~/.aws/credentials
# Rotar manualmente cada 90 días
# Keys en plain text en disco 😱
✅ Solución: AWS SSO
Ventajas:
- ✅ Una sola autenticación para todas las cuentas
- ✅ Credenciales temporales (se auto-refrescan)
- ✅ MFA integrado
- ✅ No más access keys en plain text
- ✅ Fácil cambio entre cuentas/roles
🛠️ Setup Inicial
Paso 1: Configurar SSO (Admin Task)
Esto lo hace el admin de tu organización AWS, no tú:
- Ir a AWS IAM Identity Center
- Enable SSO
- Crear grupos (Admins, Developers, ReadOnly)
- Asignar usuarios a grupos
- Asignar permission sets a cuentas
Paso 2: Configurar AWS CLI
# Install/update AWS CLI v2 (required for SSO)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install --update
# Verify version (must be 2.x)
aws --version
Paso 3: Configurar Perfiles SSO
aws configure sso
# Interactive prompts:
SSO session name: my-company
SSO start URL: https://d-1234567890.awsapps.com/start
SSO region: us-east-1
SSO registration scopes: sso:account:access
# Browser opens → Login con tus credenciales → Aprueba el acceso
# Luego selecciona:
CLI default profile name: dev
CLI default output format: json
CLI default region: us-east-1
Resultado: ~/.aws/config
[profile dev]
sso_session = my-company
sso_account_id = 123456789012
sso_role_name = DeveloperAccess
region = us-east-1
output = json
[profile prod]
sso_session = my-company
sso_account_id = 987654321098
sso_role_name = ReadOnlyAccess
region = us-east-1
output = json
[profile staging]
sso_session = my-company
sso_account_id = 555666777888
sso_role_name = DeveloperAccess
region = us-east-1
output = json
[sso-session my-company]
sso_start_url = https://d-1234567890.awsapps.com/start
sso_region = us-east-1
sso_registration_scopes = sso:account:access
🚀 Uso Diario
Login SSO (Una Vez al Día)
# Login opens browser once
aws sso login --profile dev
# Or login to session (all profiles)
aws sso login --sso-session my-company
# Credentials last ~8 hours
# Re-login when expired
Usar Perfiles
# Option 1: --profile flag
aws s3 ls --profile dev
aws s3 ls --profile prod
# Option 2: Environment variable
export AWS_PROFILE=dev
aws s3 ls
aws ec2 describe-instances
# Switch profile
export AWS_PROFILE=prod
aws s3 ls
Verificar Identidad Actual
aws sts get-caller-identity
# Output:
{
"UserId": "AROA...:[email protected]",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/DeveloperAccess/[email protected]"
}
💡 Scripts Multi-Account
Patrón 1: Iterar Sobre Cuentas
#!/bin/bash
# multi-account-report.sh
set -euo pipefail
readonly PROFILES=(dev staging prod)
for profile in "${PROFILES[@]}"; do
echo "=== Account: $profile ==="
# Get account ID
account_id=$(aws sts get-caller-identity \
--profile "$profile" \
--query 'Account' \
--output text)
echo "Account ID: $account_id"
# Count EC2 instances
instances=$(aws ec2 describe-instances \
--profile "$profile" \
--query 'length(Reservations[].Instances[])' \
--output text)
echo "EC2 Instances: $instances"
# Count S3 buckets
buckets=$(aws s3api list-buckets \
--profile "$profile" \
--query 'length(Buckets)' \
--output text)
echo "S3 Buckets: $buckets"
echo ""
done
Patrón 2: Función Helper
#!/bin/bash
# aws-helpers.sh
# Run command in all profiles
run_in_all_profiles() {
local cmd=("$@")
local profiles=(dev staging prod)
for profile in "${profiles[@]}"; do
echo "▶ Running in $profile..."
AWS_PROFILE=$profile "${cmd[@]}"
echo ""
done
}
# Usage
run_in_all_profiles aws ec2 describe-instances \
--query 'Reservations[].Instances[].[InstanceId,State.Name]' \
--output table
Patrón 3: Parallel Execution
#!/bin/bash
# parallel-multi-account.sh
set -euo pipefail
readonly PROFILES=(dev staging prod)
check_account() {
local profile=$1
echo "[$profile] Checking..."
# Your checks here
local running=$(aws ec2 describe-instances \
--profile "$profile" \
--query 'length(Reservations[].Instances[?State.Name==`running`][])' \
--output text)
echo "[$profile] Running instances: $running"
}
export -f check_account
# Run in parallel (requires GNU parallel)
printf '%s\n' "${PROFILES[@]}" | parallel -j 3 check_account
# Or with xargs
printf '%s\n' "${PROFILES[@]}" | xargs -P 3 -I {} bash -c 'check_account "$@"' _ {}
🔧 Aliases y Funciones Útiles
# ~/.bashrc or ~/.zshrc
# Quick profile switching
alias awsp='export AWS_PROFILE='
alias awsp-dev='export AWS_PROFILE=dev'
alias awsp-prod='export AWS_PROFILE=prod'
# Show current profile
alias awswho='echo "Profile: $AWS_PROFILE" && aws sts get-caller-identity'
# Login shortcut
alias awsl='aws sso login --sso-session my-company'
# Function to run command in specific profile
awsrun() {
local profile=$1
shift
AWS_PROFILE=$profile "$@"
}
# Usage: awsrun dev aws s3 ls
# Function to switch and show
awsuse() {
export AWS_PROFILE=$1
echo "Switched to profile: $AWS_PROFILE"
aws sts get-caller-identity --query '[Account,Arn]' --output text
}
# Usage: awsuse prod
🐛 Troubleshooting
Error: "Token has expired"
# Solution: Re-login
aws sso login --profile dev
# Or login to session (updates all profiles)
aws sso login --sso-session my-company
Error: "Unable to locate credentials"
# Check profile exists
cat ~/.aws/config | grep -A 5 "\[profile dev\]"
# Verify SSO session
aws sso login --sso-session my-company
# Check environment
echo $AWS_PROFILE
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
Browser No Abre en SSH
# Option 1: Use --no-browser
aws sso login --profile dev --no-browser
# Copy the URL shown and open in your local browser
# Option 2: Port forwarding
ssh -L 8080:localhost:8080 user@server
# Then login normally
~/.aws/sso/cache/. Estos archivos tienen permisos 600 pero ten cuidado al compartir tu home directory.
💼 Caso Real: Mi Setup
# ~/.aws/config (mi configuración real)
[profile work-dev]
sso_session = work
sso_account_id = 111111111111
sso_role_name = PowerUserAccess
region = us-east-1
output = json
[profile work-prod]
sso_session = work
sso_account_id = 222222222222
sso_role_name = ReadOnlyAccess
region = us-east-1
output = json
[profile personal]
sso_session = personal
sso_account_id = 333333333333
sso_role_name = AdministratorAccess
region = us-east-1
output = json
[sso-session work]
sso_start_url = https://company.awsapps.com/start
sso_region = us-east-1
sso_registration_scopes = sso:account:access
[sso-session personal]
sso_start_url = https://personal.awsapps.com/start
sso_region = us-east-1
sso_registration_scopes = sso:account:access
8:00 AM →
aws sso login --sso-session workTodo el día →
export AWS_PROFILE=work-dev (default)Cuando necesito prod →
awsuse work-prodPersonal projects →
awsuse personal
📊 Comparación: Access Keys vs SSO
| Aspecto | Access Keys | AWS SSO |
|---|---|---|
| Seguridad | ❌ Long-lived, plain text | ✅ Temporary, auto-rotate |
| Multi-account | ❌ Keys per account | ✅ Single login |
| MFA | 🟡 Optional, complex | ✅ Integrated |
| Rotation | ❌ Manual every 90d | ✅ Automatic |
| Setup | ✅ Simple | 🟡 Initial setup required |
| Auditing | 🟡 Per user | ✅ Centralized |
💡 Best Practices
- ✅ Usa SSO para todo (elimina access keys)
- ✅ Nombra perfiles descriptivamente:
company-devnodev - ✅ Agrupa perfiles por SSO session
- ✅ Configura ReadOnly para prod por defecto
- ✅ Usa MFA siempre
- ✅ Login una vez por día (no por comando)
- ✅ Verifica identidad antes de operaciones destructivas
- ❌ No uses access keys si tienes SSO disponible
- ❌ No compartas credenciales SSO
📚 Recursos
💭 Conclusión
AWS SSO es un game-changer para gestionar múltiples cuentas. El setup inicial toma 15 minutos, pero después de eso, tu workflow es más simple, más seguro y más productivo. Si aún usas access keys con múltiples cuentas, este es el momento de migrar a SSO.
Mi experiencia: después de migrar a SSO, nunca volví a preocuparme por rotar keys manualmente o por tener credenciales en plain text. Es una de esas mejoras que te preguntas "¿por qué no lo hice antes?"