Przejdź do głównej zawartości

Autoryzacja — kto może co robić i jak to udowodnisz

Control Center odpowiada na dwa pytania autoryzacyjne i są to pytania naprawdę różne. „Czy ta osoba może wywołać tę operację?” dotyczy ludzi, ról i repozytoriów. „Czy ten agent może wywołać ten efekt?” dotyczy działań, argumentów i zasięgu skutków — to drugie należy do guardraili.

Ta strona odpowiada na pierwsze pytanie, a także opisuje ślad, który zostawiają oba.

Każda decyzja autoryzacyjna dotycząca człowieka przechodzi przez jedną funkcję:

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

Uprawnienie ma postać <domain>:<tier> — tickets:write, members:administer, repos:read. Katalog jest wyprowadzany, a nie pisany ręcznie: powstaje na podstawie samej powierzchni operacji (prefiks nazwy operacji wyznacza domenę, wymuszany już próg roli wyznacza poziom), dzięki czemu wszystkie ~550 operacji mają przypisane uprawnienie, choć nikt go nie wpisuje.

To wyprowadzanie jest cechą wartą ochrony. Oznacza, że NOWA operacja domyślnie podlega bramce — trybem awarii modelu opisywanego ręcznie jest to, że ktoś zapomni, a tym, o czym zapomni, jest właśnie bramka. Test zapadkowy przypina wynikowy zbiór domen, więc dodanie operacji pod nowym prefiksem to decyzja nazewnicza podejmowana przez człowieka, a nie przypadek.

Cztery poziomy odpowiadają dokładnie wbudowanym rolom:

Poziom Minimalna rola Przykład
read gość tickets:read
write członek tickets:write
administer administrator members:administer
own właściciel workspace:own

Pięć wbudowanych ról — właściciel, administrator, członek, obserwator, gość — to gotowe zestawy oparte na tym katalogu. Własność to jedno miejsce na obszar roboczy, przekazywane jawnie przez Przenieś własność (właściciel, który odchodzi, jest inaczej nieusuwalny: cofanie aprowizacji przez SCIM odmawia w przypadku każdego właściciela obszaru roboczego — najpierw przenieś własność).

Role niestandardowe działają odejmująco. Rola niestandardowa wskazuje rolę bazową (admin, member, viewer albo guest — nigdy owner) oraz zestaw uprawnień z niej USUNIĘTYCH — „administrator, ale bez zarządzania członkami”. Nigdy nie może przyznać więcej niż jej baza, i właśnie dlatego można je bezpiecznie wprowadzać do istniejącej instalacji: każde istniejące sprawdzenie pozostaje bezpiecznym górnym ograniczeniem. Członkowie mają je jako custom:<id>, a klient zbyt stary, by zrozumieć tę wartość, cofa się do roli gościa, zamiast zgadywać.

Pod rolami znajdują się uprawnienia do poszczególnych repozytoriów (none / read / review / write): członkostwo w obszarze roboczym nigdy po cichu nie daje większych uprawnień niż host kodu. Sprawdzają je wszystkie powierzchnie udostępniające kod — także te, które sięgają do kodu bokiem, jak terminal czy sesja edytora otwarta w worktree przestrzeni.

Niektóre operacje wcale nie dotyczą obszaru roboczego: ustawienia dla całej instalacji, konfiguracja SSO, poświadczenia dostawców, zarządzanie modelami, kopie zapasowe całej instalacji. Deklarują one autorytet serwera i są odmawiane wszystkim poza operatorem instalacji (zarejestrowanym właścicielem serwera). Świadomie istnieje jedna tożsamość operatora i jedna jej definicja.

Każda decyzja autoryzacyjna — zgoda i odmowa — jest dopisywana do dziennika audytu prowadzonego dla każdego obszaru roboczego i powiązanego łańcuchem skrótów.

Dziennik zawierający wyłącznie odmowy odpowiada na pytanie „co zablokowaliśmy?”, ale nie na pytanie „co ten agent faktycznie zrobił i kto to autoryzował?”, od którego zaczyna się analiza incydentu. Dlatego każdy wpis rejestruje pełny łańcuch atrybucji: podmiot działający, człowieka, w imieniu którego działał, delegację, przez którą nadeszło, działanie i jego argumenty (w postaci skrótu), decyzję oraz regułę, która zdecydowała.

Wpisy są powiązane łańcuchem: skrót każdego obejmuje poprzedni, więc edycja, usunięcie lub zmiana kolejności dowolnego wiersza psuje każdy kolejny skrót. Zweryfikuj łańcuch odtwarza całość od nowa i wskazuje pierwsze ogniwo, które się nie zgadza. Dziennika audytu, którego nie można sprawdzić, jest tylko dziennikiem; ten, który można odtworzyć, jest dowodem.

Dwie konsekwencje warte poznania:

  • Tabela audytu jest wyłączona z czyszczenia na podstawie wieku. Łańcucha skrótów nie można obciąć w środku. Retencja polega na eksporcie, a następnie obcięciu, a obcięcie pozostawia punkt kontrolny zawierający skrót końcowy usuniętego segmentu, więc to, co przetrwa, nadal weryfikuje się aż do początku.
  • Znajduje się obok osi czasu aktywności, a nie ponad nią. Oś czasu pokazuje, co zrobili ludzie; dziennik — co zostało autoryzowane i odrzucone. Wspólny identyfikator korelacji pozwala prześledzić jedno wywołanie w obu.

Dziennik jest eksportowany jako JSON rozdzielany znakami nowej linii i może być strumieniowany do SIEM (Splunk, Elastic, Sentinel — punkt końcowy HTTP z tokenem bearer). Strumieniowanie z założenia działa w miarę możliwości: awaria SIEM nigdy nie może blokować wywołania narzędzia przez agenta, a trwała, weryfikowalna kopia i tak leży na dysku.

Instalacja może ustawić maksymalny wiek sesji oraz limit bezczynności. Oba są egzekwowane przy sprawdzaniu poświadczeń urządzenia, przez które przechodzi każda uwierzytelniona ścieżka — ograniczenie sesji, które klient może zignorować, odpowiada na ankietę, a nie na atakującego. Instalacja może też wymagać SSO, co wyłącza ręczne parowanie nowych urządzeń (z zabezpieczeniem przed zablokowaniem dostępu: odmawia, dopóki nie istnieje działające połączenie SSO).

  • Nie listy ACL dla poszczególnych obiektów. Świadomie nie istnieje uprawnienie do pojedynczego zgłoszenia czy wiadomości. Separacja na poziomie repozytoriów to coś, o co zespoły naprawdę proszą, i ona istnieje; udostępnianie poszczególnych obiektów to powierzchnia kombinatoryczna bez udowodnionego tu zapotrzebowania.
  • Nie silnik polityk konfigurowany w DSL. Słownik jest celowo zamknięty, więc całą politykę można wyrenderować, wyjaśnić i wyliczyć.
  • Nie egzekwowana nigdzie poza serwerem. Sprawdzenia po stronie klienta istnieją tylko po to, by nie oferować kontrolki, która zostanie odrzucona. Wiążąca decyzja zawsze należy do serwera.