Auditar tu propio RBAC en Kubernetes: los permisos que nadie concedió a propósito
El API server ya describe cada permiso del clúster; el trabajo es leerlo, resolver los roles agregados y decidir qué concesiones siguen teniendo sentido

El API server de Kubernetes ya contiene una descripción legible por máquina de cada permiso del clúster. Sabe quién puede hacer qué, sobre qué recurso y en qué namespace, y lo expone sin necesidad de instalar nada, como recoge la documentación de RBAC. La mayoría de los clústeres, aun así, tienen sujetos capaces de leer todos los secret de todos los namespace, y buena parte de esos permisos no los concedió nadie a propósito.
El motivo es estructural: los permisos se acumulan. Una sesión de depuración deja un ClusterRoleBinding temporal que nadie retira. Un service account por defecto recibe un rol porque una carga fallaba sin él. Un chart de Helm trae un rol más amplio de lo que la aplicación necesita, y se actualiza el chart en vez de revisarlo.
Por dónde empezar
Los puntos de entrada son los objetos de la API: ClusterRoleBinding, RoleBinding, ClusterRole y Role. Una primera pasada debería responder a cuatro preguntas. Qué sujetos están ligados a cluster-admin, el hallazgo de mayor valor porque concede todos los verbos sobre todos los recursos. Qué sujetos pueden leer secret a escala de clúster. Qué sujetos pueden crear o modificar cargas de trabajo. Y qué bindings apuntan a los grupos system:authenticated o system:unauthenticated: un binding al primero alcanza a cualquier identidad autenticada, incluido un token filtrado.
El permiso que se subestima
Poder crear un Pod es, en la práctica, poder obtener cualquier token de service account del namespace: basta montarlo, ejecutar código dentro y usar los permisos de ese service account. Si la carga corre con uno privilegiado, create pods es una vía de escalada, igual que crear un Deployment, un DaemonSet, un StatefulSet, un CronJob o un Job. Una revisión que trata create pods como riesgo bajo y get secrets como riesgo alto tiene el orden al revés.
Hay otra trampa: los ClusterRole agregados. Los roles view, edit y admin se ensamblan por etiquetas, y cualquier ClusterRole con la etiqueta de agregación entra automáticamente. El conjunto efectivo de edit no es fijo. Quien audite solo el rol nombrado en el binding se perderá los permisos agregados; hay que seguir las etiquetas hasta cada rol contribuyente.
En service accounts hay dos patrones que conviene marcar: uno ligado a un rol amplio y montado por muchas cargas, donde el radio de impacto de un compromiso es la unión de los permisos, y el default de un namespace con un rol no trivial, que es un permiso para todas las cargas que no especifican uno. Desde Kubernetes 1.24 los volúmenes de token son proyectados y caducan, y automountServiceAccountToken admite false.
La secuencia que se repite: inventariar bindings y sujetos, separar identidades humanas de service accounts, resolver permisos efectivos siguiendo las etiquetas, ordenar por potencial de escalada, comprobar fronteras de namespace, buscar wildcards y anotar propietario y justificación.
La corrección casi nunca es borrar. Quitar un binding del que depende una carga provoca una caída, y la caída acaba en una concesión más amplia que la original. Funciona mejor sustituir el permiso amplio por uno estrecho que cubra las llamadas observadas y retirar el amplio tras un ciclo completo. Para eso hacen falta los audit logs del API server, que registran verbo, recurso y sujeto.
Un límite que conviene tener presente: RBAC no es la única vía de acceso. Los webhooks de admisión, los API servers agregados, el acceso al nodo y el IAM del proveedor cloud conceden permisos que RBAC no describe. Lo que tiene a favor la auditoría es que es barata, determinista y produce una lista concreta de concesiones que ya no tienen motivo para existir.


