Roles¶
Un permiso concede un rol en un cluster, sobre un namespace o sobre todo el cluster. Un rol es uno de los seis roles de sistema, los niveles que trae kubelatch (Roles de sistema), o un rol personalizado que compone un administrador en «Roles». Esta página explica qué puede llevar un rol personalizado, qué rechaza kubelatch siempre y por qué. Cómo crearlo, editarlo y concederlo está en Gestionar roles.
Aquí «rol» es lo que concede un permiso. No tiene nada que ver con el rol de administrador, que deja a una persona gestionar kubelatch (Usuarios y bots).
Roles de sistema y roles personalizados¶
| Rol de sistema | Rol personalizado | |
|---|---|---|
| Lo define | kubelatch: viewer, developer, debugger, secrets-reader, admin, cluster-admin |
Un administrador, en «Roles» |
| Se puede cambiar | No. Todos menos admin y cluster-admin se pueden duplicar en un rol personalizado |
Sí, en vivo: cada permiso que lo usa cambia al guardar |
| Dónde se concede | Fijo para cada nivel (Ámbitos permitidos) | Cualquier namespace; todo el cluster solo si el rol lo dice; todos los clusters o solo algunos |
| Caducidad | cluster-admin: 8 h como máximo |
Sin límite |
| Clusters | Cualquier cluster registrado | Los que tienen el bootstrap actual (más abajo) |
Un rol personalizado es global a la instancia de kubelatch. Su «Identificador» (de 2 a 39 minúsculas, dígitos o guiones, empezando por una letra) queda fijo al crearlo y no se vuelve a usar nunca, ni siquiera después de eliminar el rol, para que los permisos pasados y el registro de auditoría señalen siempre a un solo rol. No puede ser el nombre de un rol de sistema.
Un rol personalizado se compone de dos cosas: capacidades, conjuntos de reglas ya preparados, y reglas avanzadas para lo que ninguna capacidad cubre. Lo que concede es la unión de ambas.
Capacidades¶
Una capacidad es un conjunto de reglas con nombre, del catálogo de kubelatch. Leer es get, list y watch; escribir es create, update, patch y delete. El constructor las agrupa por dominio:
| Dominio | Capacidad | Qué permite | Marcas | Todo el cluster |
|---|---|---|---|---|
| Cargas de trabajo | «Leer cargas de trabajo» (workloads.read) |
Leer Deployments, StatefulSets, DaemonSets, ReplicaSets, Jobs, CronJobs, Pods y HorizontalPodAutoscalers. | Admitida | |
| Cargas de trabajo | «Desplegar cargas de trabajo» (workloads.deploy) |
Escribir Deployments, StatefulSets, DaemonSets, ReplicaSets, Jobs, CronJobs y Pods. | Sensible, exige PSA | No |
| Cargas de trabajo | «Escalar» (workloads.scale) |
get, update y patch sobre el subrecurso scale de Deployments, StatefulSets y ReplicaSets. |
No | |
| Cargas de trabajo | «Eliminar Pods» (pods.delete) |
delete sobre Pods, para que su controlador los arranque de nuevo. |
No | |
| Depuración | «Leer logs» (pods.logs) |
get y list sobre Pods y pods/log. |
Admitida | |
| Depuración | «Exec y attach» (pods.exec) |
get y create sobre pods/exec y pods/attach; get y list sobre Pods. |
Sensible | No |
| Depuración | «Port-forward» (pods.portforward) |
get y create sobre pods/portforward; get y list sobre Pods. |
Sensible | No |
| Depuración | «Contenedores efímeros» (pods.ephemeral) |
patch sobre pods/ephemeralcontainers; get y list sobre Pods. |
Sensible, exige PSA | No |
| Configuración y Secrets | «Leer ConfigMaps» (config.read) |
Leer ConfigMaps. | Admitida | |
| Configuración y Secrets | «Escribir ConfigMaps» (config.write) |
Escribir ConfigMaps. | No | |
| Configuración y Secrets | «Leer Secrets» (secrets.read) |
Leer Secrets, incluidos los tokens de ServiceAccount. | Sensible | No |
| Configuración y Secrets | «Escribir Secrets» (secrets.write) |
Escribir Secrets. | Sensible | No |
| Red | «Leer la red» (network.read) |
Leer Services, Endpoints, EndpointSlices, Ingresses y NetworkPolicies. | Admitida | |
| Red | «Escribir Services e Ingresses» (network.write) |
Escribir Services e Ingresses. | No | |
| Almacenamiento | «Leer reclamaciones de volumen» (storage.read) |
Leer PersistentVolumeClaims. | Admitida | |
| Almacenamiento | «Escribir reclamaciones de volumen» (storage.write) |
Escribir PersistentVolumeClaims. | No | |
| Eventos y autoescalado | «Leer eventos» (events.read) |
Leer Events, de la API del núcleo y de events.k8s.io. |
Admitida | |
| Eventos y autoescalado | «Escribir autoescaladores» (autoscaling.write) |
Escribir HorizontalPodAutoscalers. | No | |
| De todo el cluster | «Leer nodos» (nodes.read) |
Leer Nodes. | Necesaria | |
| De todo el cluster | «Leer namespaces» (namespaces.read) |
Leer Namespaces. | Necesaria | |
| De todo el cluster | «Leer volúmenes» (volumes.read) |
Leer PersistentVolumes y StorageClasses. | Necesaria | |
| De todo el cluster | «Leer CRDs» (crds.read) |
Leer CustomResourceDefinitions. | Necesaria |
«Todo el cluster» dice si la capacidad cabe en un rol que se puede conceder a todo el cluster: «Admitida», «No» (escribe, o lee Secrets o un subrecurso que actúa) o «Necesaria» (lee recursos que solo existen a nivel de cluster). Ver Roles que se conceden a todo el cluster.
exec, attach y port-forward llevan get además de create porque kubectl 1.31 y posteriores intenta WebSocket (un GET) antes que SPDY (un POST).
No hay capacidades para recursos personalizados: se añaden como reglas avanzadas.
Los roles de sistema en capacidades¶
Cuatro roles de sistema tienen una equivalencia en capacidades, que «Roles» muestra y «Duplicar» copia:
| Rol de sistema | Capacidades |
|---|---|
viewer |
Leer cargas de trabajo, Leer logs, Leer ConfigMaps, Leer la red, Leer reclamaciones de volumen, Leer eventos, Leer nodos, Leer namespaces, Leer volúmenes, Leer CRDs; se puede conceder a todo el cluster |
developer |
Todo lo de viewer salvo las cuatro de todo el cluster, más Desplegar cargas de trabajo, Escalar, Escribir ConfigMaps, Escribir Services e Ingresses, Escribir reclamaciones de volumen, Escribir autoescaladores |
debugger |
Leer logs, Exec y attach, Port-forward, Contenedores efímeros |
secrets-reader |
Leer Secrets |
En viewer y developer es una aproximación: en cada cluster agregan además el rol view de Kubernetes y cualquier ClusterRole etiquetado para ellos (Cómo se materializa), y una copia no hereda ninguna de las dos cosas. admin y cluster-admin enlazan los roles propios de Kubernetes: no tienen capacidades que mostrar y no se pueden duplicar.
Reglas avanzadas¶
Una regla avanzada es una regla de RBAC de Kubernetes escrita a mano, para lo que ninguna capacidad cubre: un recurso personalizado, o un objeto por su nombre. Cada regla tiene:
| Campo | Qué lleva |
|---|---|
| «Grupo de la API» | El grupo, por ejemplo argoproj.io. Vacío para el grupo del núcleo (Pods, ConfigMaps…), que el constructor ofrece como «Grupo core». |
| «Recursos» | Los recursos, en plural y minúsculas (applications), con el subrecurso tras una barra cuando hace falta (deployments/scale). |
| «Verbos» | Entre get, list, watch, create, update, patch, delete y deletecollection. |
| «Nombres (opcional)» | Los nombres de objeto a los que se limita la regla (resourceNames en Kubernetes). |
En el constructor, los recursos y los nombres son chips (escribe uno y pulsa Intro), los verbos son ocho chips con los atajos «Lectura» y «Escritura», y el grupo se escribe o se elige. Un rol admite hasta 50 reglas avanzadas, cada una con hasta 20 nombres.
«Sugerir desde el cluster», en el constructor, lee los grupos, recursos, subrecursos y verbos de un cluster listo de su API de discovery y los ofrece en los campos de una regla. Los nombres de objeto se escriben siempre a mano: listar los objetos de un cluster exigiría dar al reconciliador lectura de todo.
Lo que los nombres no pueden limitar¶
Kubernetes solo restringe por nombre get, update, patch y delete. No puede restringir list, watch, create ni deletecollection: un list con un nombre en la regla listaría igualmente todos los objetos, y un create no puede conocer el nombre antes de que exista el objeto. kubelatch rechaza una regla con nombres y alguno de esos cuatro verbos.
La consecuencia: una regla limitada al ConfigMap app-config deja a su titular leer y cambiar ese ConfigMap con kubectl get configmap app-config, pero no listar ConfigMaps, así que kubectl get configmaps falla.
Lo que se rechaza siempre¶
En las capacidades y en las reglas avanzadas por igual, kubelatch rechaza:
| Se rechaza | Por qué |
|---|---|
Los verbos impersonate, escalate y bind |
Saltan por encima de RBAC: actuar como otro, o conceder más de lo que se tiene. |
Cualquier verbo fuera de los ocho de arriba (approve, sign, use…) |
Cada uno es un poder especial que ningún rol personalizado debe llevar. |
El comodín * en un grupo, un recurso o un verbo |
Cubre lo que el cluster gane más adelante, y nadie lo puede revisar. |
Cualquier escritura en los grupos rbac.authorization.k8s.io y admissionregistration.k8s.io |
Escribir RBAC concede cualquier cosa; escribir la configuración de admisión apaga los controles, Pod Security entre ellos. |
serviceaccounts/token, nodes/proxy, certificatesigningrequests/approval, certificatesigningrequests/status y signers, con cualquier verbo |
Atajos a la identidad de otro o al kubelet. |
Cualquier escritura sobre namespaces y sus subrecursos |
Un RoleBinding en el namespace X permite a su titular modificar el propio objeto Namespace X. Quien le quitara la etiqueta de Pod Security podría crear un pod privilegiado y llegar al nodo. El rol admin de Kubernetes tampoco lo permite. |
| Caracteres de control y de formato en el nombre, la descripción y los nombres de objeto | Hacen que un nombre se lea como otra cosa. El salto de línea cuenta: la descripción es de una sola línea. |
| Un rol sin capacidades ni reglas, o la misma capacidad dos veces | Un rol que no concede nada no significa nada. |
El constructor muestra cada problema junto a su campo (una capacidad, un campo de una regla, el nombre, los clusters), y en «Por corregir antes de guardar». La API rechaza el rol con el primero (Errores).
Roles que se conceden a todo el cluster¶
Todo rol personalizado se puede conceder en un namespace. Con «Namespaces y todo el cluster» en «Dónde se aplica» se puede conceder también con ámbito *, y entonces tiene que ser de solo lectura:
- solo los verbos
get,listywatch; - nunca
secrets; - ningún subrecurso salvo
status,scaleypods/log.
El motivo es que Kubernetes no tiene «todos los namespaces menos estos»: un binding de ámbito * alcanza también kube-system y kubelatch-system, donde vive el Secret con el token del reconciliador. Leer Secrets ahí expone ese token. Escribir ahí (el ConfigMap aws-auth de EKS, el de CoreDNS, un pod en kube-system) es una vía a cluster-admin que se salta el acceso de emergencia auditado. En muchos subrecursos un get ya actúa: exec, attach, portforward, proxy y ephemeralcontainers, pero también nodes/log o la consola de una máquina virtual de KubeVirt. No se pueden enumerar todos, así que la lista es cerrada por el lado de lo permitido. Para escribir en todo un cluster está cluster-admin, con sus 8 h.
Las capacidades de todo el cluster («Leer nodos», «Leer namespaces», «Leer volúmenes», «Leer CRDs») necesitan «Namespaces y todo el cluster». Concedidas en un namespace no conceden nada: un RoleBinding solo alcanza lo que vive en su namespace. Un rol que se puede conceder a todo el cluster es siempre «Sensible».
Limitado a algunos clusters¶
En «Clusters», dentro de «Dónde se aplica», un rol es para «Todos los clusters» o «Solo algunos…», hasta 100. Un cluster que aún no está registrado puede estar en la lista. Conceder el rol en cualquier otro cluster se rechaza, y una edición no puede quitar un cluster de la lista mientras el rol tenga permisos activos en él.
Riesgo y Pod Security¶
Los dos se derivan de lo que lleva el rol; nadie los fija a mano.
Un rol es «Sensible» cuando:
- se puede conceder a todo el cluster;
- tiene una capacidad sensible: Desplegar cargas de trabajo, Exec y attach, Port-forward, Contenedores efímeros, Leer Secrets o Escribir Secrets;
- o una regla avanzada toca
secrets, un subrecurso que actúa (exec,attach,portforward,proxy,ephemeralcontainers), escribeserviceaccounts, exige Pod Security (abajo) o nombra un grupo de la API ajeno a Kubernetes (cualquier grupo con un punto que no acabe en.k8s.io).
Las listas muestran un rol sensible en seminegrita, con la etiqueta «Sensible» en «Roles»; el constructor explica por qué en «Mira dos veces».
Un rol exige Pod Security cuando tiene Desplegar cargas de trabajo o Contenedores efímeros, o una regla avanzada que crea o modifica (create, update, patch) Pods, ReplicationControllers, Deployments, StatefulSets, DaemonSets, ReplicaSets, Jobs o CronJobs, o que toca pods/ephemeralcontainers. Concederlo en un namespace exige entonces la etiqueta pod-security.kubernetes.io/enforce con baseline o restricted, como para developer (Pod Security Admission).
Esa etiqueta se comprueba una vez, al conceder. Por eso una edición no puede hacer que un rol empiece a exigir Pod Security mientras esté concedido en namespaces: revoca esos permisos y vuelve a concederlos, y se comprueba cada namespace.
El namespace sigue siendo la frontera: un rol que despliega pods alcanza los Secrets y las ServiceAccounts del namespace montándolos, aunque no tenga «Leer Secrets» (El namespace es la frontera).
Lo que kubelatch no puede saber: los recursos personalizados¶
kubelatch no sabe qué hace un recurso personalizado. Un rol que permite crear un Workflow de Argo ejecuta código sin tocar un solo pod: los crea el controlador. Por eso cualquier regla sobre un grupo ajeno a Kubernetes marca el rol como «Sensible», pero kubelatch no puede saber si exige Pod Security. Concede los roles con reglas así solo en namespaces que aplican PSA, como harías con developer, y lee en la documentación del controlador qué permite cada recurso a quien lo crea.
Cotas¶
| Cota | Valor | Por qué |
|---|---|---|
| Roles personalizados por instancia | 200 | Cada rol en uso es trabajo en cada reconciliación. |
| Reglas avanzadas por rol | 50 | Un ClusterRole es un objeto de etcd, y un rol que no se puede leer de un vistazo es un rol que nadie revisa. |
| Nombres por regla avanzada | 20 | Lo mismo, y el resumen deja de ser legible. |
| Clusters en «Solo algunos…» | 100 | — |
| Nombre | 80 caracteres | — |
Son fijas en kubelatch, no se configuran.
En el cluster¶
Por cada rol personalizado con al menos un permiso activo en un cluster, el reconciliador escribe:
| Objeto | Nombre | Sujeto del binding |
|---|---|---|
| ClusterRole con las reglas del rol | kubelatch-role-<id> |
|
| RoleBinding, para ámbito namespace | kubelatch-role-<id> en ese namespace |
Grupo kubelatch:ns:<namespace>:role-<id> |
ClusterRoleBinding, para ámbito * |
kubelatch-role-<id>-cluster |
Grupo kubelatch:cluster:role-<id> |
El ClusterRole lleva las etiquetas kubelatch.io/kind=role y kubelatch.io/role=<id> y la anotación kubelatch.io/revision. No es agregado: a diferencia de viewer, un rol personalizado no recoge ClusterRoles etiquetados, así que un CRD se añade con una regla avanzada. La pestaña «YAML» del constructor muestra exactamente el ClusterRole que escribe kubelatch.
Guardar un rol reconcilia cada cluster donde tiene permisos activos: sus titulares reciben las reglas nuevas en segundos, con la misma credencial. Cuando el reconciliador deja de necesitar un rol en un cluster, borra su ClusterRole y sus bindings.
Si un rol deja de cumplir estas reglas (una versión posterior rechaza algo que lleva), kubelatch deja de aplicarlo: sus permisos no tienen efecto y el cluster pasa a «Error» con custom role <id> no longer passes validation and was not applied: edit or delete it.
El cluster necesita el bootstrap actual¶
Los roles personalizados necesitan en el cluster el manifiesto de bootstrap actual, que acota al reconciliador con una política de admisión en lugar de una lista fija de nombres (El reconciliador y su ServiceAccount), y Kubernetes 1.30 o posterior. Un cluster registrado con el manifiesto anterior sigue funcionando con los roles de sistema; su tarjeta en «Clusters» dice «Bootstrap v1: en este cluster no se pueden conceder roles personalizados.», y el formulario de conceder desactiva ahí los roles personalizados. Actualizar el bootstrap explica cómo pasarlo al actual.