Platforma · Nadzór i kontrola dostępu

Nadzór wbudowany w rdzeń

W MindooDB nadzór jest cechą samej warstwy danych - nie dodatkiem przykręconym do zaufanego serwera albo warstwy aplikacji. Polityka dostępu, tożsamość i kryptograficznie dowodliwa, odtwarzalna dla dowolnego momentu ścieżka audytu są przechowywane i wymuszane w rdzeniu bazy danych. Zysk: udowodnisz nie tylko, co się zmieniło, ale też kto miał prawo to zmienić - w chwili, gdy zmiana faktycznie trafiła do tenanta.

Nadzór ma dwie połowy: stronę zapisu, która decyduje, kto może tworzyć, zmieniać i usuwać dokumenty - wymuszaną nawet wtedy, gdy użytkownicy są offline - oraz stronę odczytu, która decyduje, kto może dane zobaczyć, łącząc bramę dostępu na poziomie synchronizacji z dystrybucją kluczy bez wglądu administratora. Obie opierają się na szyfrowaniu end-to-end w MindooDB.

Nadzór wbudowany w rdzeń: urządzenia klienckie wysyłają podpisane żądania zapisu przez bramę polityk zbudowaną z podpisanych przez administratora reguł; dozwolone zapisy trafiają do zaszyfrowanej bazy danych, odrzucone są blokowane, a oś czasu audytu pokazuje autoryzację w danym momencie
Dlaczego to nadzór, a nie same uprawnienia

Nadzór jest cechą warstwy danych

Większość stosów wypycha nadzór w górę - na serwer albo do aplikacji: baza danych przechowuje wiersze, a coś innego decyduje, kto może ich dotknąć, i prowadzi dziennik. MindooDB odwraca ten układ. Polityka, tożsamość, pełna historia i ścieżka audytu leżą w tych samych magazynach szyfrowanych end-to-end i prowadzonych w trybie append-only - gwarancje wędrują więc razem z danymi przez serwery, peery i urządzenia offline, i przetrwają nawet całkowicie przejęty serwer.

Polityka jako wersjonowane dane

Polityki i reguły to podpisane przez administratora dokumenty w bazie danych katalogu, same również append-only. Dokładny moment włączenia nadzoru - albo jego chwilowego wyłączenia - jest częścią trwałego zapisu, a nie zmianą konfiguracji, która nie zostawia śladu.

Odtwarzalna autoryzacja

Każdy wpis nosi zaufany czas, a katalog prowadzi łańcuch podróży w czasie po własnej historii. Dzięki temu wasAllowedAt(op, user, dbid, at) odtworzy, jakie reguły obowiązywały i kto był uprawniony w dowolnej przeszłej chwili - z deterministycznym wyrokiem, na który zgodzi się każda uczciwa replika.

Dowodliwa rozliczalność

Każda zmiana jest podpisana kluczem Ed25519, co czyni ją niezaprzeczalną, i poświadczona wobec zaufanego zegara. Naruszenia nie znikają po cichu - trafiają do dziennika kwarantanny i audytu prowadzonego dla każdego tenanta, który pokazuje Haven, więc rozliczalna jest nawet odrzucona próba.

Tożsamość, odwołanie i usunięcie

Dokumenty nadania zawierają tablice kluczy dla każdego urządzenia; odwołanie polega po prostu na usunięciu kluczy, a wyraźne zdalne czyszczenie urządzenia usuwa całego tenanta ze skradzionego lub porzuconego urządzenia przy następnym połączeniu - cały cykl życia tożsamości jest zarządzany w tym samym podpisanym katalogu.

Główna myśl

Model dwóch poziomów

Każda reguła należy do jednego z dwóch poziomów, w zależności od tego, co widzi serwer synchronizacji. Serwer zawsze dostaje tylko szyfrogram plus niewielki zestaw metadanych w postaci jawnej - treści dokumentów nie przeczyta nigdy. To jedno rozróżnienie jest całą architekturą: pozwala MindooDB uczciwie powiedzieć, co dokładnie jest zagwarantowane kryptograficznie, a co wymuszają polityką współpracujące klienty.

