Qué te dice el audit log de Kubernetes
Cada solicitud al API server de Kubernetes — desde kubectl, controladores, kubelets o un token robado — puede registrarse como un evento de auditoría: quién (usuario, grupos, cuenta de servicio), desde dónde (IPs de origen, user agent), qué (verbo, recurso, namespace, nombre, subrecurso), si fue permitido y por qué (el binding de RBAC), y en niveles más altos el propio cuerpo de la solicitud.
Eso lo convierte en la evidencia principal para responder "¿nuestro clúster fue comprometido?": un token de cuenta de servicio robado, un pod privilegiado montando el nodo, un nuevo binding a cluster-admin o un CronJob de crypto-mining dejan todos huellas de llamadas a la API, incluso cuando los workloads ya no existen.
Qué detecta esta herramienta
- Ejecución: pods/exec y pods/attach (especialmente por cuentas de servicio), port-forward, acceso al kubelet a través de nodes/proxy.
- Acceso a credenciales: secrets listados en todos los namespaces, ráfagas de lecturas de secrets, tokens de cuenta de servicio generados con TokenRequest.
- Escalada de privilegios y escape de contenedor: contenedores privilegiados, hostPID/hostNetwork/hostIPC, montajes hostPath de / o de sockets del runtime, DaemonSets en kube-system.
- Abuso de RBAC: nuevos bindings a cluster-admin, roles con escalate/bind/impersonate o comodines, impersonation, acceso concedido a usuarios anónimos.
- Reconocimiento: ráfagas de kubectl auth can-i (SelfSubjectAccessReviews / RulesReviews), ráfagas de 403, tokens de cuenta de servicio usados con kubectl o curl o desde IPs públicas, user agents de herramientas de ataque conocidas.
- Impacto y persistencia: imágenes y comandos de crypto-miner, imágenes de registries inusuales, CronJobs, eventos de Kubernetes eliminados. Las alertas opcionales de Falco se correlacionan en la misma línea de tiempo.
- Las detecciones son datos: un archivo de reglas JSON revisado (condiciones al estilo Sigma) mapeado a la matriz MITRE ATT&CK para Containers, de modo que se pueden leer, auditar y reutilizar.
Cómo exportar audit logs de Kubernetes
El audit logging debe estar habilitado antes de un incidente para que sea útil. Exporta todo el período de interés (idealmente unos días antes del primer evento sospechoso) como JSON; gzip y ZIP están bien.
Self-managed (kubeadm, k3s, RKE2, on-prem)
- El API server escribe eventos de auditoría cuando se inicia con --audit-policy-file y --audit-log-path (por ejemplo /var/log/kubernetes/audit/audit.log).
- En cada nodo del control plane, copia el audit.log actual y sus archivos rotados (audit-*.log, posiblemente .gz).
- Si envías los eventos de auditoría con el backend de webhook (Fluent Bit, Vector, un SIEM), expórtalos desde ahí como líneas JSON.
- Suelta aquí los archivos o toda la carpeta.
Amazon EKS
- El logging del control plane debe incluir el tipo de log "audit" (consola de EKS → clúster → Observability → Control plane logging).
- Los eventos están en CloudWatch Logs, log group /aws/eks/<cluster>/cluster, streams kube-apiserver-audit-*.
- Rangos pequeños: aws logs filter-log-events --log-group-name /aws/eks/<cluster>/cluster --log-stream-name-prefix kube-apiserver-audit --start-time <ms> --end-time <ms> > eks-audit.json
- Rangos grandes: crea una export task a S3 (aws logs create-export-task), descarga los archivos .gz y suelta la carpeta. Los resultados de CloudWatch Logs Insights exportados como JSON también funcionan.
Google GKE
- Los audit logs de Admin Activity siempre están activos; los logs de Data Access (get/list, lecturas de secrets) deben habilitarse para la Kubernetes Engine API en IAM → Audit Logs.
- Exporta con gcloud: gcloud logging read 'resource.type="k8s_cluster" AND logName:"cloudaudit.googleapis.com"' --project=<project> --freshness=30d --format=json > gke-audit.json
- O descarga los resultados desde Logs Explorer como JSON, o usa un log sink a Cloud Storage / BigQuery para períodos largos (exporta las filas de BigQuery como JSON o JSON delimitado por saltos de línea).
- Suelta aquí los archivos JSON; las entradas de otros servicios se ignoran.
Azure AKS
- Crea una diagnostic setting en el clúster con la categoría kube-audit (o kube-audit-admin, que excluye get/list).
- Destino storage account: descarga los blobs PT1H.json bajo insights-logs-kube-audit/… y suelta la carpeta.
- Destino Log Analytics: consulta AKSAudit (o AzureDiagnostics | where Category startswith "kube-audit") y exporta los resultados como JSON, no como CSV.
- También se admiten exportaciones de Event Hubs ({"records": […]}).
Asegúrate de que exista la evidencia
- Registra al menos Metadata para todo, y Request o RequestResponse para objetos de RBAC, pods, workloads, pods/exec y serviceaccounts/token: sin los cuerpos de la solicitud no se pueden reconocer los pods privilegiados ni los bindings a cluster-admin.
- Nunca registres los cuerpos de secrets, configmaps o tokenreviews (solo Metadata): el log se convertiría en un almacén de credenciales.
- Mantén los audit logs fuera del clúster, durante al menos 90 días: los atacantes con cluster-admin pueden manipular cualquier cosa dentro de él.
Limitaciones
- El audit log solo ve el API server: la actividad dentro de un contenedor o en un nodo (una reverse shell, un miner iniciado a mano) es invisible sin herramientas de runtime como Falco.
- Lo que se detecta depende de tu política de auditoría: a nivel Metadata faltan los cuerpos de la solicitud (flags de privileged, imágenes, roleRef) y varias detecciones no pueden dispararse.
- Las reglas marcan patrones, no intenciones: los administradores legítimos también ejecutan kubectl exec, y los operators crean DaemonSets. Cada hallazgo necesita revisión humana.
- Solo se leen exportaciones JSON (las exportaciones CSV aún no son compatibles). Puede que sea necesario añadir los nombres de cuenta de servicio de tus propios componentes de plataforma a las listas de exclusión de las reglas.
Preguntas frecuentes
¿Mis audit logs se suben a algún sitio?
No. El analizador es Rust compilado a WebAssembly y se ejecuta en un Web Worker en tu navegador; los archivos se transmiten desde tu disco en fragmentos. No existe ningún endpoint de subida.
¿Qué tamaño de exportación puede manejar?
Los archivos se leen y descomprimen en streaming, así que el tamaño está limitado sobre todo por el tiempo: espera entre decenas y unos pocos cientos de MB por minuto según tu equipo. Las exportaciones pequeñas mantienen todos los eventos navegables; por encima de 50.000 eventos solo se conservan los eventos marcados, mientras que los recuentos, entidades y hallazgos siguen cubriendo todo.
¿Qué formatos son compatibles?
Líneas JSON crudas de audit.k8s.io/v1, exportaciones de EKS CloudWatch (filter-log-events, JSON de Logs Insights, archivos de exportación a S3), JSON de GKE Cloud Logging (gcloud logging read, descargas de Logs Explorer, sinks), logs de diagnóstico de AKS (storage account, Event Hubs, JSON de AKSAudit / AzureDiagnostics), gzip y ZIP, además de alertas JSON de Falco.
¿Cómo detecto kubectl exec en los audit logs?
kubectl exec genera una solicitud sobre el subrecurso pods/exec (verbo create o get, objectRef.subresource exec); el comando aparece en requestURI como parámetros command=. Esta herramienta lista cada exec, attach y port-forward, y eleva la severidad cuando lo hace una cuenta de servicio.
¿"Sin señales de compromiso" significa que estamos a salvo?
No. Significa que ninguna de las reglas coincidió en los logs que proporcionaste. Vacíos en la política de auditoría, rangos de tiempo faltantes y actividad dentro de los contenedores pueden ocultar una intrusión. Si tienes otros motivos de preocupación, solicita una revisión de un experto.
¿Puedo ver o reutilizar las reglas de detección?
Sí. Son un archivo JSON en el repositorio abierto (crates/k8s-audit-wasm/rules), con condiciones, umbrales, ids de técnica de MITRE ATT&CK y pasos de remediación, de modo que se pueden revisar y reutilizar en otras herramientas.