Hoppa till innehåll

Auktorisering – vem får göra vad, och hur du bevisar det

Control Center besvarar två auktoriseringsfrågor, och de är verkligen olika. ”Får den här personen anropa den här operationen?” handlar om människor, roller och repositorier. ”Får den här agenten orsaka den här effekten?” handlar om åtgärder, argument och skadeomfång – den frågan besvaras av Räcken.

Den här sidan handlar om den första frågan, plus den dokumentation båda lämnar efter sig.

Varje auktoriseringsbeslut på människosidan avgörs genom en enda funktion:

can(principal, permission, resource) → allow | deny + why

En behörighet är <domain>:<tier> – tickets:write, members:administer, repos:read. Katalogen är härledd, inte handskriven: den beräknas från själva operationsytan (operationens namnprefix ger domänen, den lägsta roll den redan upprätthåller ger nivån), så alla ~550 operationer har en behörighet utan att någon har skrivit en.

Den härledningen är egenskapen som är värd att skydda. Den innebär att en NY operation grindas som standard – felmoden hos en handannoterad modell är att någon glömmer, och det man glömmer är grinden. Ett spärrtest låser fast den resulterande uppsättningen domäner, så att lägga till en operation under ett nytt prefix blir ett namngivningsbeslut som en människa fattar i stället för en olyckshändelse.

De fyra nivåerna motsvarar exakt de inbyggda rollerna:

Nivå Lägsta roll Exempel
read gäst tickets:read
write medlem tickets:write
administer admin members:administer
own ägare workspace:own

Fem inbyggda roller – ägare, admin, medlem, visare, gäst – är förval över den katalogen. Ägarskap är en enda plats per arbetsyta och överlämnas uttryckligen med Överför ägarskap (en ägare som slutar går annars inte att ta bort: SCIM-avprovisionering vägrar varje arbetsytaägare – överför först).

Anpassade roller är subtraktiva. En anpassad roll anger ett basförval (admin, member, viewer eller guest – aldrig owner) och en uppsättning behörigheter som TAS BORT från den – ”admin, men kan inte hantera medlemmar”. Den kan aldrig ge mer än sin bas, vilket är det som gör dem säkra att införa i en befintlig installation: varje befintlig kontroll förblir en giltig övre gräns. Medlemmar har dem som custom:<id>, och en klient som är för gammal för att förstå det värdet faller tillbaka på gäst i stället för att gissa.

Under rollerna ligger behörigheter per repo (none / read / review / write): ett arbetsytemedlemskap ger aldrig tyst fler privilegier än forge-tjänsten. Varje yta som exponerar kod kontrollerar dem – även de som når kod på omvägar, som en terminal eller en redigerarsession som öppnats mot en ytas worktree.

Vissa operationer handlar inte om en arbetsyta alls: installationsövergripande inställningar, SSO-konfiguration, leverantörsuppgifter, modellhantering, säkerhetskopior av hela installationen. De deklarerar serverauktoritet och nekas för alla utom installationens operatör (den registrerade serverägaren). Det finns medvetet en enda operatörsidentitet och en enda definition av den.

Varje auktoriseringsbeslut – tillåtelse och nekande – läggs till i ett hashkedjat revisionsspår per arbetsyta.

En logg med bara nekanden svarar på ”vad blockerade vi?” men inte på ”vad gjorde agenten egentligen, och vem auktoriserade det?”, vilket är frågan en incidentutredning börjar med. Så varje post registrerar hela attributionkedjan: den agerande aktören, människan den handlade på uppdrag av, den delegering den kom in genom, åtgärden och dess argument (som en digest), beslutet och regeln som avgjorde.

Posterna är kedjade: varje posts hash täcker den föregåendes, så att redigera, ta bort eller ändra ordningen på en rad bryter varje hash efter den. Verifiera kedja räknar om hela kedjan och pekar ut den första länk som inte håller. En revisionslogg du inte kan kontrollera är en logg; en du kan räkna om är bevis.

Två konsekvenser värda att känna till:

  • Revisionstabellen är undantagen från åldersbaserad gallring. En hashkedja kan inte kortas av i mitten. Bevarande sker genom export och därefter avkortning, och avkortningen lämnar en kontrollpunkt som bär det borttagna segmentets slutliga hash, så det som finns kvar verifieras fortfarande bakåt till början.
  • Det ligger bredvid aktivitetstidslinjen, inte ovanpå den. Tidslinjen är vad människor gjorde; det här är vad som auktoriserades och nekades. En gemensam korrelations-id följer ett och samma anrop i båda.

Det exporteras som nyradsavgränsad JSON och kan strömmas till en SIEM (Splunk, Elastic, Sentinel – en HTTP-slutpunkt med en bearer-token). Strömningen sker med bästa möjliga ansträngning, medvetet: en SIEM som ligger nere får aldrig blockera en agents verktygsanrop, och den hållbara, verifierbara kopian finns på disk oavsett.

En installation kan ange en maximal sessionsålder och en timeout för inaktivitet. Båda upprätthålls i kontrollen av enhetsuppgifter som varje autentiserad väg passerar – en sessionsbindning som en klient kunde strunta i svarar på ett frågeformulär, inte mot en angripare. En installation kan också kräva SSO, vilket stänger av manuell parkoppling för nya enheter (med en utelåsningsspärr: den vägrar så länge ingen fungerande SSO-anslutning finns).

  • Inte ACL:er per objekt. Det finns medvetet ingen behörighet per ärende eller per meddelande. Separering på repositorienivå är vad team faktiskt efterfrågar, och den finns; delning per objekt är en kombinatorisk yta utan påvisad efterfrågan här.
  • Inte en policymotor du konfigurerar i ett DSL. Vokabulären är medvetet sluten, så hela policyn kan renderas, förklaras och räknas upp.
  • Inte upprätthållet någon annanstans än på servern. Kontroller på klientsidan finns bara för att undvika att erbjuda en kontroll som ändå kommer att nekas. Det auktoritativa beslutet är alltid serverns.