DEV Community

Cover image for 🛡️ AWS IAM Access Analyzer — Parte 4/4
Terry Quispe Paniagua
Terry Quispe Paniagua

Posted on

🛡️ AWS IAM Access Analyzer — Parte 4/4

Después de probar External Access e Internal Access, me quedaba una tercera capacidad de IAM Access Analyzer por revisar: Unused Access.

La pregunta que quería responder era bastante simple:

¿Qué accesos sigo manteniendo aunque ya no se estén utilizando?

Pero había otra pregunta todavía más importante:

Si IAM ya muestra Last activity y datos de Last accessed, ¿por qué pagaría por otro analyzer?

Para responderlo configuré un analyzer real sobre una de mis cuentas, limité deliberadamente el scope para controlar el costo y lo dejé trabajando durante una semana.

El resultado fueron 18 findings sobre 17 principals, incluyendo roles completos sin uso, una contraseña de consola y, probablemente lo más interesante, permisos sin utilizar dentro de principals que no necesariamente estaban completamente inactivos.


Antes del lab: External vs Internal vs Unused Access

Las tres capacidades responden preguntas diferentes.

Analyzer Pregunta principal Qué analiza Pricing
External Access ¿Quién puede acceder desde fuera de mi zona de confianza? Recursos y resource-based policies Sin cargo adicional
Internal Access ¿Qué principals internos pueden acceder a recursos específicos? Permisos efectivos sobre recursos seleccionados Por recurso monitoreado/mes/región
Unused Access ¿Qué roles, credenciales o permisos ya no se utilizan? IAM users y roles Por IAM user/role analizado/mes

AWS documenta estas tres capacidades por separado porque no realizan el mismo análisis. External busca exposición pública o cross-account; Internal calcula acceso interno a recursos seleccionados; Unused analiza actividad histórica de identidades y permisos.


El laboratorio

No quería activar el analyzer sobre todo sin controlar primero el costo.

La configuración quedó así:

Analyzer:       UnusedAccess-Lab
Type:           ACCOUNT_UNUSED_ACCESS
Scope:          Current account
Tracking period: 60 days

Exclusion tag:
UnusedAnalyzerExclude=true
Enter fullscreen mode Exit fullscreen mode

Antes de crearlo etiqueté 30 roles que no quería incluir en este experimento.

Después de las exclusiones quedaron en scope:

16 IAM roles
 1 IAM user
-----------
17 principals
Enter fullscreen mode Exit fullscreen mode

Los service-linked roles tampoco forman parte del análisis. Son roles de IAM creados y administrados por servicios de AWS para ejecutar acciones en tu cuenta en nombre de ese servicio. Normalmente utilizan la ruta /aws-service-role/.

Unused Access Analyzer no los evalúa, por lo que tampoco cuentan dentro del número de roles analizados.

El tracking period fue de 60 días.

Esto no significa que haya que crear el analyzer y esperar 60 días. IAM Access Analyzer utiliza la información de last accessed que IAM ya mantiene, por lo que puede generar findings usando actividad anterior a la creación del analyzer.

El período configurado funciona como el umbral para generar los findings: un role puede aparecer cuando lleva ese tiempo inactivo, mientras que un permiso, password o access key puede aparecer cuando supera ese período sin uso. Para los permisos, AWS especifica además que solo evalúa permisos de entidades IAM que hayan existido durante todo el tracking period.

AWS permite configurar entre 1 y 365 días.


¿Cuánto cuesta Unused Access Analyzer?

Esta parte conviene entenderla antes de activarlo sobre una organización completa.

AWS cobra actualmente:

$0.20 USD
por IAM user o IAM role analizado
por analyzer
por mes
Enter fullscreen mode Exit fullscreen mode

No cobra por finding.

En este laboratorio dejé 17 principals dentro del análisis:

17 × $0.20 = $3.40 USD/mes
Enter fullscreen mode Exit fullscreen mode

Ese era el costo teórico del scope que había definido.

Y esta diferencia es importante porque finalmente obtuve 18 findings, pero eso no significa:

18 × $0.20
Enter fullscreen mode Exit fullscreen mode

La unidad de cobro es el principal analizado, no el número de findings que genera.

AWS cobra los analyzers de Internal y Unused Access una vez durante su configuración y, después, el primer día de cada mes calendario.

