From 8741169259702aa1dc5afd88c3894a6b0a7189b3 Mon Sep 17 00:00:00 2001 From: SIAX Agent Date: Sat, 7 Nov 2026 18:14:23 +0100 Subject: [PATCH] =?UTF-8?q?docs(identity):=200pt=20workload=20identity=20?= =?UTF-8?q?=E2=80=94=20m=C3=A5lbild,=20integrationsdesign=20och=20blockera?= =?UTF-8?q?re?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nuläge (delad INTERNAL_TOKEN + serverkonfigurerad tenant-allowlist) mot CL0UD:s redan existerande service-account/workload-token-maskineri (aud:0pt, 10 min, capabilities). Design: verifiering före route-logik, tenant från claim, capability per route, dual-accept under övergång, negativa tester i samma svit. Provisionering är blockerad: /account/service-accounts kräver operator-session (307 -> /login) och Zitadel admin-PAT är invalid (AUTH-7fs1e). --- docs/runbook/workload-identity-0pt.md | 78 +++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 docs/runbook/workload-identity-0pt.md diff --git a/docs/runbook/workload-identity-0pt.md b/docs/runbook/workload-identity-0pt.md new file mode 100644 index 0000000..51026eb --- /dev/null +++ b/docs/runbook/workload-identity-0pt.md @@ -0,0 +1,78 @@ +# 0pt workload identity — målbild, nuläge och övergång + +Status: **design klar, provisionering blockerad** (2026-11-07). +Ägare: CL0UD (identitet) / 0pt (konsument). + +## 1. Nuläge + +0pt autentiserar maskin-till-maskin med en **delad hemlighet**: + +- `X-Internal-Token` mot `INTERNAL_TOKEN` (samma värde i engine och edge). +- Tenant-auktoritet kommer från serverkonfigurationen `INTERNAL_SERVICE_TENANTS` + (se `src/auth/internal-service-tenant.ts`), aldrig från en klientheader. +- Tom allowlist ⇒ ingen tenant-auktoritet ⇒ tenant-scopade skrivningar 403. + +Det här är säkert men grovkornigt: en enda hemlighet representerar hela +engine-processen, och varje ny konsument kräver en manuell allowlist-post. + +## 2. Målbild (CL0UD workload identity) + +CL0UD äger redan maskineriet: + +- `POST /account/service-accounts` skapar en service account (identitet). +- `POST /account/service-accounts/{id}/workload-token` mints en **kortlivad** + (10 min default, 1 h max) workload-token vars `capabilities` är en delmängd av + service accountens `platform.cl0ud_service_account_scopes.allowedCapabilities`. +- `@siax/platform-core` `auth/workload.ts` är verifieringsadaptern; publika + nycklar via JWKS. +- `packages/capability-registry/src/workload-identities.ts` deklarerar + arbetsbelastningsnamn och `aud:*`-audiences. Modulen är uttryckligen **inte** + provisionerad och **inte** inkopplad i utfärdande eller verifiering än. + +För 0pt innebär det: + +| Egenskap | Idag | Mål | +|---|---|---| +| Credential | delad `INTERNAL_TOKEN` | CL0UD-workload-token, `aud:0pt`, 10 min | +| Tenant | serverkonfigurerad allowlist | `tenant_id`-claim i verifierad token | +| Capabilities | route-lista i middleware | `capabilities`-claim (t.ex. `0pt.canonical.write`) | +| Rotation | manuell | automatisk (kortlivad token) | +| Spårbarhet | delad hemlighet | per-arbetsbelastning (`0pt-engine`, `site0-pipeline`) | + +## 3. Integrationsdesign (när provisionering är möjlig) + +1. **Verifiering före route-logik.** Middleware accepterar + `Authorization: Bearer ` för `INTERNAL_SERVICE_ROUTES` om + signaturen verifieras mot CL0UD JWKS, `aud` innehåller `0pt` och `exp` är + giltig. Ingen klientheader får bidra till tenant. +2. **Tenant från claim, inte från allowlist.** `tenant_id` i den verifierade + tokenen sätts som `x-0pt-verified-tenant`; `INTERNAL_SERVICE_TENANTS` + används endast för legacy `X-Internal-Token`. +3. **Capabilities per route.** Route-metadata (`0pt.canonical.write`, + `0pt.quality.run`) jämförs med tokenens `capabilities`. Saknad capability ⇒ + 403, inte 401 (identiteten är giltig, behörigheten räcker inte). +4. **Dual-accept under övergång.** Båda credentialtyperna accepteras tills + engine och site0-pipeline mintar workload-tokens; därefter tas + `X-Internal-Token` bort i en egen release med negativt test. +5. **Negativa tester i samma svit som idag** + (`tests/auth/internal-token-tenant-scope.test.ts`): fel `aud` ⇒ 401, utgången + token ⇒ 401, tenant utanför claim ⇒ 403, saknad capability ⇒ 403. + +## 4. Blockerare + +- `/account/service-accounts` svarar **307 → /login** utan operator-session; + ingen giltig `SIAX_TOKEN` finns i Infisical-miljön. +- Zitadel admin-PAT (`/opt/siax-access/zitadel-admin-pat`) är invalid + (AUTH-7fs1e), så nya machine users kan inte mintas via det flödet. +- `workload-identities.ts` är deklaration-only: ingen identitet är + `provisioned: true`. + +Åtgärd kräver en operatörsinloggning i CL0UD-konsolen (eller en ny giltig +admin-PAT) och är därför **EXTERNALLY_BLOCKED** från agentsidan. + +## 5. Vad som inte ska göras + +- Ingen egen JWT-signering i 0pt. +- Ingen parallell identitetsplattform. +- Ingen klientheader som bär tenant. +- Ingen långlivad delad hemlighet som "tillfällig" lösning utan slutdatum. -- 2.54.0