De CSVs crudos a un dashboard visual que cualquiera puede correr con un solo comando Docker — y cómo cada feature nació de una necesidad real.

El gancho

El primer script funcionaba. Recorría más de 20 cuentas AWS, asumía roles con mínimo privilegio, y producía dos CSVs con todo lo que necesitabas saber sobre Access Keys y eventos de remediación. Técnicamente correcto. Completo. Útil.

Pero cuando llegó el momento de compartir los resultados con el equipo, me di cuenta de algo incómodo: un CSV es una respuesta para quien sabe hacer las preguntas correctas. Para el resto, es ruido.

El engineer abre el CSV y ve los datos. El CISO abre el CSV y ve filas. Son el mismo archivo — pero no son la misma experiencia.

Eso me llevó a una pregunta que cambió la dirección del proyecto: ¿qué pasaría si los hallazgos se pudieran ver, filtrar y entender sin abrir una sola hoja de cálculo?

El contexto

Cuando trabajás en seguridad en entornos enterprise, rápidamente aprendés que los hallazgos técnicos tienen dos vidas distintas. La primera es la vida técnica — el dato crudo, el campo, el valor, la fecha. La segunda es la vida ejecutiva — el riesgo, el impacto, la urgencia. El problema es que la mayoría de las herramientas solo hablan uno de esos dos idiomas.

Un CSV habla el primero. Y está bien — para el CloudSec Engineer que necesita triagear, filtrar por cuenta, ordenar por antigüedad de key, y exportar para un ticket. Pero para el CISO que necesita entender en 30 segundos cuál es el estado de seguridad de la organización, un CSV es una barrera, no una respuesta.

Esta tensión no es nueva. Las herramientas comerciales de seguridad lo resuelven hace años — CSPM como Wiz o Prisma Cloud tienen dashboards ejecutivos muy pulidos. Pero no todos los equipos tienen presupuesto para esas plataformas, y menos en LATAM donde muchas organizaciones están todavía construyendo su baseline de seguridad.

Con eso claro, el siguiente paso del proyecto era obvio: los datos ya estaban. Lo que faltaba era la capa de presentación — sin costo, sin dependencias externas, sin fricción.

Feature 1: El dashboard

De datos a visibilidad: el dashboard HTML

La decisión de usar HTML puro fue intencional. Podría haber usado Grafana, QuickSight, o cualquier herramienta de visualización — pero todas tienen el mismo problema: requieren infraestructura, configuración, o una cuenta en algún servicio. Un archivo HTML no requiere nada. Lo abrís en cualquier browser, en cualquier máquina, sin instalar nada.

El mecanismo es simple: el script genera los CSVs como siempre, pero antes de terminar los embebe directamente dentro del HTML como strings. El dashboard los parsea en el browser con JavaScript y los convierte en widgets interactivos. Sin backend, sin base de datos, sin dependencias — un solo archivo autocontenido.

Una advertencia importante: el HTML generado contiene datos reales de tu organización. Tratalo con la misma sensibilidad que tratarías un CSV con información de cuentas y usuarios — no lo compartas por canales no seguros, no lo subas a repositorios públicos, y asegurate de que el directorio output/ esté en tu .gitignore. El script ya lo contempla, pero vale la pena tenerlo presente.

El dashboard tiene cuatro vistas principales:

  • Resumen ejecutivo — total de cuentas auditadas, total de Access Keys, keys activas vs inactivas, usuarios sin MFA
  • Risk scoring por usuario — priorización automática basada en antigüedad de la key, estado activo, y ausencia de MFA
  • Tendencia de remediación — gráfico de eventos CloudTrail en el tiempo, para ver si el equipo está efectivamente remediando
  • Tabla de hallazgos — filtrable por cuenta, por estado, por nivel de riesgo

Los filtros son globales — cuando filtrás por cuenta, todos los widgets se actualizan al mismo tiempo. Eso es lo que lo hace útil para una presentación: podés mostrar el estado de una cuenta específica en segundos, sin exportar nada ni cambiar de herramienta.

Dashboard interactivo generado por iam-audit v2

Feature 2: Root account detection

La cuenta que todos ignoran: root account detection