En este laboratorio activé UnusedAccess-Lab el 9 de agosto, por lo que el análisis inicial se cobró ese día. El siguiente ciclo de cobro no ocurre 30 días después, el 9 de septiembre, sino el 1 de septiembre para los principals que continúen dentro del análisis.

Por eso las exclusiones por tags pueden ser especialmente útiles. AWS permite excluir IAM users y roles mediante pares key=value; esos principals dejan de generar findings dentro de ese analyzer.

En mi caso utilicé:

UnusedAnalyzerExclude=true
Enter fullscreen mode Exit fullscreen mode

Después de una semana: 18 findings

El resultado terminó así:

Finding type Cantidad
UnusedIAMRole 14
UnusedIAMUserPassword 1
UnusedPermission 3
UnusedIAMUserAccessKey 0
Total 18

Los 18 findings corresponden a 17 principals porque un mismo principal puede generar más de un tipo de finding.

Eso ocurrió precisamente con el IAM user terraform.


Finding 1: un role realmente abandonado

Uno de los casos más simples fue:

Role:
ec2rolssm

Finding:
UnusedIAMRole

Last accessed:
2025-11-23 03:52:31 UTC
Enter fullscreen mode Exit fullscreen mode

Con un tracking period de 60 días, no había mucha ambigüedad: el role llevaba muchísimo más tiempo sin actividad.

El analyzer generó:

findingType: UnusedIAMRole
status: ACTIVE
Enter fullscreen mode Exit fullscreen mode

y mantuvo también el timestamp de su último acceso.

Este es probablemente el caso que cualquiera esperaría de un producto llamado Unused Access: encontrar roles que siguen existiendo aunque aparentemente ya nadie los use.

Pero este tampoco es el caso que justifica por sí solo pagar por el feature.

Para detectar algo así, IAM ya tiene información de último uso.

Lo interesante viene después.


Finding 2: también aparecieron roles de IAM Identity Center

Entre los findings apareció:

AWSReservedSSO_AWSAdministratorAccess_xxxxxxxxxxxxxxx
Enter fullscreen mode Exit fullscreen mode

con:

Finding:
UnusedIAMRole

Last accessed:
2025-10-06 01:52:45 UTC
Enter fullscreen mode Exit fullscreen mode

Es un role AWSReservedSSO_* generado por IAM Identity Center y también terminó identificado como unused.

No fue el único. Varios de los AWSReservedSSO_* que quedaron dentro del scope generaron findings.

Hay además una limitación relacionada: si un role de IAM Identity Center genera un finding de tipo UnusedPermission, AWS no soporta policy recommendations para ese tipo de role.


Finding 3: una contraseña que sigue existiendo pero ya no se usa

El único IAM user del experimento era:

terraform
Enter fullscreen mode Exit fullscreen mode

y generó:

findingType:
UnusedIAMUserPassword

lastAccessed:
2026-05-03 15:50:22 UTC
Enter fullscreen mode Exit fullscreen mode

Es decir: la contraseña de consola seguía asociada al IAM user, pero había superado ampliamente nuestra ventana de 60 días sin uso.

Este tipo de finding me parece más útil que revisar solamente roles.

Unused Access Analyzer también puede detectar:

Unused IAM roles
Unused IAM user passwords
Unused IAM user access keys
Unused permissions
Enter fullscreen mode Exit fullscreen mode

En este lab no apareció ninguna access key unused, así que no voy a fabricar un ejemplo que no ocurrió.


Finding 4: acá está la diferencia real con Last activity

El mismo user terraform generó además:

findingType:
UnusedPermission
Enter fullscreen mode Exit fullscreen mode

Y este finding es mucho más interesante.

El JSON devuelto por GetFindingV2 contenía 453 bloques unusedPermissionDetails y, dentro de ellos, 302 acciones individuales distribuidas en cinco servicios.

Es decir, el problema no era simplemente:

"este user nunca se usa"
Enter fullscreen mode Exit fullscreen mode

El finding no estaba limitado a un solo servicio. Aparecían permisos no utilizados en una gran cantidad de servicios; entre ellos ACM, CloudFormation, IAM, Route 53 y muchos otros.

Para mostrar el comportamiento sin convertir esta sección en una lista enorme, tomemos ACM como ejemplo.

El finding registraba actividad reciente sobre el servicio:

serviceNamespace:
acm

lastAccessed:
2026-08-12
Enter fullscreen mode Exit fullscreen mode

Pero dentro del mismo servicio aparecían acciones consideradas unused como:

