En los posts anteriores creamos nuestra cuenta, aseguramos el root con MFA y creamos un usuario IAM con AdministratorAccess. Pero ¿qué significa exactamente eso de “AdministratorAccess”? ¿Cómo decide AWS qué puede y qué no puede hacer un usuario o un servicio? La respuesta está en dos conceptos fundamentales: Policies y Roles. En este post vamos a entender cómo funcionan, para qué sirven y por qué son tan importantes.
¿Qué es una Policy?
Una Policy (política) es un documento en formato JSON que define permisos: qué acciones están permitidas o denegadas, sobre qué recursos y bajo qué condiciones. Es la forma en que AWS controla el acceso a absolutamente todo.
Cada policy tiene una estructura como esta:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mi-bucket-010791/*"
}
]
}
Vamos a desglosar cada parte:
- Version: siempre
"2012-10-17"(es la versión actual del lenguaje de policies, no la fecha de nuestra policy). - Statement: es un array de “declaraciones” o reglas. Cada una define un permiso.
- Effect: puede ser
"Allow"(permitir) o"Deny"(denegar). - Action: la acción o acciones que estamos permitiendo o denegando. Se escriben como
servicio:acción(por ejemplo,s3:GetObjectpara leer objetos de S3,ec2:StartInstancespara iniciar instancias EC2). - Resource: el ARN (Amazon Resource Name) del recurso específico al que aplica la regla. Si queremos que aplique a todo, usamos
"*".
Tip: Pensá en una policy como un cartel que dice “esta persona puede hacer X cosa en Y lugar”. Sin una policy que lo permita explícitamente, todo está denegado por defecto en AWS.
Tipos de Policies
AWS tiene varios tipos de policies, pero las más importantes para empezar son:
AWS Managed Policies: son policies creadas y mantenidas por AWS. Las reconocés porque tienen un ícono de AWS al lado. La que usamos en el post anterior, AdministratorAccess, es una de estas. Hay cientos disponibles para los casos de uso más comunes (ReadOnlyAccess, AmazonS3FullAccess, AmazonEC2ReadOnlyAccess, etc.).
Customer Managed Policies: son policies que creamos nosotros. Nos dan control total para definir permisos a medida, siguiendo el principio de menor privilegio.
Inline Policies: son policies que se crean directamente dentro de un usuario, grupo o role (no existen de forma independiente). Se usan para casos muy específicos, pero en general es mejor usar managed policies porque son reutilizables.
Para ver las policies disponibles, vamos a IAM → Policies en el menú lateral izquierdo.

Nuestra policy actual: AdministratorAccess
Antes de crear policies nuevas, veamos qué tiene adentro la policy que ya estamos usando. En la lista de policies, usamos el buscador y filtramos por admin. Vamos a ver varias policies que empiezan con “Administrator”, entre ellas AdministratorAccess que es la que tenemos adjunta a nuestro usuario. Hacemos clic en ella para ver su contenido.

El JSON de AdministratorAccess es simplemente:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
Básicamente dice: “permitir todas las acciones sobre todos los recursos”. Por eso decíamos que es una policy muy permisiva — es el equivalente a ser root pero como usuario IAM.

Importante: En un entorno productivo, nunca deberías usar
AdministratorAccesspara tareas del día a día. Lo ideal es crear policies específicas con solo los permisos que realmente necesitás. Esto se conoce como el principio de menor privilegio (least privilege).
Crear una Policy personalizada
Vamos a crear una policy propia para entender el proceso. Queremos una policy que permita solo leer objetos de un bucket S3 específico (por ejemplo, para un usuario o servicio que solo necesita consultar archivos).
Nota: Para este ejemplo creé previamente un bucket llamado
mi-bucket-010791. Como los nombres de bucket en S3 son únicos a nivel global, vas a tener que usar uno propio (con un nombre disponible). Más adelante, en otro post, vamos a profundizar en cómo crear y configurar buckets S3 paso a paso.
En IAM → Policies, hacemos clic en Create policy.

AWS nos ofrece dos formas de crear la policy: el Visual editor (un formulario guiado) y el JSON editor (donde escribimos el JSON directamente). Vamos a usar el JSON editor para entender bien la estructura.
Seleccionamos la pestaña JSON en el editor y pegamos el siguiente JSON:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::mi-bucket-010791",
"arn:aws:s3:::mi-bucket-010791/*"
]
}
]
}
Esta policy permite dos acciones: s3:ListBucket (listar los objetos del bucket) y s3:GetObject (descargar/leer los objetos). Y solo aplica al bucket mi-bucket-010791 y a todos sus objetos (mi-bucket-010791/*).

¿Por qué dos Resources? Porque en S3, el bucket y los objetos dentro de él son recursos diferentes.
s3:ListBucketopera sobre el bucket (arn:aws:s3:::mi-bucket-010791), mientras ques3:GetObjectopera sobre los objetos dentro del bucket (arn:aws:s3:::mi-bucket-010791/*).
Hacemos clic en Next. AWS nos muestra la pantalla de Review and create donde le damos un nombre descriptivo a la policy (por ejemplo, s3-mi-bucket-010791-read), una descripción y podemos ver un resumen de los permisos que definimos.

Dejamos la sección de Tags vacía (es opcional) y hacemos clic en Create policy.
Listo, ya tenemos nuestra primera policy personalizada. Podemos adjuntarla a cualquier usuario, grupo o role que necesite solo lectura sobre ese bucket específico.
¿Qué es un Role?
Ahora vamos con el segundo concepto clave. Un Role (rol) es una identidad de IAM que, a diferencia de un usuario, no tiene credenciales permanentes (no tiene contraseña ni access keys propias). En su lugar, cualquiera que “asuma” un role recibe credenciales temporales que expiran automáticamente.
¿Y quién puede “asumir” un role? Tres tipos de entidades:
- Servicios de AWS: por ejemplo, una instancia EC2 que necesita acceder a S3, o una función Lambda que necesita escribir en DynamoDB. En lugar de poner access keys dentro del código (un gran riesgo de seguridad), le asignamos un role al servicio.
- Usuarios de IAM: un usuario puede asumir un role para obtener permisos temporales diferentes a los que tiene normalmente (por ejemplo, permisos elevados para una tarea puntual).
- Cuentas externas o Identity Providers: para acceso cross-account (entre cuentas de AWS) o federación con servicios externos.
Analogía: Si una policy es un “carnet de permisos”, un role es un “chaleco que te ponés temporalmente”. Mientras lo tenés puesto, podés hacer ciertas cosas. Cuando te lo sacás (o expira), ya no.
¿Cómo funciona un Role por dentro?
Un role tiene dos partes fundamentales:
1. Trust Policy (política de confianza): define quién puede asumir el role. Es un JSON que especifica las entidades autorizadas.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
En este ejemplo, solo el servicio EC2 puede asumir este role.
2. Permissions (permisos): son las policies adjuntas al role que definen qué puede hacer quien lo asuma. Pueden ser managed policies o inline policies, igual que con un usuario.
Para ver los roles existentes en nuestra cuenta, vamos a IAM → Roles en el menú lateral.

Ejemplo práctico: un Role para EC2
Para entender mejor cómo funciona un role, vamos a ver un caso de uso muy común: una instancia EC2 (un servidor virtual en AWS) que necesita leer archivos de un bucket S3.
Sin un role, tendríamos que guardar access keys dentro del servidor para que pueda comunicarse con S3. Esto es un riesgo de seguridad enorme: si alguien accede al servidor, tiene las llaves. Con un role, en cambio, EC2 recibe credenciales temporales automáticamente — sin que tengamos que almacenar nada.
Vamos a crear un role para verlo en acción. En la pantalla de Roles, hacemos clic en Create role.

AWS nos pide seleccionar el tipo de entidad de confianza (Trusted entity type). Como queremos que un servicio de AWS use este role, seleccionamos AWS service. Más abajo, en la sección Use case, abrimos el dropdown Service or use case y elegimos EC2.

A continuación, AWS nos muestra las distintas opciones de uso para EC2. Seleccionamos la primera, EC2 (Allows EC2 instances to call AWS services on your behalf), que es la opción básica para permitir que una instancia EC2 use AWS APIs. Hacemos clic en Next.

¿Qué hace esta selección? AWS genera automáticamente la Trust Policy del role que vimos antes (la que tiene
"Service": "ec2.amazonaws.com"), así no tenemos que escribirla a mano.
Ahora toca asignar los permisos al role. En el buscador escribimos s3-mi-bucket-read (la policy que creamos antes) y la tildamos. Hacemos clic en Next.

En la pantalla de Name, review, and create le damos un nombre descriptivo al role (por ejemplo, ec2-s3-read) y una descripción. Más abajo podemos revisar la Trust policy que AWS generó automáticamente al elegir EC2 como entidad de confianza.

Si bajamos un poco más, vemos el resumen de los permisos (la policy s3-mi-bucket-read) y la sección de Tags (opcional). Hacemos clic en Create role.

Así funciona un role en la práctica: cuando lancemos una instancia EC2 y le asignemos este role, la instancia va a poder leer objetos de S3 automáticamente, sin access keys, sin credenciales hardcodeadas. AWS se encarga de rotar las credenciales temporales de forma transparente. Más seguro, más limpio.
Policies vs Roles: ¿cuál es la diferencia?
Para resumir la relación entre ambos:
- Una Policy define qué se puede hacer (los permisos).
- Un Role define quién puede hacerlo temporalmente (mediante la Trust Policy) y qué puede hacer (adjuntando policies de permisos).
Dicho de otra forma: los roles contienen policies. Un role sin policies no tiene ningún permiso, y una policy sin estar adjunta a algo (usuario, grupo o role) no hace nada por sí sola.
El principio de menor privilegio
Ahora que entendemos cómo funcionan las policies y los roles, hay un concepto de seguridad que es clave: el principio de menor privilegio (least privilege). La idea es simple: cada usuario, servicio o role debería tener únicamente los permisos que necesita para hacer su trabajo, y nada más.
En la práctica, esto significa:
- Evitar usar
AdministratorAccesso"Action": "*"salvo que sea realmente necesario. - Crear policies específicas para cada caso de uso (como la policy de S3 que creamos más arriba).
- Revisar periódicamente los permisos y eliminar los que ya no se usan. IAM tiene una herramienta llamada Access Analyzer que ayuda con esto.
- Preferir roles con credenciales temporales en lugar de access keys permanentes.
Tip: AWS recomienda empezar con permisos mínimos e ir agregando los que hagan falta a medida que surjan necesidades reales, en lugar de empezar con acceso total e ir restringiendo después.
Conclusiones
En este post vimos los dos pilares fundamentales de IAM: las Policies definen los permisos (qué se puede hacer y sobre qué recursos) y los Roles permiten que servicios y usuarios asuman esos permisos de forma temporal y segura. Lo pusimos en práctica creando un bucket S3 (mi-bucket-010791), una policy personalizada para ese bucket (s3-mi-bucket-read) y un role para EC2 (ec2-s3-read) que le permite a una instancia leer ese bucket sin necesidad de access keys.
Con estos conceptos claros, en el próximo post vamos a dar el salto a IAM Identity Center, la forma moderna y recomendada por AWS para gestionar el acceso humano a nuestras cuentas. Vamos a migrar de nuestro usuario IAM admin a un acceso centralizado con Permission Sets, que básicamente son colecciones de policies pero gestionadas de una manera mucho más escalable.