Tier 1 kontra Tier 2
Reguły tożsamościowe Tier 1 sprawdzają autora, bazę danych i typ operacji, i są wymuszane przez serwer oraz klienty; reguły treściowe Tier 2 sprawdzają withfields i są wymuszane tylko przez klienty
Reguła należy do Tier 2 dokładnie wtedy, gdy ma klauzulę withfields. Wszystko inne to Tier 1.
Porównanie dwóch poziomów
Tier Co sprawdza Kto wymusza Siła
Tier 1 - tożsamośćTożsamość autora, docelowa baza danych, typ operacji Serwer i klientyKryptograficzna - serwer odmawia poświadczenia wpisu łamiącego regułę, więc wpis nie może się rozejść
Tier 2 - treśćRzeczywista treść dokumentu (withfields)Tylko klienty Polityka - ogranicza uczciwe klienty i kształtuje UX. Zmanipulowany klient obejdzie ją tylko lokalnie; każda uczciwa replika sprawdza withfields ponownie przy odbiorze i poddaje kwarantannie zmianę łamiącą regułę, więc nigdy nie stanie się ona widoczna dla nikogo innego
Problem zegara offline

Poświadczenia świadka: zaufany zegar, do którego nie musisz ufać klientowi

Najtrudniejsze pytanie w systemie local-first brzmi: "któremu zegarowi wierzymy?". Kto pracuje offline, mógłby antydatować własne wpisy, żeby przemknąć zmianę obok polityki. MindooDB odpowiada na to poświadczeniem świadka: potwierdzeniem podpisanym przez zaufanego świadka (Twój serwer synchronizacji), że wpis został przyjęty w określonym czasie. Każdy punkt wymuszania korzysta wtedy z dokładnie jednego, jasno określonego zegara.

Cykl życia zapisu
Urządzenie autora tworzy wpis i wypycha go; serwer jako świadek sprawdza Tier 1, stempluje receivedAt i podpisuje poświadczenie; inne repliki pobierają wpis i ufają poświadczeniu. Odrzucony wpis zostaje lokalnie i nie może się zsynchronizować.
Kto stracił uprawnienie, po prostu nie zsynchronizuje danej zmiany - zegara offline nigdy nie da się użyć do antydatowania w celu obejścia polityki.
Scenariusz A
Zapis lokalny

SDK ocenia Tier 1 + Tier 2 wobec lokalnego stanu katalogu u użytkownika, na bieżący czas lokalny. Jeśli operacja jest dozwolona, wpis zapisuje się lokalnie bez pól świadka i od razu jest widoczny na tym urządzeniu. O czysto lokalnym widoku decyduje własny zegar użytkownika - i to nie szkodzi, bo zmiana jeszcze nie weszła do wspólnego tenanta.

Scenariusz B
Wypchnięcie na serwer

Serwer ocenia Tier 1 wobec własnego stanu, na czas serwera. Jeśli operacja jest dozwolona, stempluje receivedAt, zapisuje klucz świadka, podpisuje poświadczenie i zwraca pola świadka, żeby wróciły do nadawcy i poszły dalej. Jeśli odmawia, zwraca strukturalne AccessDenied, a wpis zostaje lokalnie - nie może się rozejść.

Scenariusz C
Pobranie z serwera

Odbiorca sprawdza podpis poświadczenia wobec swojej listy zaufanych świadków. Poprawny podpis oznacza, że Tier 1 był spełniony w chwili receivedAt, więc domyślnie nie jest oceniany ponownie. Następnie odbiorca sprawdza lokalnie Tier 2 i albo materializuje zmianę, albo kieruje ją do lokalnego dziennika kwarantanny i audytu.

Reguły, polityki i tożsamości

Jak konfiguruje się decyzje