acm:RequestCertificate
acm:ExportCertificate
acm:RenewCertificate
acm:ImportCertificate
acm:DeleteCertificate
...
Enter fullscreen mode Exit fullscreen mode

Algo parecido ocurría con CloudFormation e IAM: el servicio podía tener actividad reciente mientras numerosas acciones concedidas seguían apareciendo dentro del análisis de permisos no utilizados.

Y ahí está para mí el punto más fuerte del feature:

Que un principal esté activo no significa que necesite todos los permisos que tiene.


Entonces, ¿qué aporta si IAM ya muestra Last activity?

IAM ya tiene esa información y no tiene sentido ignorarlo.

Por ejemplo, RoleLastUsed puede indicar:

Last used date
Region
Enter fullscreen mode Exit fullscreen mode

para un role, con información disponible para los últimos 400 días.

IAM también dispone de datos de service last accessed y, para servicios soportados, información a nivel de acción.

De hecho, AWS documenta explícitamente que Unused Access Analyzer utiliza esa información de last accessed para generar sus findings.

Así que Unused Access Analyzer no tiene una fuente mágica de telemetría diferente.

La diferencia es operacional:

IAM Unused Access Analyzer
Consulto un principal Analiza principals a escala de cuenta u organización
Veo cuándo se usó un role Genera UnusedIAMRole
Reviso manualmente credenciales Detecta password/access key unused
Reviso Last Accessed Genera findings de permisos unused
Investigación puntual Monitoreo continuo
Datos Findings gestionables

La forma corta de decirlo sería:

IAM te entrega la evidencia. Unused Access Analyzer convierte esa evidencia en un proceso continuo de detección.

Para cinco roles probablemente puedo hacer una revisión manual.

Para cientos o miles de roles y users distribuidos por una AWS Organization, la conversación cambia (y el costo también).


Algo que observé: los findings no aparecieron todos al mismo tiempo

El analyzer fue creado el:

2026-08-09
Enter fullscreen mode Exit fullscreen mode

Los findings de roles y password aparecieron ese mismo día.

Sin embargo, los tres findings de UnusedPermission se crearon posteriormente, el:

2026-08-13
Enter fullscreen mode Exit fullscreen mode

Cuatro días después.

Y al revisar el JSON una semana después todos habían sido reanalizados nuevamente el 16 de agosto.

AWS no proporciona un tiempo exacto para que todos los findings estén disponibles; su documentación simplemente advierte que después de crear o actualizar un analyzer puede tomar tiempo antes de que aparezcan.

Para una prueba rápida puedes mirar los primeros findings casi inmediatamente, pero para una auditoría yo no asumiría que la primera pantalla representa necesariamente todo el análisis final.


Limitaciones que conviene conocer

1. Unused no significa automáticamente innecesario.

Un role de DR, una cuenta break-glass (acceso de emergencia) o un proceso trimestral puede pasar 60 días sin utilizarse y seguir siendo necesario.

El tracking period tiene que corresponder con el ciclo real de uso de tus accesos.


2. El detalle action-level tiene límites.

AWS puede evaluar unused permissions a nivel de servicio ampliamente, pero el análisis a nivel de acción depende de los servicios y acciones para los que IAM dispone de action last accessed information.


3. Los service-linked roles no se analizan.

No generan findings de unused access y tampoco forman parte del total de roles analizados para pricing.


4. No todos mis findings trajeron el mismo nivel de detalle.

En el JSON hubo varios UnusedIAMRole donde:

"unusedIamRoleDetails": {}
Enter fullscreen mode Exit fullscreen mode

sin un lastAccessed explícito.

Otros roles sí incluían la fecha.

Por eso no asumiría que cada finding tendrá exactamente la misma evidencia disponible.


Del finding a una policy de mínimo privilegio

Hasta aquí el analyzer ya había identificado qué permisos del principal no se estaban utilizando, pero el finding tenía otra funcionalidad interesante.

Al seleccionar un servicio, la consola abre un panel lateral con las acciones que no se han utilizado. Por ejemplo, para Certificate Manager aparecían 14 acciones sin uso.

Esto permite bajar del nivel:

Certificate Manager tiene permisos no utilizados
Enter fullscreen mode Exit fullscreen mode

a acciones concretas como:

acm:DeleteCertificate
acm:ExportCertificate
acm:GetCertificate
acm:ImportCertificate
acm:RenewCertificate
acm:RequestCertificate
...
Enter fullscreen mode Exit fullscreen mode

