Identidad¶
Cómo sabe kubelatch quién eres, cómo se vincula tu cuenta con GitHub o con el proveedor de identidad de tu organización y qué pasa con tu acceso cuando te vas. También explica por qué existen las cuentas break-glass.
Sujetos: personas y bots¶
Todo lo que puede tener permisos en kubelatch es un sujeto. Hay dos clases:
- Personas. Entran en la interfaz web, piden credenciales para sí mismas y pueden ser administradoras.
- Bots. No tienen contraseña ni sesión: solo credenciales. Un admin emite las suyas desde «Credenciales», o la CI las obtiene canjeando su token OIDC de GitHub Actions (ver reglas de confianza).
Cada sujeto tiene un login inmutable que nunca se reutiliza, ni siquiera tras deshabilitar la cuenta. Por defecto es el nombre con el que lo ven los clusters: user:<login> para personas y bot:<nombre> para bots, más un identificador interno como uid. Si un login se reciclara, la auditoría nativa del cluster mezclaría a dos personas. Un cluster puede nombrar en su lugar a las personas como lo hace su propio SSO, por ejemplo oidc:ana@acme.com, con su plantilla de identidad (kubelatch encima del SSO que ya tienes); los bots siguen siendo bot:<nombre>.
No hay autorregistro. Un admin crea las cuentas desde «Usuarios» y comparte un enlace de invitación de un solo uso (<KUBELATCH_BASE_URL>/account-link#kli_…, válido 72 h). La otra vía es la CLI del servidor, kubelatch-server user create (ver CLI del servidor).
Cómo entran las personas: contraseñas, GitHub u OIDC¶
kubelatch deja entrar a las personas con contraseñas locales, con GitHub, con un proveedor de identidad OpenID Connect, o con GitHub y un proveedor a la vez, según qué variables GITHUB_* y OIDC_* estén puestas:
| Solo contraseñas | Con la GitHub App | Con un proveedor OIDC | |
|---|---|---|---|
| Cómo entran las personas | Login y contraseña locales | «Entrar con GitHub» | «Entrar con {name}», donde {name} es el nombre del proveedor |
| Contraseñas | Todas las cuentas | Solo las cuentas break-glass | Solo las cuentas break-glass |
| Doble factor | No | El que impone la organización de GitHub | El que impone el proveedor |
| Bajas | Manuales | Automáticas al salir de la organización | Manuales: el proveedor no da lista de miembros |
Sin login externo no hay doble factor ni bajas automáticas: ese modo sirve para probar kubelatch o para entornos sin proveedor de identidad (ver Modelo de seguridad). En producción, configura la GitHub App (Login con GitHub) o tu proveedor (Login con OIDC (SSO)). Con los dos activos, la página de login ofrece los dos y cada persona puede tener cualquiera de las dos identidades, o las dos.
Cambiar de modo no toca las cuentas: mismo login, mismos permisos, mismas credenciales. Con GitHub, vinculas cada cuenta con su cuenta de GitHub; con un proveedor OIDC, la mayoría de las cuentas se vinculan solas en su primer acceso.
Vincular una cuenta con GitHub¶
Vincular es asociar una cuenta de kubelatch con el id numérico de una cuenta de GitHub. kubelatch no usa el login de GitHub como identidad, porque GitHub permite renombrarlo y reciclarlo; lo guarda solo para mostrarlo y lo refresca cuando cambia. Una cuenta de GitHub solo puede estar vinculada a una cuenta de kubelatch.
Hay tres caminos, todos con el mismo resultado:
- El enlace de invitación de una cuenta nueva lleva a «Vincular con GitHub y entrar».
- El «Enlace de vinculación» que genera un admin desde la ficha de la cuenta en «Usuarios» (24 h) vincula una cuenta existente, o la cambia a otra cuenta de GitHub. Generarlo cierra al momento las sesiones de esa persona.
- Una persona que ya puede entrar usa «Mi cuenta» → «Identidades» → «Vincular con GitHub», solo si su cuenta aún no está vinculada.
Desvincular es cosa de un admin («Desvincular GitHub»), y cierra las sesiones de esa persona. No hay alta automática: una cuenta de GitHub que no está vinculada a nadie no entra, aunque sea miembro de la organización.
Qué comprueba el login con GitHub¶
sequenceDiagram
participant N as Navegador
participant K as kubelatch
participant G as GitHub
N->>K: «Entrar con GitHub»
K-->>N: Cookie de estado firmada + redirección
N->>G: Autoriza la GitHub App
G-->>N: Redirección al callback con code y state
N->>K: /api/auth/github/callback
K->>K: state == cookie
K->>G: Canjea el code (client secret)
K->>G: GET /user (id numérico)
K->>G: Pertenencia activa a la organización
K->>G: ¿La organización exige 2FA?
K->>K: Cuenta vinculada a ese id y habilitada
K-->>N: Sesión y redirección a «Inicio»
Cada paso puede fallar con un código que la página de login traduce (la lista está en Errores). Detalles que importan:
- Solo miembros activos de la organización configurada. Una invitación pendiente no vale.
- El
stateva en una cookie firmada válida 10 minutos. El código se canjea en el servidor con el client secret, y el token de GitHub de la persona se descarta tras el login. - El callback comparte el límite por IP del login con contraseña.
- El login con GitHub ignora a propósito el bloqueo por contraseñas fallidas. Si lo respetara, cualquiera podría bloquear a una persona que entra con GitHub probando contraseñas con su login.
Qué pide kubelatch a GitHub¶
| Para qué | Con qué token | Llamada |
|---|---|---|
| Identidad de quien entra | El de la persona, solo durante el login | GET /user |
| Pertenencia a la organización | El de la persona | GET /user/memberships/orgs/<org>, que debe responder state: active |
| Token de instalación de la App | Un JWT RS256 firmado con la clave privada de la App | GET /orgs/<org>/installation y POST /app/installations/<id>/access_tokens |
| Lista de miembros (sincronización) | El de instalación | GET /orgs/<org>/members |
| ¿La organización exige 2FA? | El de instalación | El campo two_factor_requirement_enabled de GET /orgs/<org>. GitHub solo lo devuelve a una App con Administration: read. |
La identidad OIDC¶
Con un proveedor OIDC, la identidad no es la dirección de correo: es el issuer del proveedor, el nombre del claim que identifica a la persona (sub, u oid en Entra ID) y el valor de ese claim. Una identidad abre una sola cuenta de kubelatch, y una cuenta tiene como mucho una identidad del proveedor. Los bots nunca la tienen.
La dirección de correo solo cuenta en el primer acceso de cada persona. Mientras su identidad no está vinculada, kubelatch busca la cuenta con el correo que garantiza el proveedor (verificado y de un dominio permitido) y la vincula, si la política de vinculación lo permite y hay exactamente una cuenta habilitada con esa dirección. A partir de ahí, el correo ya no interviene:
- Nunca sustituye una identidad del mismo proveedor. Si la cuenta con ese correo ya tiene otra identidad del proveedor, el acceso se rechaza (
identity_mismatch): es lo que protege a una cuenta cuya dirección de correo pasa a otra persona cuando su dueño se va. Decide un administrador: desvincula la identidad si es la misma persona, cuya cuenta en el proveedor se volvió a crear, o deshabilita la cuenta antigua y crea otra para la persona nueva. - Una identidad guardada con otro issuer, o con otro nombre de claim, es de otro proveedor. El siguiente acceso de la persona la sustituye por correo, según permita la política de vinculación, y el evento lo dice: así se resuelve solo un cambio de proveedor, o un
OIDC_SUBJECT_CLAIMcorregido. - Si más adelante el proveedor envía otro correo para la misma identidad, kubelatch actualiza el correo de la identidad y registra el cambio (
oidc.email_changed); el correo de la propia cuenta, el que puso un administrador, no cambia.
Cada vinculación por correo deja un evento oidc.link, revoca los enlaces de invitación y de vinculación pendientes de la cuenta y aparece durante una semana en los «Avisos» de los administradores. Las demás formas de vincular son las mismas que con GitHub: un enlace de invitación o un «Enlace de vinculación» llevan a «Vincular con {name} y entrar», y «Mi cuenta» ofrece «Vincular con {name}» en su tarjeta «Identidades» mientras la cuenta no tiene identidad del proveedor. Desvincular, con «Desvincular {name}», es cosa de un administrador y cierra las sesiones de la persona. Una dirección de correo sin cuenta solo entra por una regla que un administrador creó para su dominio, que crea la cuenta dentro de un grupo, o pidiendo unirse y siendo aprobada (Acceso por dominio y solicitudes de alta). Las políticas de vinculación y el detalle de cada proveedor están en Login con OIDC (SSO); qué comprueba cada acceso, en Modelo de seguridad.
Doble factor: lo impone la organización¶
kubelatch no tiene segundo factor propio. Se apoya en el que la organización de GitHub exige a todos sus miembros. Si la organización lo exige, toda persona que entra con GitHub lo ha pasado.
kubelatch solo puede comprobarlo si la App tiene el permiso Organization → Administration: read. Con él, y con GITHUB_REQUIRE_ORG_2FA en su valor por defecto true, rechaza los logins mientras la organización no lo exija. Sin ese permiso, GitHub no le dice nada: kubelatch deja entrar y avisa en cada sincronización. Si no puede preguntar por un fallo real (un 5xx, un timeout), rechaza el login.
En resumen: el 2FA lo garantiza la configuración de la organización, no kubelatch.
Con un proveedor OIDC, el doble factor es el que pida el proveedor: kubelatch no lo impone, pero guarda en cada evento de acceso los métodos de autenticación que declara el proveedor (amr y acr, cuando el token los trae).
Cuentas break-glass¶
Con el login con GitHub o con OIDC activo, ninguna contraseña abre sesión salvo las de las cuentas break-glass. Existen para cuando el login externo no está disponible: una caída de GitHub o del proveedor, la App desinstalada, un error de configuración como un dominio mal escrito.
- Solo se marcan desde la CLI del servidor (
kubelatch-server user create --break-glassokubelatch-server user set-break-glass), nunca desde la interfaz ni la API. - No tienen doble factor. Deben ser pocas, con contraseñas largas en un gestor de secretos, y usarse solo en emergencias.
- En la página de login, siguen «Entrar con contraseña», al pie de la página, hasta un paso propio.
- Una cuenta break-glass que se vincula con GitHub queda sujeta a las bajas automáticas como cualquier otra. Las que nunca se vinculan quedan fuera de la sincronización.
- Vincular una con el proveedor OIDC no le quita la contraseña: sigue entrando con ella cuando el proveedor está caído.
- Cada acceso así se envía por correo a los administradores y se muestra en su campanita durante 12 horas (Avisos).
kubelatch impide quitar el rol, deshabilitar, desvincular o desmarcar como break-glass al último administrador que puede entrar: con una contraseña que le sirva, con GitHub vinculado mientras el login con GitHub está activo, o con una identidad del proveedor configurado mientras el login con OIDC está activo. Al arrancar con GitHub u OIDC activo y sin ningún admin que pueda entrar, lo registra como error en el log.
Esto no sustituye al acceso nativo de emergencia a cada cluster, que no depende de kubelatch (ver Cuentas y recuperación).
Bajas automáticas¶
Con la GitHub App configurada, quien sale de la organización se deshabilita solo, por dos vías:
- Sincronización cada hora. Una vez por hora (la primera, un minuto después de arrancar), una réplica lista los miembros de la organización con un token de instalación de la App y deshabilita las cuentas vinculadas cuyo id ya no aparece. Refresca también los logins de GitHub renombrados.
- Webhook
member_removed. ConGITHUB_WEBHOOK_SECRET, GitHub avisa en el momento y la baja es inmediata. La firma HMAC es la autenticación.
La sincronización es conservadora a propósito. Nunca deshabilita ante un error: un 5xx, un timeout, una página que falla, la App desinstalada o una lista con cero miembros abortan la pasada sin tocar a nadie. Y nunca rehabilita: si alguien vuelve a la organización, un admin lo rehabilita a mano.
Por eso la sincronización no corrige una baja indebida, como la que puede causar una entrega repetida del webhook, que no deduplica (ver Modelo de seguridad). Lo que sí corrige es un webhook perdido: da de baja a quien salió aunque la entrega no llegara.
Un proveedor OIDC no le da a kubelatch ninguna lista de miembros, así que, solo con OIDC, no hay bajas automáticas: deshabilitar a alguien en el proveedor impide su siguiente acceso, pero lo que ya tiene sigue funcionando hasta que caduque o un admin deshabilite la cuenta (ver Modelo de seguridad). Quien además tenga vinculada una cuenta de GitHub sigue quedando deshabilitado por la sincronización al salir de la organización.
Qué pasa al deshabilitar una cuenta¶
Da igual quién deshabilite (un admin con «Deshabilitar», la sincronización o el webhook), los efectos son los mismos y ocurren a la vez:
- Sesiones: todas se cierran. La siguiente petición con la cookie de esa persona se rechaza.
- Enlaces pendientes de invitación o vinculación: se revocan.
- Credenciales: todas las vigentes se revocan. La siguiente petición al proxy recibe
401, y losexecowatchabiertos se cortan en 10 s como máximo. - Agentes que actúan en su nombre: cada sesión delegada se corta. Sus tokens dejan de valer, sus solicitudes pendientes se cierran y el evento
user.disablecuenta las sesiones endetails.agent_sessions_revoked. - Clusters: la siguiente reconciliación saca a la persona de la lista de usuarios que el proxy puede suplantar, y sus bindings si nadie más los sostiene.
- Permisos: se conservan, pero no cuentan mientras la cuenta esté deshabilitada.
Rehabilitar devuelve el efecto de los permisos, pero no las credenciales ni las sesiones de los agentes: quedan revocadas, hay que emitir credenciales nuevas y volver a conectar cada agente. El TTL máximo de las credenciales (30 días para personas por defecto) acota lo que un olvido podría dejar abierto.
Sesiones¶
La sesión web es una cookie firmada que dura 12 h (cómo se protege está en el Modelo de seguridad). Cerrar sesión, cambiar la contraseña, usar un enlace de restablecimiento o de vinculación, desvincular GitHub o la identidad OIDC, deshabilitar la cuenta o el «Cerrar las sesiones web» de un admin invalidan todas las sesiones web de esa persona a la vez.
La sesión web no sirve para hablar con los clusters. Para eso hace falta una credencial, que es independiente de la sesión.