Cały stan kontroli dostępu leży w dostępnej tylko administratorowi bazie danych directory i synchronizuje się do wszystkich uczestników. Wszystko, czego serwer potrzebuje do Tier 1, jest zaszyfrowane kluczem $publicinfos, więc da się to odczytać bez domyślnego klucza tenanta; treści withfields serwer nie przeczyta nigdy. Każde wywołanie zmieniające stan jest podpisane przez administratora.

Polityki ustalają poziom bazowy

Domyślna polityka tenanta i opcjonalne polityki dla poszczególnych baz danych określają, które operacje są zabronione, dopóki nie pasuje żadna reguła zezwalająca:

  • Create, change, delete & undelete - dozwolone domyślnie, dopóki ich nie zabronisz
  • Snapshot & purge - domyślnie tylko dla administratora
  • Read - poziom bazowy dla bramy odczytu i synchronizacji na poziomie bazy danych, doprecyzowany regułami odczytu
  • Dozwolone identyfikatory baz danych - lista tenanta określająca, jakie bazy danych mogą istnieć; serwer odmawia utworzenia i synchronizacji każdej bazy poza nią
  • Domyślny klucz szyfrujący - którego klucza używa nowy dokument, gdy żaden nie jest podany; to wygoda, a nie mechanizm bezpieczeństwa
  • Globalny wyłącznik - jedna flaga, która od razu wyłącza wszystkie kontrole dostępu

Zupełnie nowy tenant nie ma jeszcze żadnego dokumentu polityki, więc wszystko jest dozwolone, dopóki administrator go nie napisze. Każda wersja dopisuje się do historii, więc dokładne okno włączenia i wyłączenia zostaje sprawdzalne. Rzecz kluczowa: każda zmiana jest oceniana wobec polityk aktywnych w jej własnym zaufanym czasie (receivedAt). Zmiany, które weszły do tenanta po włączeniu, są nią objęte, a wcześniejsze rozstrzygają się wobec domyślnego, milczącego przyzwolenia - dane istniejące wcześniej zachowują więc swoje prawa automatycznie, bez żadnego kroku migracji.

Reguły decydują według deny-overrides-allow

Każda reguła celuje w typ operacji i bazę danych ("*" = wszystkie) i wymienia użytkowników lub grupy, których dotyczy. Ocena opiera się na zbiorach i nie zależy od kolejności:

  • pasuje jakakolwiek reguła denyzabronione
  • w przeciwnym razie pasuje reguła allowdozwolone
  • a jeśli nie, decyduje polityka bazowa

Niezależność od kolejności jest ważna, bo dokumenty reguł scalają się między replikami przez CRDT - nie ma kolejności reguł, o którą można się nie zgodzić.

Serwer może dojść tylko do wyroku na poziomie Tier 1. Jeśli jedyną rzeczą stojącą między zezwoleniem a odmową jest treściowa reguła Tier 2, traktuje wpis jako dozwolony na Tier 1 i zostawia sprawdzenie withfields klientom. Każda decyzja zwraca strukturalny wynik - allowed, czytelny reason, matchedRuleId oraz tier - z którego SDK korzysta, żeby wyszarzyć akcje niedostępne dla użytkownika.

withfields: warunki na treści

Klauzula withfields sprawdza ścieżkę kropkową wewnątrz dokumentu, zamkniętym zestawem operatorów (equals, contains, gt, …) i podstawieniami w rodzaju ${user.usernames}. Każda klauzula jest oceniana wobec wybranego stanu dokumentu:

  • before - dokument w obecnej postaci (domyślne dla zmiany i usunięcia): "musisz już być edytorem". Ocena na stanie after pozwoliłaby dopisać siebie i samemu autoryzować własną edycję.
  • after - dokument po zastosowaniu zmiany (domyślne dla tworzenia): "kto tworzy, musi dopisać siebie do myeditors".
Tożsamości, grupy i odwoływanie

Reguły dopasowuje się do zahaszowanej nazwy użytkownika, hashy jego grup (także zagnieżdżonych) oraz zarezerwowanych pseudotokenów:

  • $everyone - wszyscy zarejestrowani użytkownicy
  • $admin - tylko administrator
  • $author - pierwotny twórca dokumentu (Tier 1, model własności)

