Sin servidor de autenticación: tokens verificables sin conexión, roles y ámbitos en Zaris
La mayoría de las formas de poner autenticación delante de un almacén de datos distribuido acaban por añadir un segundo sistema distribuido para hacerla funcionar: un servicio de autenticación al que llamar, una base de datos de sesiones que replicar, un endpoint de introspección de tokens que cada nodo tiene que alcanzar en la ruta caliente. Aseguraste el almacén y te compraste una nueva dependencia de disponibilidad y una nueva fuente de latencia.
Zaris toma una ruta distinta, y es una deliberadamente aburrida: una clave de firma por clúster, y tokens que cualquier nodo puede verificar por sí mismo. Un token es un JWT firmado con la clave privada del clúster; cada manager y cada nodo tiene la mitad pública y comprueba la firma sin conexión — sin llamada a un servidor de autenticación, sin quórum, sin consulta a una base de datos. La seguridad está desactivada por defecto, y un clúster con ella desactivada se comporta exactamente como uno no asegurado. Esta entrada trata de qué se activa cuando lo enciendes: la forma del token, el modelo de roles-y-ámbitos, los dos planos donde realmente ocurre la aplicación y — porque fingir lo contrario es cómo la gente adquiere una falsa sensación de seguridad — los bordes operativos que es fácil equivocar.
El token es toda la historia
Cada token de Zaris es un JWT. Nombra un sujeto — un usuario o una aplicación — y lleva una o más concesiones role @ scope. Está firmado por la clave privada RS256 del clúster, que vive solo en los managers; todo lo que necesita comprobar un token tiene solo la clave pública.
Esa única decisión de diseño es lo que elimina el servidor de autenticación del cuadro:
- Cualquier manager puede emitir un token. No hay nodo de autenticación primario, ni elección, ni estado de sesión mutable compartido que coordinar. Emitir es una operación de firma local.
- Cada manager y cada nodo puede verificar un token con solo la clave pública. La verificación es una comprobación de firma más una comprobación de expiración y de ámbito — CPU puro, sin red. El token es autocontenido: el rol y el ámbito están embebidos en él, así que un nodo que autoriza una conexión no necesita nada más que la clave pública. No hay base de datos de políticas en el nodo que mantener sincronizada.
La recompensa práctica aparece en la ruta de datos. Un cliente presenta su token una vez, cuando se establece la conexión — el "Hello". El nodo lo verifica, autoriza la conexión para el almacén y luego confía en esa conexión durante toda su vida. Los tokens nunca se vuelven a comprobar en la ruta caliente por operación, así que activar la seguridad no te cuesta nada por cada Get o Set. Pagas la autenticación en el momento de la conexión, una vez, y nunca más para esa conexión.
Roles y ámbitos
Los permisos son un pequeño catálogo preestablecido de roles, cada uno concedido en un ámbito que dice dónde se aplica.
| Rol | Nivel de ámbito | Qué concede |
|---|---|---|
ClusterAdmin | clúster | todo — todos los permisos del plano de control y del plano de datos |
StoreOperator | almacén | iniciar/detener el almacén, editar config, iniciar/detener nodos, diagnósticos, métricas |
Observer | almacén | diagnósticos y métricas, solo lectura |
DataWriter | almacén | lectura / escritura / borrado / escaneo de datos |
DataReader | almacén | lectura / escaneo de datos |
Un ámbito es jerárquico, y un ámbito más amplio cubre todo lo que hay por debajo de él:
zaris:cluster— todo el clúster, para la administración a nivel de clúster.zaris:store:<name>— un único almacén, p. ej.zaris:store:orders.- root (el ámbito vacío) — cubre todo; reservado para el administrador de arranque (bootstrap).
La contención es root ⊃ cluster ⊃ store, de modo que un DataWriter concedido en zaris:cluster puede escribir en todos los almacenes, mientras que uno concedido en zaris:store:orders solo puede escribir allí. Compones el mínimo privilegio a partir de estos dos ejes: elige el rol más pequeño que haga el trabajo, y fíjalo al ámbito más estrecho que la identidad necesite.
Activarlo sin dejarte fuera
Lo único que un sistema de seguridad jamás debe hacer es dejarte varado fuera de tu propio clúster. Zaris lo maneja haciendo de inicializar y activar un único paso: la aplicación solo entra en vigor una vez que existe el primer administrador.
Connect-ZrManager -Managers mgr-01:7801, mgr-02:7801, mgr-03:7801
Initialize-ZrSecurity -AdminSubject admin -AdminPassword (Read-Host -AsSecureString)
# creates the 'admin' login, generates the shared RS256 key on the first manager,
# copies the SAME key to the rest, turns enforcement on, and signs this session in.
El administrador es una identidad de inicio de sesión real — un nombre de usuario y una contraseña, como una cuenta root en la nube — no un token flotante que tengas que custodiar para siempre. Después de esto, los operadores inician sesión con credenciales y obtienen un token de sesión de corta duración. La propia aplicación es un conmutador en tiempo de ejecución, persistido por manager, que se activa sin reinicio ni edición de config:
Enable-ZrSecurity # control-plane enforcement ON (requires an initialized admin)
Disable-ZrSecurity # OFF — keeps the key and policy, so you can re-enable instantly
Ambos se distribuyen a cada manager del workspace, de modo que el clúster se mantiene consistente.
Dos tipos de identidad: personas y aplicaciones
Siguiendo el mismo patrón que AWS IAM, Kubernetes y Vault, cada token pertenece a una identidad registrada — no puedes acuñar un token para un nombre arbitrario. Hay exactamente dos tipos, más el único administrador de arranque.
Los usuarios son personas. Se crean con una contraseña (almacenada solo como un hash PBKDF2 con sal en users.json en cada manager — nunca en texto plano, sin base de datos externa) e inician sesión para obtener un token de sesión:
New-ZrUser -Name alice -Password (Read-Host -AsSecureString) `
-Role StoreOperator -Scope zaris:store:orders
Las cuentas de servicio son aplicaciones. Sin contraseña; crear una te entrega un token autocontenido que la aplicación presenta y renueva:
New-ZrServiceAccount -Name orders-svc -Role DataWriter `
-Scope zaris:store:orders -LifetimeMinutes 1440
# prints the application token once — store it in the app's secret manager.
New-ZrToken -Subject <name> sigue existiendo para emitir o rotar un token, pero el sujeto ya debe ser un usuario o cuenta de servicio registrado. No hay tokens ad hoc para nombres que no existen — esa es la propiedad que hace de "¿quién puede tocar este almacén?" una pregunta con respuesta.
Usar un token
En el plano de datos, el token se integra directamente en la cadena de conexión — y nunca tienes que incrustar un secreto literal en ella, porque la indirección env: y file: es de primera clase:
Connect-ZrStore -ConnectionString "zaris://node-a:7861,node-b:7861/orders?token=env:ZARIS_TOKEN"
Set-ZrItem -Key customer:42 -Value '{"name":"Ada"}'
Desde .NET es la misma cadena, o un TokenProvider en código cuando quieres rotación:
var services = new ServiceCollection()
.AddClustronZarisConnectionString("orders",
"zaris://node-a:7861,node-b:7861/orders?token=env:ZARIS_TOKEN")
.BuildServiceProvider();
var client = await services
.GetRequiredService<IZarisClientProvider>()
.GetAsync("orders"); // token presented once, at the connection Hello
Si el token falta, está expirado, es inválido o no tiene ámbito para este almacén, la conexión se rechaza con un estado Unauthorized — te enteras al conectar, no tres operaciones después dentro de una transacción. Si prefieres no acuñar y pegar un token a mano, Connect-ZrStore también puede intercambiar una credencial de usuario/contraseña por uno contra el Management Service y renovarlo en segundo plano.
Renovación que nunca corta una conexión
Aquí es donde "verificado solo al conectar" rinde el doble. Como un nodo comprueba el token solo cuando se abre la conexión, una conexión en vuelo nunca se interrumpe cuando su token expira. La renovación solo tiene que asegurarse de que el cliente tenga un token actualmente válido la próxima vez que abra una conexión — en una reconexión, un nodo nuevo, un reinicio de nodo.
Así que el cliente lee su token a través de un provider en cada (re)conexión. Mantén ese provider devolviendo tokens frescos y la renovación es completamente transparente:
var renewer = new ZarisRenewingTokenProvider(initialToken, "http://mgr-01:7801");
renewer.Start(); // renews itself at 80% of lifetime, before expiry
var options = new ZarisClientOptions {
StoreName = "orders",
Mode = ZarisClientMode.Remote,
TokenProvider = renewer.Token, // read on every (re)connect
};
El endpoint de renovación (POST /security/token/renew) es sin estado — verifica tu token actual sin conexión contra la clave compartida y devuelve uno nuevo con el mismo sujeto y roles y una expiración fresca, de modo que cualquier manager puede servirlo y sobrevive a reinicios. Un token expirado no se puede renovar (renueva antes de la expiración — el provider integrado lo hace), y un token o sujeto revocado se rechaza. La orientación que se desprende de esto es simple: prefiere vidas cortas con renovación automática a un solo token de larga duración. Obtienes la misma fluidez con mucha menos exposición.
Si no quieres código de cliente en el bucle en absoluto, apunta el provider a una variable de entorno o a un archivo y deja que un rotador externo — un gestor de secretos, un sidecar, un cron que reacuña — lo actualice fuera de banda:
options.TokenProvider = ZarisTokenProviders.FromEnvironment("ZARIS_TOKEN");
// or ZarisTokenProviders.FromFile("/etc/zaris/token");
La parte honesta: dos planos significan dos conmutadores
Este es el detalle que muerde a la gente, así que tiene su propia sección. "La seguridad está activada" no es un hecho — son dos, porque hay dos puntos de aplicación.
El plano de control — el Management Service en el puerto 7801, donde creas almacenes, inicias y detienes nodos y gestionas concesiones — aplica en cuanto has inicializado y activado la seguridad. Ese es el conmutador que acciona Enable-ZrSecurity.
El plano de datos — los nodos de Zaris reales que sirven tus claves — es un conmutador separado. Un nodo solo aplica tokens una vez que tiene la clave pública compartida en su configuración, y eso lo aprovisionas por almacén:
Enable-ZrStoreSecurity -Store orders # write the public key into every node's config
Enable-ZrStoreSecurity -Store orders -Restart # ...and rolling-restart to activate now
Hasta que hagas esto, los nodos del almacén ejecutan un autenticador AllowAll y aceptan cada conexión — con token o sin él. Esto es intencional: te permite activar primero el plano de control y desplegar la aplicación en el plano de datos almacén por almacén, con un reinicio planificado, en lugar de accionar todo el clúster de una vez. Pero significa que activar el plano de control no asegura, por sí mismo, tus datos. Las dos trampas correspondientes:
Get-ZrSecurityStatusinforma del plano de control. Sus camposEnabled/Initialized/Issuerdescriben la aplicación del plano de gestión. UnTrueahí no demuestra que los nodos de un almacén dado estén verificando tokens — ese es el trabajo deEnable-ZrStoreSecurity, confirmado por separado. Si un almacén "asegurado" sigue aceptando clientes sin token, la config del nodo carece de la clave o no se reinició.- La revocación no es instantánea en la ruta de datos. Como los tokens de datos son autocontenidos y se comprueban solo al conectar,
Revoke-ZrTokenes honrado de inmediato por el plano de control y por la renovación (un sujeto revocado no puede refrescar), pero una conexión de datos ya abierta sigue funcionando hasta que se cierra. La forma limpia de cortar a una aplicación en el plano de datos es emitir tokens de datos con un-LifetimeMinutesmodesto y dejar que el actual expire, o reiniciar sus conexiones tras revocar. Si necesitas un corte casi instantáneo, las vidas cortas son la palanca — no una expectativa de que la ruta caliente vuelva a comprobar.
Ninguna de estas es un error; son las consecuencias directas de "verificar sin conexión, una vez, sin servidor de autenticación". Son simplemente la parte que tienes que operar deliberadamente. El despliegue recomendado se desprende directamente de ellas: inicializa y activa el plano de control, verifica con Get-ZrSecurityStatus, emite tokens de operador y de aplicación y confirma que funcionan, luego Enable-ZrStoreSecurity por almacén con un reinicio planificado, y finalmente mueve las aplicaciones a tokens de corta duración con renovación automática.
Dónde se sitúa en la pila
La autenticación por tokens responde a quién puede tocar este almacén y qué puede hacer. Se compone con las otras dos mitades de un Zaris blindado y no reemplaza a ninguna:
- Confianza TLS enchufable cifra el cable y autentica los extremos — es el transporte
zariss://bajo el token, ortogonal a quién sostiene el token. - El tutorial seguro de Helm reúne ambos en Kubernetes de principio a fin, que es donde los detalles de la cadena de conexión y del certificado realmente se ejercitan.
Lo que vale la pena retener es la forma de la idea central. Una clave RS256, JWT que embeben su propia autoridad, verificación que es CPU puro sin conexión, y un token comprobado exactamente una vez por conexión. Eso es lo que te compra autenticación y autorización con rol y ámbito a través de un clúster entero sin levantar un servidor de autenticación, un almacén de sesiones ni un solo salto de red extra en la ruta que tu aplicación realmente ejecuta. El coste es la disciplina a la que esta entrada dedicó su segunda mitad: recuerda que el plano de datos es su propio conmutador, y mantén tus tokens de corta duración. Haz eso, y "asegurado" se convierte en una propiedad que puedes afirmar con precisión en lugar de esperar que lo esté.