Gå til innholdet

Autorisasjon — hvem får gjøre hva, og hvordan du beviser det

Control Center svarer på to autorisasjonsspørsmål, og de er genuint forskjellige. «Får denne personen kalle denne operasjonen?» handler om mennesker, roller og repoer. «Får denne agenten forårsake denne effekten?» handler om handlinger, argumenter og skadeomfang — det spørsmålet dekkes av Tillatelsesregler.

Denne siden handler om det første spørsmålet, i tillegg til nedtegnelsen begge etterlater seg.

Hver autorisasjonsbeslutning på menneskesiden løses gjennom én enkelt funksjon:

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

En tillatelse er <domain>:<tier> — tickets:write, members:administer, repos:read. Katalogen er utledet, ikke håndskrevet: den beregnes fra selve operasjonsflaten (navneprefikset til operasjonen gir domenet, rolleminimumet den allerede håndhever, gir nivået), slik at alle ~550 operasjoner har en tillatelse uten at noen har skrevet den inn.

Det er denne utledningen som er verdt å verne om. Den gjør at en NY operasjon er sperret som standard — feilmodusen til en håndannotert modell er at noen glemmer det, og det de glemmer, er nettopp sperren. En låsetest fester domenesettet som blir resultatet, slik at det å legge til en operasjon under et nytt prefiks blir et navnevalg et menneske tar, og ikke en tilfeldighet.

De fire nivåene svarer nøyaktig til de innebygde rollene:

Nivå Rolleminimum Eksempel
read gjest tickets:read
write medlem tickets:write
administer admin members:administer
own eier workspace:own

Fem innebygde roller — eier, admin, medlem, leser, gjest — er forhåndsvalg over denne katalogen. Eierskap er ett enkelt sete per arbeidsområde og overføres eksplisitt med Overfør eierskap (en eier som slutter, er ellers umulig å fjerne: deprovisjonering via SCIM avviser enhver eier av et arbeidsområde — overfør først).

Egendefinerte roller er subtraktive. En egendefinert rolle angir et basisforhåndsvalg (admin, member, viewer eller guest — aldri owner) og et sett med tillatelser som FJERNES fra det — «admin, men kan ikke administrere medlemmer». Den kan aldri gi mer enn basisen sin, og det er nettopp derfor de er trygge å innføre i en eksisterende installasjon: enhver eksisterende sjekk forblir en gyldig øvre grense. Medlemmer har dem som custom:<id>, og en klient som er for gammel til å forstå den verdien, faller tilbake på gjest i stedet for å gjette.

Under rollene ligger tilganger per repo (none / read / review / write): medlemskap i et arbeidsområde gir aldri i stillhet større rettigheter enn kodeverten. Enhver flate som eksponerer kode, sjekker dem — også de som når koden på omveier, som en terminal eller en editorsesjon åpnet på et områdes worktree.

Noen operasjoner handler ikke om et arbeidsområde i det hele tatt: installasjonsomfattende innstillinger, SSO-konfigurasjon, påloggingsinformasjon for leverandører, modellhåndtering, sikkerhetskopier av hele installasjonen. Disse erklærer serverautoritet og avvises for alle unntatt installasjonens operatør (den registrerte servereieren). Det finnes med vilje én operatøridentitet og én definisjon av den.

Hver autorisasjonsbeslutning — tillatelse så vel som avvisning — legges til i et hash-kjedet revisjonsspor per arbeidsområde.

En logg som bare inneholder avvisninger, svarer på «hva blokkerte vi?», men ikke på «hva gjorde denne agenten egentlig, og hvem autoriserte det?» — og det er spørsmålet en hendelsesgjennomgang starter med. Derfor registrerer hver oppføring hele tilskrivningskjeden: den handlende identiteten, mennesket den handlet på vegne av, delegeringen den kom gjennom, handlingen og argumentene (som en digest), beslutningen og regelen som avgjorde.

Oppføringene er kjedet sammen: hashen til hver oppføring dekker den forrige, så å redigere, slette eller omorganisere en rad bryter alle hasher etter den. Verifiser kjede utleder hele kjeden på nytt og navngir det første leddet som ikke holder. En revisjonslogg du ikke kan kontrollere, er bare en logg; en du kan utlede på nytt, er bevis.

To konsekvenser det er verdt å kjenne til:

  • Revisjonstabellen er unntatt fra aldersbasert opprydding. En hash-kjede kan ikke trimmes fra midten. Oppbevaring skjer ved å eksportere og deretter trunkere, og trunkeringen etterlater et sjekkpunkt som bærer den fjernede delens avsluttende hash, slik at det som blir igjen, fortsatt lar seg verifisere helt tilbake til begynnelsen.
  • Det ligger ved siden av aktivitetstidslinjen, ikke oppå den. Tidslinjen viser hva folk gjorde; dette viser hva som ble autorisert og avvist. En felles korrelasjons-id leser ett kall på tvers av begge.

Det eksporteres som nylinjeseparert JSON og kan strømmes til et SIEM (Splunk, Elastic, Sentinel — et HTTP-endepunkt med et bearer-token). Strømming skjer etter beste evne, og det er med vilje: at et SIEM er nede, må aldri blokkere et verktøykall fra en agent, og den varige, verifiserbare kopien ligger uansett på disk.

En installasjon kan angi en maksimal øktalder og et tidsavbrudd ved inaktivitet. Begge håndheves i enhetslegitimasjonskontrollen som hver autentiserte kanal passerer — en øktbegrensning en klient bare kan ignorere, er et spørreskjema, ikke et forsvar mot en angriper. En installasjon kan også kreve SSO, noe som slår av manuell paring for nye enheter (med et utestengingsvern: det nekter så lenge ingen fungerende SSO-tilkobling finnes).

  • Ikke ACL-er per objekt. Det finnes med vilje ingen tillatelse per sak eller per melding. Separasjon på reponivå er det team faktisk etterspør, og den finnes; deling per objekt er en kombinatorisk flate uten dokumentert etterspørsel her.
  • Ikke en policy-motor du konfigurerer i et DSL. Vokabularet er lukket med vilje, slik at hele policyen kan gjengis, forklares og listes opp.
  • Håndheves ikke andre steder enn på serveren. Kontroller på klientsiden finnes bare for å unngå å tilby en kontroll som vil bli avvist. Den autoritative beslutningen er alltid serverens.