Odwołanie polega na usunięciu kluczy z podpisanego przez administratora dokumentu nadania - nie ma osobnych dokumentów odwołania. Administrator może też podpisać wyraźne, włączane osobno zdalne czyszczenie urządzenia, które usuwa tenanta ze skradzionego lub porzuconego urządzenia przy jego następnym połączeniu.

Przykład z życia

CRM z edytorami dla każdego rekordu

Tu jedna realistyczna polityka przechodzi całą drogę, żeby wszystkie elementy się zgrały. Tenant ma bazę danych crm i chcemy czterech reguł: wszyscy mogą tworzyć kontakty, ale muszą wpisać siebie do myeditors; zmienić kontakt może tylko już wpisany edytor; usunąć go może tylko pierwotny twórca; a grupa HR może zmieniać wszystko jako furtka dla przełożonych.

Alice tworzy kontakt

Poziom bazowy to deny. Reguła 1 pasuje przez $everyone, a jej withfields przechodzi, bo myeditors w stanie after zawiera Alice → dozwolone. Serwer potwierdza tylko Tier 1, a potem poświadcza wpis.

Bob (nie jest edytorem) próbuje to zmienić

Reguła 2 pasuje przez $everyone, ale jej withfields nie przechodzi: myeditors w stanie before nie zawiera Boba → lokalnie zabronione, nawet jeśli jego zmiana próbuje go dopisać. Zmanipulowany klient mógłby ją wypchnąć, ale każdy uczciwy odbiorca poddaje ją kwarantannie przy materializacji.

Alice usuwa, a HR nadpisuje decyzję

Reguła 3 pasuje przez $author - klucz twórcy i podpis usunięcia rozwiązują się do tego samego użytkownika → dozwolone i poświadczone (Tier 1, przetrwa złośliwego klienta). Reguła 4 pozwala każdemu członkowi grupy HR zmienić dowolny kontakt, niezależnie od myeditors.

Widać tu podział pracy: reguły Tier 1 ($author, grupa hr) są wymuszane na serwerze i przetrwają złośliwego klienta; reguły Tier 2 (sprawdzenia treści myeditors) wymusza każdy uczciwy klient i poddaje je kwarantannie przy odbiorze, jeśli zostały złamane.

Strona odczytu

Kontrola dostępu do odczytu

Reguły zapisu decydują, kto może dane zmieniać; dostęp do odczytu decyduje, kto może je widzieć - a MindooDB wymusza to na dwóch poziomach, obu podpisanych przez administratora i zaszyfrowanych kluczem $publicinfos, żeby serwer zero-trust mógł działać na potrzebnych mu metadanych, nigdy nie trzymając klucza tenanta.

1. Brama odczytu i synchronizacji na poziomie bazy danych. Poziom bazowy denyDocRead plus reguły doc_read (ta sama ocena deny-overrides-allow, celująca w użytkowników, grupy, $everyone albo $admin) decydują, kto w ogóle może otworzyć i synchronizować bazę danych. Jest to wplecione wprost w system synchronizacji: kto traci dostęp do odczytu, przestaje dostawać aktualizacje i nie otworzy już nawet swojej lokalnej, wcześniej zsynchronizowanej kopii. Ponieważ brama stoi przed każdą operacją synchronizacji, odczyt jest nadrzędną bramą dla każdej bazy danych - steruje też zapisem: kto nie może czytać bazy danych, nie utworzy w niej też danych (bo tworzyłby dokumenty, których nigdy by nie zobaczył).