Hay un usuario en cada cuenta AWS que no aparece en ningún listado de IAM Users. No tiene MFA obligatorio por defecto. No genera alertas si alguien lo usa. Y tiene acceso irrestricto a absolutamente todo en la cuenta. A diferencia de cualquier otro usuario IAM, sus permisos no pueden reducirse con políticas de identidad — aunque sí es posible restringir ciertas acciones a nivel organizacional mediante SCPs. AWS Control Tower incluye dos guardrails preventivos específicos para esto: uno que impide habilitar Access Keys en la root account, y otro que impide ejecutar acciones como root. Para detectar si MFA está habilitado, existe además un guardrail detectivo — Detect Whether MFA for the Root User is Enabled — implementado via AWS Config Rule. Sin embargo, ninguno de estos mecanismos te da visibilidad consolidada del estado de root en todas tus cuentas en un solo lugar. Eso es exactamente el gap que este feature resuelve.

El AWS Security Maturity Model v2 es explícito sobre esto. En su Phase 1 — Quick Wins, dentro del dominio de Identity and Access Management, uno de los controles fundamentales es Root Account Protection — garantizar que la root account tenga MFA activo, no tenga Access Keys activas, y que su uso sea monitoreado. No es una recomendación avanzada. Es baseline. Es lo primero que deberías tener resuelto antes de cualquier otra cosa.

Agregar este control al script fue una decisión lógica: si ya estabas auditando IAM Users en cada cuenta, no auditar la root account era dejar el hallazgo más crítico fuera del reporte.

Lo que audita el script por cada cuenta:

  • MFA habilitado — si la root account tiene MFA activo o no
  • Access Keys activas — si existe alguna Access Key asociada a root, lo que AWS recomienda explícitamente evitar
  • Último login — cruzado con eventos ConsoleLogin de CloudTrail filtrados por identidad root, para detectar si alguien usó la root account recientemente

Este último punto es el más valioso para un CISO: no es solo saber si la root tiene MFA — es saber si alguien la usó en los últimos 90 días. Eso es lo que convierte un hallazgo técnico en una conversación de riesgo real.

Widget de root account detection — MFA, Access Keys y último login por cuenta

Feature 3: Docker

Un comando. Sin instalar nada. Eso es lo que quedaba.

El script ya auditaba. El dashboard ya visualizaba. Pero había un paso que seguía siendo una barrera invisible: para correrlo, necesitabas Python instalado, boto3 instalado, y el repo clonado. Para un CloudSec Engineer eso es trivial. Para alguien que quiere evaluar la herramienta rápido, o para un equipo que no quiere gestionar dependencias de Python en sus máquinas, es fricción suficiente para no intentarlo.

Docker elimina esa fricción por completo.

La decisión de dockerizar no fue sobre tecnología — fue sobre accesibilidad. Si el objetivo era construir algo que cualquier equipo en LATAM pudiera usar sin importar su stack local, la imagen tenía que ser la unidad de distribución. No el repo, no el requirements.txt, no las instrucciones de instalación. La imagen.

El resultado es este comando:

docker run --rm \

-v ~/.aws:/root/.aws \

-v $(pwd)/output:/app/output \

-p 8000:8000 \

gerardokaztro/iam-audit \

--profile YOUR-AWS-PROFILE \

--role YOUR-AUDIT-ROLE

Eso es todo. Docker descarga la imagen desde Docker Hub, monta tus credenciales AWS locales, corre la auditoría, genera el dashboard, y lo sirve en http://localhost:8000. Cuando terminás, Ctrl+C y listo — sin residuos, sin dependencias instaladas en tu máquina.

Dos decisiones de diseño que vale la pena mencionar:

La primera es el montaje de credenciales. En lugar de pasar Access Keys como variables de entorno — que sería exactamente lo contrario de lo que el script audita — el contenedor monta el directorio ~/.aws de tu máquina local. Tus credenciales nunca están hardcodeadas, nunca están en la imagen, y expiran si usás roles con aws sso login.

La segunda es el volumen de output. El directorio output/ se monta como volumen externo, lo que significa que los archivos generados — CSVs y dashboard HTML — quedan en tu máquina local aunque el contenedor se destruya. Sin volumen, perderías los reportes al hacer Ctrl+C.

La imagen está publicada en Docker Hub en gerardokaztro/iam-audit y se construye automáticamente desde el Dockerfile del repositorio.

