¿Te interesa saber cuándo alguien accede de manera no autorizada mediante una access key o asumiendo un rol? ¿O cuándo alguien que ya no trabaja con ustedes usa una credencial que tenía clonada en su notebook para destruir todo?
La buena noticia es que AWS ya registra cada una de esas acciones. La mala es que casi nadie las mira mientras pasan, y uno termina enterándose días después, cuando algo deja de funcionar. En este artículo vamos a recorrer, sin comandos ni configuración, la idea detrás de un sistema que cierra esa brecha: cómo funciona, qué te puede avisar, qué ganás con tenerlo y cuánto cuesta.
Si después querés implementarlo, el paso a paso con el código esencial, los comandos y la configuración de cada pieza está en la versión técnica de este artículo en AWS Builder Center.
La idea, en una frase
Toda actividad en tus cuentas de AWS queda registrada. Lo que proponemos es poner un filtro sobre ese registro que deje pasar solo lo peligroso, una función que decida qué tan grave es cada evento, y un canal de Slack donde el equipo lo vea en minutos.
Así se ve el recorrido completo:
Cada llamada a tu AWS deja una huella
Todo empieza en CloudTrail, el registro de auditoría de AWS. Cada vez que alguien (o algo) llama a la API, CloudTrail guarda un evento con qué se hizo, en qué servicio, cuándo, desde qué IP, en qué cuenta y si funcionó o falló.
Pero el dato que hace posible todo este sistema es otro: el campo userIdentity.type, que dice con qué tipo de credencial se hizo cada llamada.
| Tipo | Qué significa |
|---|---|
Root | Alguien usó la cuenta root |
IAMUser | Una credencial de larga duración: access key o password de un IAM user |
AssumedRole | Una credencial temporal, obtenida al asumir un rol |
AWSAccount | Otra cuenta de AWS asumió un rol tuyo |
AWSService | Un servicio de AWS actuó en tu nombre |
Con esta tabla en mente, cada escenario del principio tiene una firma reconocible. La access key olvidada en una notebook aparece como IAMUser. El tercero que entra asumiendo un rol tuyo desde su cuenta aparece como AWSAccount. Y un login con root aparece, justamente, como Root.
Las piezas que lo hacen posible
Ahora que sabemos qué información tenemos, veamos quién se encarga de cada parte del trabajo:
- La organization trail. En una organización de AWS (por ejemplo, gestionada con Control Tower), una sola trail registra los eventos de todas las cuentas. Es un único lugar para mirar todo.
- CloudWatch Logs. La trail envía ahí los eventos, a un log group en la cuenta de management.
- Los subscription filters. Son reglas enganchadas a ese log group que dejan pasar solo los eventos que coinciden con un patrón. Funcionan como un portero: la función nunca ve las millones de llamadas normales.
- La función Lambda. Recibe lo que pasó el filtro y le asigna una criticidad. Es la única pieza con lógica propia, y esa lógica es acotada: decodificar, clasificar y publicar.
- Amazon Q Developer. Es el servicio de AWS que publica en Slack (o Teams) los mensajes que llegan a un topic SNS. Gracias a él, no hace falta guardar un webhook de Slack como secreto.
Qué pasa cuando alguien toca algo
Con las piezas presentadas, sigamos un caso concreto: alguien borra una base de datos de producción usando una access key.
- CloudTrail registra el evento en la organization trail.
- El evento llega a CloudWatch Logs en un promedio de unos 5 minutos (AWS aclara que ese tiempo no está garantizado).
- El filtro lo evalúa. Si no coincidiera con ningún patrón, todo terminaría ahí, sin costo de cómputo. En este caso coincide.
- La función calcula la criticidad combinando tres ejes:
- la cuenta, porque producción pesa más que desarrollo;
- el servicio, porque tocar RDS, DynamoDB, KMS, AWS Backup, Secrets Manager o IAM pesa más que borrar una instancia efímera;
- el tipo de credencial, porque una de larga duración (
IAMUser) pesa más que una temporal.
- El mensaje llega a Slack con 🔴, 🟠 o 🟡 según la criticidad, junto con la cuenta, la acción, quién la hizo, con qué credencial y desde qué IP.
¿Y si la función falla? En ese caso, AWS la reintenta dos veces más. Si aun así no lo logra, el evento queda guardado en una cola de respaldo y una alarma avisa al equipo, para que ninguna alerta se pierda en silencio.
La decisión que lo cambia todo: quién y qué
Hasta acá, todo parece directo. Sin embargo, hay una decisión de diseño que define si el sistema realmente te protege: qué dejar pasar por el filtro.
La tentación natural es alertar solo sobre lo que hacen las personas del equipo (por ejemplo, los usuarios que entran por SSO), para no llenar el canal con lo que hacen los pipelines y los controladores de Kubernetes. El problema es que un IAM user con una access key no entra por SSO. Un filtro así deja afuera, justamente, la credencial que sobrevive cuando alguien se va.
La salida es separar el problema en dos preguntas, y CloudWatch Logs lo permite porque cada log group admite hasta dos filtros:
- ¿Quién está actuando? Uso de root, login sin MFA, cambios en CloudTrail, cualquier escritura hecha con una credencial de larga duración y cambios de IAM que dejan una puerta abierta, como crear access keys o cambiar trust policies.
- ¿Qué se está destruyendo? Borrados y acciones irreversibles hechos por cualquier actor, excluyendo a los servicios de AWS y a las automatizaciones conocidas.
Y no hace falta inventar los patrones desde cero: AWS publica, en los controles CloudWatch.1 a CloudWatch.14 de Security Hub (basados en el CIS AWS Foundations Benchmark), los patrones oficiales para root, MFA, cambios de IAM, CloudTrail, KMS, S3 y red. Son el mejor punto de partida.
Lo que este sistema puede ver por vos
Con esos dos filtros funcionando, estas son algunas de las situaciones que te van a llegar a Slack:
- Offboarding incompleto. Alguien que ya no está usa una access key que nadie revocó, y la alerta llega con el tipo de credencial y el nombre del IAM user.
- Credenciales filtradas. Una access key expuesta en un repositorio se usa desde una IP que no reconocés.
- Puertas traseras. Alguien crea una access key nueva o modifica una trust policy para poder volver.
- Uso de root y logins sin MFA, dos de los controles más básicos.
- Intentos de borrar evidencia, como apagar o modificar CloudTrail.
- Acciones destructivas sobre datos: borrar una base, un backup o programar el borrado de una llave KMS.
- Errores honestos. No todo es un ataque: también detecta el destroy en la cuenta equivocada, y enterarse en minutos ayuda igual.
Por qué vale la pena tenerlo montado
Más allá de los casos puntuales, tener esto funcionando cambia la forma en que el equipo ve su infraestructura:
- Pasás de enterarte tarde a enterarte en minutos. Esa es la diferencia más importante.
- Toda la organización queda en un solo lugar. Una trail, un log group y una función cubren todas las cuentas, presentes y futuras.
- Cada alerta trae su contexto. Cuenta, acción, actor, credencial e IP: quien está de guardia sabe qué mirar sin abrir la consola.
- La criticidad evita el ruido. Un borrado en producción se ve distinto a uno en desarrollo, y eso hace que el canal no se ignore.
- Todo es nativo. Sin agentes, sin servidores y sin un SIEM que mantener, y se despliega como cualquier otra pieza de infraestructura como código.
- Crece con vos. Sumar un patrón nuevo no cambia la arquitectura.
Cuando quieras ir más allá: bases de datos, llaves y backups
Una vez que el sistema funciona, el filtro de "qué se destruye" es el que más vale la pena ajustar a tu negocio. Estas son algunas acciones que conviene sumar:
- RDS y Aurora: borrar instancias, clusters, snapshots o backups automáticos, detener la base y, sobre todo, compartir un snapshot con otra cuenta o hacerlo público, que es una forma silenciosa de sacar datos.
- DynamoDB: borrar tablas o backups.
- KMS: programar el borrado o deshabilitar una llave. Sin la llave, el dato cifrado no se recupera.
- AWS Backup: borrar recovery points o vaults, o cambiar su política de acceso. Es el último recurso de recuperación.
- Secrets Manager: borrar secretos.
Un matiz importante: en DynamoDB, borrar una tabla queda registrado por defecto, pero borrar ítems uno por uno no. Esos son data events, y hay que habilitarlos aparte en la trail, con costo adicional.
Cuánto cuesta tenerlo funcionando
En la mayoría de los casos, muy poco. Todo depende de una pregunta: ¿tu trail ya envía eventos a CloudWatch Logs?
| Componente | Cómo se cobra | Qué esperar |
|---|---|---|
| CloudTrail, primera copia de management events | Gratis cuando se entrega a S3 | Sin costo nuevo |
| CloudTrail a CloudWatch Logs | USD 0,25 por GB de entrega más la ingesta de CloudWatch Logs | El componente principal si todavía no lo tenés. Con Control Tower ya existe |
| Lambda | USD 0,20 por millón de invocaciones y USD 0,0000166667 por GB-s (x86), con free tier de 1 millón de invocaciones y 400.000 GB-s por mes | Prácticamente cero: solo corre con los eventos filtrados |
| SNS | Por publicación | Un mensaje por alerta |
| Amazon Q Developer, custom notifications | Sin costo adicional | Cero |
Para tener una referencia concreta: en una organización de siete cuentas que ya tenía la trail enviando a CloudWatch Logs, se midieron 16 días de uso. Hubo 19 ejecuciones de la función y 103 mensajes publicados. En total, menos de un centavo de dólar por mes.
Si tu trail todavía no envía a CloudWatch Logs, el número a mirar es el volumen de eventos de tu organización en GB por mes, porque define el costo de entrega e ingesta.
Lo que este sistema no hace
Para usarlo bien, también conviene tener claros sus límites:
- No previene. Te enterás unos minutos después. Para impedir acciones existen las SCP de AWS Organizations.
- No reemplaza el offboarding. La mejor alerta es la que nunca se dispara porque la access key ya no existe, y AWS recomienda credenciales temporales para las personas.
- No es un SIEM. Es una red de seguridad liviana para equipos que no tienen un SOC mirando CloudTrail.
Para cerrar
Filtrar por quién actúa parece suficiente, hasta que el actor es justamente el que no se parece a tus usuarios habituales. Filtrar también por qué se destruye cierra esa brecha, y con servicios nativos el costo de tenerlo funcionando es marginal.
Si te quedaste con ganas de armarlo, en la versión técnica en AWS Builder Center vas a encontrar el código esencial de la función, los comandos para conectar cada pieza, el diseño de los dos filtros, los límites a tener en cuenta y cómo resolver los problemas más comunes.
¿Y vos? Si mañana alguien usa una access key que nadie revocó, ¿por dónde te enterarías?
Fuentes
- CloudTrail userIdentity element
- About logging in AWS Control Tower
- Sending CloudTrail events to CloudWatch Logs
- PutSubscriptionFilter
- Security Hub CSPM controls for CloudWatch
- How Lambda handles errors and retries with asynchronous invocation
- Custom notifications in Amazon Q Developer in chat applications
- Security best practices in IAM
- Logging DynamoDB operations by using CloudTrail
- Monitoring Amazon RDS API calls in CloudTrail
- AWS CloudTrail pricing
- AWS Lambda pricing
Seguime en más plataformas
Este tema también está en video corto (YouTube Shorts, TikTok, Instagram Reels), como carrusel en LinkedIn, en un artículo en Medium y en la versión técnica en AWS Builder Center.
- Medium: medium.com/@lucianonicolasloyola
- YouTube: youtube.com/@dev.luchops
- TikTok: tiktok.com/@dev.luchops
- Instagram: instagram.com/dev.luchops
- LinkedIn: Luciano Nicolás Loyola
━━━━━━━━━━━━━━━━━━━━ 🟧 dev.luchops Cloud & DevOps, explicado sin vueltas. ━━━━━━━━━━━━━━━━━━━━ 