Pero el analyzer no se queda únicamente en mostrar el finding.

El IAM user terraform tenía asociadas estas tres policies:

backuppolicy
AdministratorAccess
putalternatecontact
Enter fullscreen mode Exit fullscreen mode

En la sección Recommendations, Access Analyzer evaluó esas policies y mostró:

Existing policy          Recommended policy
--------------------------------------------------------
backuppolicy             None
AdministratorAccess      AdministratorAccess-recommended
putalternatecontact      None
Enter fullscreen mode Exit fullscreen mode

Para backuppolicy y putalternatecontact no propuso una policy de reemplazo; la recomendación es retirar esas policies existentes. Para AdministratorAccess, en cambio, generó AdministratorAccess-recommended como policy de reemplazo.

Al abrir Preview policy, la consola permite comparar lado a lado la policy existente AdministratorAccess, que concede:

{
  "Effect": "Allow",
  "Action": "*",
  "Resource": "*"
}
Enter fullscreen mode Exit fullscreen mode

con la policy recomendada, que contiene un conjunto mucho más reducido de permisos.

Esta recomendación puede utilizarse para sustituir AdministratorAccess por permisos más ajustados y aplicar el principio de mínimo privilegio.

Importante: Access Analyzer genera la recomendación, pero no reemplaza automáticamente la policy. AWS indica que primero debes crear y adjuntar la policy recomendada y después retirar la policy existente.

Aquí es donde Unused Access Analyzer aporta algo más que simplemente indicar cuándo se utilizó por última vez un principal: además de detectar permisos no utilizados, puede proponer cómo reducir las permissions policies existentes.

La policy recomendada debe revisarse antes de aplicarla. Un permiso que no se utilizó durante el período analizado puede seguir siendo necesario para una tarea menos frecuente.


¿Lo habilitaría en producción?

Depende de la escala.

Si solamente tengo unos pocos roles y quiero responder:

¿Cuándo se utilizó este role por última vez?

IAM ya me da información suficiente para hacer esa revisión manual.

Pero si quiero responder continuamente:

¿Qué roles llevan demasiado tiempo sin utilizarse?

¿Qué IAM users conservan passwords o access keys abandonadas?

¿Qué principals siguen activos pero tienen permisos que nunca utilizan?

¿Dónde tengo oportunidades de reducir privilegios?
Enter fullscreen mode Exit fullscreen mode

entonces Unused Access Analyzer sí agrega una capa operacional útil.

En una organización grande no lo habilitaría sin pensar primero en el scope y en el costo.

La tarifa parece pequeña:

$0.20 / principal / mes
Enter fullscreen mode Exit fullscreen mode

pero:

100 principals   = $20/mes
1,000 principals = $200/mes
10,000 principals = $2,000/mes
Enter fullscreen mode Exit fullscreen mode

por analyzer.

Las exclusiones mediante tags existen precisamente para controlar qué principals quieres analizar. AWS incluso recomienda utilizar una estrategia de tagging y exclusiones como mecanismo de optimización de costos.


Conclusión

Este laboratorio empezó con una duda bastante válida:

¿Para qué pagar por Unused Access Analyzer si IAM ya muestra Last activity?

Después de revisar los findings, mi respuesta es que no compiten exactamente por lo mismo.

Si quiero investigar un role concreto, IAM ya tiene información muy útil.

Pero Unused Access Analyzer toma esa información y la convierte en un mecanismo continuo para encontrar roles abandonados, credenciales sin uso y, sobre todo, permisos sobrantes dentro de principals que todavía tienen actividad.

En mi caso, encontrar roles que no se utilizaban desde hacía meses era esperado.

Lo que aportó más información fue ver un principal con actividad sobre determinados servicios mientras seguía acumulando cientos de permisos que el analyzer identificaba como no utilizados.

Ahí es donde el feature empieza a tener sentido para least privilege.

Eso sí: unused no significa automáticamente removable.

El finding es el inicio de la revisión, no la autorización para borrar permisos a ciegas.

Y, como con los otros analyzers de esta serie, primero conviene tener claro qué pregunta quieres responder. External, Internal y Unused Access pueden vivir bajo IAM Access Analyzer, pero están mirando problemas de seguridad bastante diferentes.


Referencias

AWS #IAM #AccessAnalyzer #CloudSecurity #LeastPrivilege #AWSOrganizations #DevSecOps #IAMSecurity

Top comments (0)