De un comando en terminal a un dashboard en el browser

Los hallazgos

Lo que muestra el dashboard cuando lo corrés en producción

Correr iam-audit v2 contra la misma AWS Organization del primer post produjo algo cualitativamente distinto al CSV original. No porque los datos fueran diferentes — sino porque la presentación cambió completamente la conversación.

El resumen ejecutivo del dashboard mostró el estado de la organización en un vistazo:

HallazgoResultado
Cuentas auditadasMás de 20 cuentas activas
Access Keys encontradasDecenas
Key más antiguaCreada en 2018 — activa en producción
Usuarios sin MFA + acceso a consolaDecenas
Cuentas root sin MFAVarias
Cuentas root con Access Keys activasNinguna
Tiempo total de ejecuciónMinutos

El widget de risk scoring fue el más útil para priorizar la remediación. Ver qué usuarios combinaban key antigua + sin MFA + acceso a consola activo — todo en una sola vista, filtrable por cuenta — es lo que convierte un reporte en un plan de acción.

Risk scoring por usuario — priorización automática de hallazgos

El widget de root account fue el más impactante para la conversación ejecutiva. No porque hubiera hallazgos críticos en todas las cuentas — sino porque por primera vez había una respuesta visual e inmediata a la pregunta: ¿cuál es el estado de root en toda la organización? Antes de este feature, esa pregunta no tenía respuesta consolidada.

Estado de root account por cuenta — MFA, Access Keys y último login

El dato que más llamó la atención no fue técnico — fue de proceso. La tendencia de remediación en CloudTrail mostró que los eventos de DeleteAccessKey aumentaron significativamente después de compartir el primer reporte. El script no solo encontró el problema — creó el mecanismo para medir si se estaba resolviendo.

Tendencia de remediación vía CloudTrail — los DeleteAccessKey aumentaron después del primer reporte

El cierre

Que las herramientas evolucionan cuando las usás en producción con personas reales. El script del primer post era técnicamente correcto — pero la realidad del campo lo fue empujando hacia algo más completo. El dashboard nació porque un CSV no comunicaba para todas las audiencias. El root account detection nació porque el ASMM lo pedía y nadie lo tenía resuelto de forma consolidada. Docker nació porque la accesibilidad importa tanto como la funcionalidad.

Ninguna de esas decisiones vino de un roadmap planificado. Vinieron de usar la herramienta, escuchar lo que faltaba, y construir la siguiente capa.

Eso es exactamente lo que quiero documentar en Road to CloudSec LATAM — no el resultado final pulido, sino el proceso real de construcción iterativa. Las decisiones de diseño, los errores, los ajustes. Porque eso es lo que realmente enseña.

Si querés correr iam-audit v2 en tu propia AWS Organization, todo lo que necesitás está en el repositorio. Sin costo, sin infraestructura adicional, sin dependencias más allá de Docker y un rol de auditoría con mínimo privilegio.

🔗 Image Docker: gerardokaztro/iam-audit

docker run --rm \

-v ~/.aws:/root/.aws \

-v $(pwd)/output:/app/output \

-p 8000:8000 \

gerardokaztro/iam-audit \

--profile YOUR-AWS-PROFILE \

--role YOUR-AUDIT-ROLE

⭐️ GitHub: iam-audit

Si lo corres, si encuentrass algo interesante, o si tienes feedback — escribeme. La comunidad de CloudSec en LATAM se construye compartiendo lo que funciona en entornos reales.

Sobre el autor

Gerardo Castro es AWS Security Hero y Cloud Security Engineer con foco en LATAM. Fundador y Lead Organizer del AWS Security Users Group LatAm. Cree que la mejor forma de aprender seguridad en la nube es construyendo cosas reales — no memorizando frameworks. Escribe sobre lo que construye, lo que encuentra, y lo que aprende en el camino.

🐳 Docker Hub: gerardokaztro

⭐️ GitHub: gerardokaztro

🔗 LinkedIn: gerardokaztro

Gerardo Castro

Gerardo Castro

AWS Security Hero · Founder, AWS Security Users Group LatAm

Cloud Security Engineer con foco en LATAM. Cree que la mejor forma de aprender seguridad en la nube es construyendo cosas reales — no memorizando frameworks.

Comentarios