Zaroz
Guía de la API de Units

Principales de servicio

Un principal de servicio es la identidad propia de un Workload. Existe para que el código de un hub pueda crear servidores de duelo sin que nadie pegue una clave personal en una variable de entorno.

  • Como máximo un principal por Workload, creado por una persona con acceso de gestión.
  • Tiene permisos: un Workload destino del mismo proyecto (el propio incluido) y una capacidad por cada uno:
    • units.read lee unidades y el flujo de eventos.
    • units.control además crea, inicia, detiene, destruye y asigna, e incluye leer.
  • Nunca puede cambiar la política de escalado, los webhooks ni sus propios permisos.

Crearlo y darle acceso

curl

TerminalCode
P="$ZAROZ_API/projects/$PROJECT/service-instances/$SERVICE/principal" curl -sS -X PUT "$P" -H "$AUTH" # 201 created / 200 already there curl -sS -X PUT "$P/grants" -H "$AUTH" -H "Content-Type: application/json" -d '{ "grants": [ {"target_service_instance_id": "<duels service uuid>", "capability": "units.control"}, {"target_service_instance_id": "<lobbies service uuid>", "capability": "units.read"} ] }'

TypeScript

TypeScriptCode
const P = `/projects/${PROJECT}/service-instances/${SERVICE}/principal`; await call("PUT", P); // 201 created / 200 already there await call("PUT", `${P}/grants`, { grants: [ { target_service_instance_id: DUELS, capability: "units.control" }, { target_service_instance_id: LOBBIES, capability: "units.read" }, ], });

Python

Code
P = f"/projects/{PROJECT}/service-instances/{SERVICE}/principal" call("PUT", P) # 201 created / 200 already there call("PUT", f"{P}/grants", {"grants": [ {"target_service_instance_id": DUELS, "capability": "units.control"}, {"target_service_instance_id": LOBBIES, "capability": "units.read"}, ]})

PUT .../principal es idempotente y un principal nuevo no tiene ningún permiso. PUT .../principal/grants reemplaza la lista entera (máximo 64; una lista vacía los quita todos). Debes poder gestionar cada Workload que nombres: si no, grant_target_unavailable y no cambia nada. Un permiso surte efecto en la siguiente petición del programa.

Activar un principal cambia la plantilla de pods del Workload, así que se aplica a medida que las unidades se reinician, según la regla de despliegue del Workload.

Código dentro de una unidad

Cada unidad de un Workload con principal recibe dos cosas: ZAROZ_API_URL en su entorno y un archivo de token en /zaroz/credentials/token. El token dura 60 minutos y la plataforma lo reemplaza antes de que caduque, así que lee el archivo en cada petición (o al recibir un 401) y nunca lo guardes en caché.

curl

TerminalCode
# inside a unit of a service that has a principal curl -sS "$ZAROZ_API_URL/projects/$ZAROZ_PROJECT_ID/service-instances/$TARGET/units?label=mode:2v2" \ -H "Authorization: Bearer $(cat /zaroz/credentials/token)"

TypeScript

TypeScriptCode
import { readFileSync } from "node:fs"; // The mounted token is rotated by the platform: read it per request, never cache it. const token = () => readFileSync("/zaroz/credentials/token", "utf8").trim(); const res = await fetch( `${process.env.ZAROZ_API_URL}/projects/${process.env.ZAROZ_PROJECT_ID}/service-instances/${TARGET}/units?label=mode:2v2`, { headers: { Authorization: `Bearer ${token()}` } }, );

Python

Code
import os def token() -> str: # rotated by the platform: read it per request, never cache it with open("/zaroz/credentials/token") as f: return f.read().strip() r = requests.get( f"{os.environ['ZAROZ_API_URL']}/projects/{os.environ['ZAROZ_PROJECT_ID']}/service-instances/{TARGET}/units", params={"label": "mode:2v2"}, headers={"Authorization": "Bearer " + token()}, timeout=10, )

Un programa fuera de Zaroz

Un matchmaker en tu propio servidor, o un trabajo de CI, crea una credencial externa para el principal. Actúa con los permisos del principal, tiene nombre y caducidad (de 1 a 365 días, 90 por defecto), es revocable y registra last_used_at.

curl

TerminalCode
curl -sS -X POST "$P/credentials" -H "$AUTH" -H "Content-Type: application/json" \ -d '{"name": "matchmaker-eu", "expires_in_days": 90}' # {"credential": {...}, "token": "zaroz_sp_..."} the token is shown this once

TypeScript

TypeScriptCode
const cred = await call("POST", `${P}/credentials`, { name: "matchmaker-eu", expires_in_days: 90 }); console.log(cred.body.token); // zaroz_sp_...: store it in your secret manager now

Python

Code
status, cred = call("POST", f"{P}/credentials", {"name": "matchmaker-eu", "expires_in_days": 90}) print(cred["token"]) # zaroz_sp_...: store it in your secret manager now

Envía el token como Authorization: Bearer zaroz_sp_.... Lista las credenciales con GET .../principal/credentials y revoca una con DELETE .../principal/credentials/{credential_id}.

Límites y auditoría

Un principal está limitado a 50 peticiones por segundo. Cada llamada suya se audita con el id del principal y el tipo de token. Desactivar el principal (DELETE .../principal) revoca todos sus tokens. Eliminar el Workload que lo posee también lo revoca, y eliminar un Workload destino borra los permisos que lo nombran.

Last modified on