2. Poufność dokumentów zostaje kryptograficzna. Dokument przeczyta tylko ten, kto w swoim KeyBagu (osobistym magazynie kluczy chronionym hasłem) ma klucz, który go odszyfruje - serwer nie podejmuje tu żadnej decyzji o odczycie. Dystrybucja kluczy odpowiada za to, by te klucze dotarły bezpiecznie do właściwych osób: podpisana przez administratora polityka mówi, którzy użytkownicy i które grupy mają trzymać dany klucz, a każdy klient automatycznie uzgadnia z nią swój KeyBag. Działa to na zasadzie opt-in - przy wspólnym kluczu domyślnym i bez bramy odczytu każdy może czytać wszystko, dokładnie jak wcześniej.

Brama odczytu wpleciona w synchronizację

W wąskim gardle na serwerze ten sam hook, który sprawdza listę dozwolonych identyfikatorów baz danych, ocenia też doc_read dla uwierzytelnionego podmiotu wobec zaufanego czasu serwera i odmawia zarówno wydania zabronionej bazy danych, jak i przyjęcia wypchnięć do niej - niedozwolone aktualizacje po prostu nigdy nie zostają dostarczone. Równolegle ścieżka otwierania na kliencie odmawia otwarcia bazy danych, do której użytkownik stracił dostęp, więc użytkownik z odwołanym dostępem nie przeczyta nawet swojej lokalnie zsynchronizowanej kopii. Baza danych directory nigdy nie podlega bramie (nosi bowiem właśnie te polityki, od których brama zależy); administrator jest wyłączony spod niej.

Klucze podróżują zaszyfrowane dla każdego odbiorcy

Gdy klucz jest wysyłany do użytkownika, szyfruje się go jego własnym osobistym kluczem publicznym (RSA), więc rozpakuje go tylko on - żaden inny użytkownik ani nawet administrator nie przeczyta tego klucza. Dlatego dystrybucja działa bez wglądu administratora: ten, kto klucz już ma, pakuje go dla odbiorców, a administrator tylko podpisuje i publikuje wynik. Zwykły użytkownik może przygotować dystrybucję i przekazać ją administratorowi do podpisu - także administratorowi, który sam tego klucza nie ma.

Wysłane klucze odsłaniają dane, odebrane je ukrywają

Każdy klient uzgadnia swój KeyBag z polityką przy starcie i po każdej synchronizacji. Wyślij komuś klucz, a jego następna synchronizacja pobierze dokumenty, które ten klucz otwiera - po prostu pojawią się w bazie danych, już czytelne. Odbierz klucz, a te dokumenty znikną: lokalne kopie, których nie da się już odszyfrować, usuwane są z bazy danych, pamięci podręcznych i widoków. Awanse, rotacje i przejścia między działami przechodzą przez to automatycznie.

Prawdziwym odcięciem jest rotacja

Dla oszczędności pasma serwer przestaje też wydawać dane zaszyfrowane kluczem, który użytkownik stracił. Ale odsunięty użytkownik, który zachował starą kopię, wciąż przeczyta to, co już miał - prawdziwym odcięciem jest więc rotacja: wydaj świeżą wersję klucza tylko pozostałym odbiorcom, a każda przyszła zmiana będzie używać wersji, której odsunięty użytkownik nigdy nie dostał.

Rozsyłanie aplikacji

Dystrybucja aplikacji oparta na politykach

Ta sama podpisywana przez administratora mechanika, która rozsyła klucze, rozsyła też aplikacje Haven. Administrator publikuje politykę, która nazywa aplikacje oferowane przez tenanta i wskazuje, kto ma je dostać, a każdy klient Haven po synchronizacji katalogu uzgadnia z tą polityką swoją lokalną listę aplikacji - wdrożenie użytkownika do tenanta samo instaluje więc aplikacje publikowane przez tego tenanta, a odebranie dostępu je usuwa.

W przeciwieństwie do klucza aplikacja nie nosi żadnego sekretu, więc dystrybucja to po prostu kwestia tego, kto co dostaje. Definicja aplikacji i jej metadane są zaszyfrowane kluczem tenanta, więc serwer zero-trust widzi wyłącznie szyfrogram, a mimo to kieruje politykę do właściwych odbiorców.

Wysyłanie do użytkowników i grup (oraz odbieranie)

