Roles de IAM en AWS: Mejores Practicas para Permisos Seguros de Servicios
Aprende sobre Roles de IAM en AWS: como difieren de los usuarios, como funciona AssumeRole, y como usarlos para EC2, Lambda, acceso cross-account y federacion.
En la Parte 1 de esta serie, cubrimos usuarios, grupos y políticas de IAM. Ahora es momento de abordar uno de los conceptos más poderosos (y frecuentemente mal entendidos) en AWS IAM: Roles.
Los roles son fundamentales para arquitectura segura en AWS. Te permiten otorgar permisos sin embeber credenciales en código, habilitar acceso cross-account e integrar con proveedores de identidad externos. Si alguna vez has visto un error “no tienes permiso” al ejecutar código en EC2 o Lambda, probablemente fue un problema de roles.
En esta guía, cubriremos qué son los roles de IAM, cómo difieren de los usuarios, cómo funcionan, y cómo usarlos para EC2, Lambda, acceso cross-account y federación.
¿Qué es un Rol de IAM?
Un rol de IAM es una identidad con permisos (como un usuario), pero con diferencias clave:
- Sin credenciales permanentes: Los roles no tienen passwords o access keys a largo plazo.
- Asumibles: Cualquier entidad (usuario, servicio AWS, cuenta externa) puede asumir un rol temporalmente.
- Credenciales temporales: Cuando asumes un rol, obtienes credenciales temporales (válidas por 1-12 horas).
Users vs Roles
| Característica | Usuario de IAM | Rol de IAM |
|---|---|---|
| Credenciales | Password, access keys (permanentes) | Credenciales temporales (asumidas) |
| Asociado con | Una persona o aplicación específica | Cualquiera que pueda asumirlo |
| Caso de uso | Acceso humano a AWS Console/CLI | Servicios AWS, cross-account, federación |
| Rotación de credenciales | Manual | Automática (credenciales temporales expiran) |
Cómo Funcionan los Roles
Los roles operan en un modelo trust + permissions:
- Trust Policy (Who): Define quién puede asumir el rol.
- Permissions Policy (What): Define qué puede hacer el rol.
Ejemplo: Rol para EC2
Trust Policy (permite que instancias EC2 asuman este rol):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Permissions Policy (permite leer desde S3):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-app-bucket",
"arn:aws:s3:::my-app-bucket/*"
]
}
]
}
Cuando una instancia EC2 asume este rol, obtiene acceso temporal read-only a my-app-bucket.
Creando un Rol de IAM
Via AWS Console
- IAM → Roles → Create role
- Selecciona tipo de entidad de confianza:
- AWS service: Para EC2, Lambda, etc.
- Another AWS account: Para acceso cross-account
- Web identity: Para federación (Google, Facebook, etc.)
- SAML 2.0 federation: Para Single Sign-On corporativo
- Selecciona servicio (ej. EC2)
- Adjunta políticas de permisos
- Nombra el rol y crea
Via AWS CLI
# 1. Crear trust policy (guardar como trust-policy.json)
cat > trust-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "ec2.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}
EOF
# 2. Crear el rol
aws iam create-role \
--role-name MyEC2Role \
--assume-role-policy-document file://trust-policy.json
# 3. Adjuntar permisos
aws iam attach-role-policy \
--role-name MyEC2Role \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
# 4. Crear instance profile (requerido para EC2)
aws iam create-instance-profile --instance-profile-name MyEC2InstanceProfile
aws iam add-role-to-instance-profile \
--instance-profile-name MyEC2InstanceProfile \
--role-name MyEC2Role
Casos de Uso de Roles
1. Roles para Servicios AWS (EC2, Lambda, ECS)
Los servicios AWS necesitan permisos para acceder otros recursos. En lugar de embeber access keys en código, adjuntas un rol.
Ejemplo: EC2 Instance Role
Problema: Una aplicación en EC2 necesita leer desde S3.
Solución: Adjuntar un rol a la instancia EC2.
# Lanzar EC2 con rol
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t2.micro \
--iam-instance-profile Name=MyEC2InstanceProfile \
--key-name my-key
En tu aplicación (Python/boto3):
import boto3
# boto3 automáticamente usa credenciales del rol de instancia
s3 = boto3.client('s3')
response = s3.get_object(Bucket='my-app-bucket', Key='data.json')
print(response['Body'].read())
No hay access keys en el código. AWS SDK automáticamente recupera credenciales temporales del servicio de metadata de la instancia.
Ejemplo: Lambda Execution Role
Lambda requiere un rol para ejecutar y acceder otros servicios.
# Trust policy para Lambda
cat > lambda-trust-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}
EOF
# Crear rol
aws iam create-role \
--role-name MyLambdaRole \
--assume-role-policy-document file://lambda-trust-policy.json
# Adjuntar políticas
aws iam attach-role-policy \
--role-name MyLambdaRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
aws iam attach-role-policy \
--role-name MyLambdaRole \
--policy-arn arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
Crear función Lambda con rol:
aws lambda create-function \
--function-name MyFunction \
--runtime python3.9 \
--role arn:aws:iam::123456789012:role/MyLambdaRole \
--handler lambda_function.lambda_handler \
--zip-file fileb://function.zip
2. Cross-Account Access
Los roles permiten a usuarios o servicios en una cuenta de AWS acceder recursos en otra cuenta.
Ejemplo: Cuenta A accede S3 en Cuenta B
En Cuenta B (la que contiene el bucket S3):
# Trust policy permite a Cuenta A asumir el rol
cat > cross-account-trust.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111111111111:root" },
"Action": "sts:AssumeRole"
}
]
}
EOF
# Crear rol en Cuenta B
aws iam create-role \
--role-name CrossAccountS3Access \
--assume-role-policy-document file://cross-account-trust.json
# Dar permisos al rol
aws iam attach-role-policy \
--role-name CrossAccountS3Access \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
En Cuenta A (la que quiere acceder):
# Usuario en Cuenta A asume el rol en Cuenta B
aws sts assume-role \
--role-arn arn:aws:iam::222222222222:role/CrossAccountS3Access \
--role-session-name CrossAccountSession
# Esto retorna credenciales temporales:
# - AccessKeyId
# - SecretAccessKey
# - SessionToken
# Usa estas para acceder recursos en Cuenta B
En código:
import boto3
sts = boto3.client('sts')
assumed_role = sts.assume_role(
RoleArn='arn:aws:iam::222222222222:role/CrossAccountS3Access',
RoleSessionName='MySession'
)
credentials = assumed_role['Credentials']
s3 = boto3.client(
's3',
aws_access_key_id=credentials['AccessKeyId'],
aws_secret_access_key=credentials['SecretAccessKey'],
aws_session_token=credentials['SessionToken']
)
# Ahora puedes acceder S3 en Cuenta B
buckets = s3.list_buckets()
print(buckets)
3. Federación con Proveedores de Identidad Externos
Los roles permiten a usuarios autenticar con proveedores externos (Google, Facebook, Active Directory) y obtener acceso temporal a AWS.
Ejemplo: Web Identity Federation (Google Login)
# Trust policy para Google
cat > google-trust.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Federated": "accounts.google.com" },
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"accounts.google.com:aud": "YOUR_GOOGLE_CLIENT_ID"
}
}
}
]
}
EOF
aws iam create-role \
--role-name GoogleFederatedRole \
--assume-role-policy-document file://google-trust.json
aws iam attach-role-policy \
--role-name GoogleFederatedRole \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
Los usuarios inician sesión con Google, obtienen un ID token, y lo intercambian por credenciales temporales de AWS usando AssumeRoleWithWebIdentity.
4. Service-Linked Roles
Algunos servicios AWS crean automáticamente roles (service-linked roles) que no puedes modificar. Ejemplos:
AWSServiceRoleForElasticLoadBalancingAWSServiceRoleForAutoScalingAWSServiceRoleForRDS
Estos se crean y gestionan automáticamente por AWS.
AssumeRole: El Mecanismo Core
Cuando una entidad asume un rol, llama la API sts:AssumeRole (AWS Security Token Service). Esto retorna:
- AccessKeyId
- SecretAccessKey
- SessionToken
- Expiration (típicamente 1 hora, configurable hasta 12 horas)
Flujo
- Entidad llama
sts:AssumeRolecon ARN del rol. - AWS verifica la trust policy del rol.
- Si se permite, AWS retorna credenciales temporales.
- La entidad usa estas credenciales para hacer llamadas a API de AWS.
- Las credenciales expiran después del tiempo configurado.
Ejemplo CLI
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/MyRole \
--role-session-name MySession \
--duration-seconds 3600
# Output:
{
"Credentials": {
"AccessKeyId": "ASIAXXX...",
"SecretAccessKey": "xxx...",
"SessionToken": "xxx...",
"Expiration": "2025-09-02T12:00:00Z"
}
}
Mejores Prácticas
1. Usa Roles en Lugar de Access Keys para Servicios
# ❌ MAL: Embeber access keys en código
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# ✅ BIEN: Usar rol de EC2/Lambda
# Sin credenciales en código, AWS SDK las obtiene automáticamente
2. Usa Menor Privilegio en Permissions Policies
No adjuntes AdministratorAccess a roles a menos que sea absolutamente necesario.
{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::specific-bucket/*"
}
3. Limita Quién Puede Asumir Roles (Trust Policies)
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:user/specific-user" },
"Action": "sts:AssumeRole"
}
No uses "Principal": "*" a menos que sea por diseño.
4. Usa Condiciones en Trust Policies
Restringe cuándo/dónde se puede asumir un rol:
{
"Effect": "Allow",
"Principal": { "Service": "ec2.amazonaws.com" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "123456789012"
},
"StringLike": {
"aws:SourceArn": "arn:aws:ec2:us-east-1:123456789012:instance/*"
}
}
}
5. Habilita MFA para Roles Sensibles
Requiere MFA para asumir roles críticos:
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:root" },
"Action": "sts:AssumeRole",
"Condition": {
"Bool": { "aws:MultiFactorAuthPresent": "true" }
}
}
6. Usa ExternalId para Cross-Account Roles
Previene el “confused deputy problem” en acceso cross-account:
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111111111111:root" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": { "sts:ExternalId": "unique-external-id-12345" }
}
}
La cuenta que asume debe proporcionar el ExternalId correcto.
7. Monitorea Actividad de AssumeRole
Usa CloudTrail para auditar llamadas AssumeRole:
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole
Troubleshooting Común
Error: “User is not authorized to perform: sts:AssumeRole”
Causa: El usuario no está en el principal de la trust policy del rol.
Solución: Agrega el ARN del usuario a la trust policy del rol.
Error: “Access Denied” después de asumir rol
Causa: El rol fue asumido correctamente, pero la permissions policy del rol no otorga el permiso necesario.
Solución: Revisa y actualiza la permissions policy del rol.
EC2 instance no puede acceder S3
Causa: No se adjuntó instance profile a la instancia.
Solución:
aws ec2 associate-iam-instance-profile \
--instance-id i-1234567890abcdef0 \
--iam-instance-profile Name=MyEC2InstanceProfile
Conclusión
Los roles de IAM son esenciales para arquitectura segura en AWS. En esta Parte 2, cubrimos:
- Qué son los roles: Identidades con credenciales temporales.
- Cómo difieren de usuarios: Sin credenciales permanentes, asumibles.
- Trust vs Permissions policies: Quién puede asumir vs qué pueden hacer.
- Casos de uso:
- EC2/Lambda roles para servicios
- Cross-account access
- Federación con proveedores externos
- AssumeRole: El mecanismo para obtener credenciales temporales.
- Mejores prácticas: Menor privilegio, MFA, ExternalId, monitoreo.
Puntos clave:
- Siempre usa roles para servicios AWS (EC2, Lambda, ECS, etc.).
- Nunca embebas access keys en código.
- Usa menor privilegio en policies.
- Monitorea actividad de AssumeRole con CloudTrail.
En la siguiente parte de esta serie, exploraremos políticas avanzadas de IAM, policy boundaries y Service Control Policies (SCPs) en AWS Organizations.
Los roles son uno de los conceptos más poderosos en IAM — domínalos, y tu infraestructura AWS será más segura, escalable y mantenible.