Polityka celuje zarówno w pojedynczych użytkowników, jak i w całe grupy. Lista push mówi, kto ma dostać aplikację; lista pull ją odbiera. Członkostwo w grupach rozwiązuje się w czasie dystrybucji, więc dodanie albo usunięcie kogoś z grupy zmienia, kto dostaje aplikację, bez ruszania polityki, a przy nakładaniu się list pull zawsze wygrywa z push.

Przygotowane przez użytkowników, podpisane przez administratora

Zwykły użytkownik może przygotować nową dystrybucję - albo zmianę w istniejącej - i przekazać ją administratorowi jako gotowe żądanie do podpisu. Administrator przegląda je i podpisuje dokument polityki; tylko ten podpis nadaje jej moc. Odpowiada to dokładnie dystrybucji kluczy, więc aplikacjami zarządzają ci sami ludzie, którzy zarządzają już kluczami.

Automatyczna instalacja, aktualizacja i usuwanie

Po każdej synchronizacji katalogu klient porównuje politykę z tym, co ma lokalnie: instaluje aplikacje, które powinien już mieć, aktualizuje aplikację, gdy zmieni się opublikowana wersja albo szczegóły, i usuwa każdą, do której nie ma już uprawnień - wszystko bez kiwnięcia palcem przez użytkownika.

Wyraźnie zarządzane przez tenanta

Rozesłana aplikacja jest oznaczona jako zarządzana przez tenanta i pokazuje, z którego tenanta pochodzi. Aplikacji zarządzanych użytkownik nie może edytować ani usunąć - tylko zduplikować do prywatnej kopii na potrzeby lokalnego budowania i testów - żeby opublikowana wersja tenanta pozostała źródłem prawdy.

Audyt i zakres

Sprawdzalne z założenia, uczciwe wobec swoich granic

Odtwarzalne dla dowolnego momentu

Ponieważ każdy wpis nosi zaufany czas (receivedAt, a dla wpisów wyłącznie lokalnych zapasowo createdAt), a katalog prowadzi łańcuch podróży w czasie po własnej historii, odpowiesz na pytanie "czy użytkownik X miał prawo zmienić ten dokument w chwili, gdy zmiana faktycznie weszła do tenanta?" - i odtworzysz dokładnie, jak jego dostęp zmieniał się z czasem. Zapytanie wasAllowedAt(op, user, dbid, at) czyni z tego pełnoprawne API. Naruszenia Tier 2 nie znikają po cichu; trafiają do dziennika kwarantanny prowadzonego dla każdego tenanta, który Haven pokazuje w widoku audytu.

Zakres i cele negatywne v1

Warstwa ta reguluje zarówno zapisy, jak i odczyty (na poziomie dokumentów i kluczy). Nie powstrzyma zmanipulowanego klienta od utworzenia wpisu lokalnie, ale nie dopuści, by ten wpis został przyjęty do tenanta, a brama odczytu na serwerze nie pozwoli nieuprawnionym danym w ogóle dotrzeć do klienta. W v1 świadkiem jest synchronizacja przez serwer. Synchronizacja z urządzenia na urządzenie przez Iroh już istnieje, ale peer nie wystawia pokwitowania świadka: urządzenie odbierające samo ocenia reguły tożsamości, a serwer ocenia wpis ponownie, gdy ten dotrze. Pokwitowania świadka wystawiane przez peery i prawdziwa kontrola odczytu na poziomie pól (klucze dla każdego pola) pozostają na później. Historia nie jest nigdy szyfrowana ponownie w miejscu, bo podpisy autorów obejmują szyfrogram.

Zobacz to w akcji
Haven - obszar roboczy zbudowany na tym modelu dostępu

MindooDB Haven wkłada to samo szyfrowanie end-to-end, podpisaną historię i wbudowany nadzór w spokojny, wieloplatformowy obszar roboczy - razem z widokiem audytu, który pokazuje zmiany w kwarantannie. Wypróbuj darmową betę albo poczytaj szczegóły.