vitrinka.docs
Bezpečnost

Šifrování a klíče

Jak jsou chráněné klíče jednotlivých workspaců, která data se šifrují a jak provést rotaci klíče instalace.

Obálka

Každý workspace vlastní 32bajtový datový šifrovací klíč AES-256-GCM (DEK). Řídicí databáze ho ukládá jen v zabalené podobě, zašifrovaný klíčem instalace pro šifrování klíčů (KEK), spolu s id poskytovatele, který ho zabalil. Rozbalení probíhá v procesu serveru při otevření workspace; rozbalený DEK se tam drží v paměti a nezapisuje se do databáze nájemce, do úložiště blobů ani do logu.

KEK se načítá z VITRINKA_KEK jako 64 hexadecimálních znaků. Pokud není nastavený, server použije VITRINKA_MASTER_KEY. Neplatná hodnota VITRINKA_KEK zabrání spuštění serveru. S VITRINKA_KEYS_PROVIDER=openbao KEK v prostředí vůbec není — zůstává uvnitř transit enginu a server mu posílá jen zabalené klíče — viz Úložiště klíčů.

Co je zapečetěné

DataFormátVázáno na
Citlivé sloupce nájemce — zachycené události nahraných sessions a hlášení chyb, zprávy ve vláknech anotací a zadání revizí, dokumenty stránek a jejich historie úprav, paměť projektu, zmrazené snímky sdílení, textové mapy snímků obrazovky a souborů, záznamy pracovního času, úlohy a zpětná vazba hodnocení reviewenc2 — verze, id klíče, 12bajtový nonce, AES-256-GCMid workspace + druh obsahu
Každý blob — nahrané soubory, snímky obrazovky, nahrávky, zdroje náhledůenc2 s druhem blobid workspace + blob
Archivy záloh a další operátorské artefaktyenc2f — čerstvý zabalený DEK, pak rámované 4 MiB bloky AES-256-GCMindex rámce + typ rámce

Šifrování váže obsah na workspace a jeho typ. Přesunutí šifrované hodnoty do jiného workspace nebo jiného typu sloupce proto způsobí chybu ověření. U archivů se ověřuje také pořadí a typ bloků; poškozený nebo neúplný archiv se nepovažuje za úspěšně obnovený.

Co tabulka nevyjmenovává, se ukládá tak, jak je, a chrání to šifrování svazku a řízení přístupu: zbytek nástěnky (karty kromě stránek, jejich pozice a popisky), úkoly, fulltextové indexy — které drží text odvozený ze zapečetěného obsahu — a identifikátory a časové údaje. Datový svazek hostované služby používá šifrování LUKS2; vlastní instalace si šifrování svazku zajišťuje sama.

Objektové úložiště

S BLOB_BACKEND=s3 server po bucketu chce i šifrování na straně serveru: VITRINKA_S3_SSE je ve výchozím stavu aes256, kms:<key id> pro klíč spravovaný zákazníkem, nebo off. Backend, který hlavičku odmítne, degraduje na off s jedním řádkem v logu při startu; důvěrnost stojí tak jako tak na pečetění enc2 na straně klienta, takže bucket odmítající SSE drží pořád jen šifrovaný text.

Průchozí cache před S3 (BLOB_CACHE_MAX_GB) ukládá stejný šifrovaný text, jaký drží bucket. Ukradený adresář cache nevydá nic, co by nevydal ukradený bucket.

Přísný režim a pečeticí průchod

Starší instalace mohou obsahovat data zapsaná před zavedením šifrování. Server je ve výchozím režimu umí přečíst. VITRINKA_SEAL_STRICT=on čtení takových dat odmítne, proto tento režim zapněte až po jejich zašifrování a úspěšném ověření.

vitrinka seal-existing -data /data                                   # sčítání nanečisto, nic nezapíše
vitrinka seal-existing -data /data -manifest /root/seal.json -execute # zapečetí každý řádek a objekt v prostém textu na místě
vitrinka seal-existing -data /data -verify                           # brána: nula nezapečetěných položek, každý zbytek pojmenovaný

Příkaz před každou aktualizací ověří zašifrování a zpětné dešifrování hodnoty. Zápis provede jen tehdy, pokud se mezitím původní hodnota nezměnila. -verify skončí chybou, pokud zbývají nezašifrované položky nebo pokud neměl co ověřit.

VITRINKA_SEAL_STRICT=on přepínejte až poté, co nefiltrovaný běh -verify vypíše svůj řádek o průchodu. Přísný režim se zbylým prostým textem promění ty položky v chyby čtení, záměrně.

Rotace klíče instalace

Rotace KEK nikdy nepřešifrovává data: rozbalí DEK každého workspace pod starým KEK a znovu ho zabalí pod novým, jedna transakce na řádek. Bajty DEK se nemění, takže nic pod nimi zapečetěného se nedotkne, a běh přerušený v půlce dokončíte tím, že ho spustíte znovu.

vitrinka rewrap-deks -data /data -old-kek <hex> -new-kek <hex>           # nanečisto
vitrinka rewrap-deks -data /data -old-kek <hex> -new-kek <hex> -execute

Klíče můžou přijít z VITRINKA_REWRAP_OLD_KEK a VITRINKA_REWRAP_NEW_KEK místo přepínačů, aby se nedostaly do ps a historie shellu. Spouštějte se zastaveným serverem: živý proces pořád drží starý KEK a kontrola klíče při startu potvrdí nový, než se obsluha obnoví. Zavedení vyhrazeného VITRINKA_KEK na instalaci, která běžela na záložním master klíči, je samo o sobě rotací — starý KEK je hodnota master klíče.

Úložiště klíčů

VITRINKA_KEYS_PROVIDER rozhoduje, kdo drží KEK. Výchozí env je obálka popsaná výše: KEK sedí v prostředí serveru a nic ohledně klíčů neopouští hostitele. openbao přesune KEK do transit klíče v OpenBao. Server ten klíč nikdy nevidí: každý zabalený DEK pošle transit enginu k dešifrování a dostane zpět DEK, takže kopie disků datového hostitele vydá zabalené klíče a žádný klíč, který by je otevřel. Běžící server drží DEK workspace v paměti jen po dobu, kdy je workspace otevřený, a každé rozbalení je řádek v auditu. Transit klíč se zakládá jako neexportovatelný, takže ani výpis klíčového serveru KEK nevydá, a jeho rotace v OpenBao je průchod přebalením, přesně jako rotace VITRINKA_KEK.

K této topologii hostovaná služba přechází: transit engine žije na vyhrazeném klíčovém serveru, který hostí jen úložiště tajemství, dostupném přes privátní síť WireGuard, a každý z obou serverů se při startu odemyká materiálem drženým na tom druhém. Který stav produkce právě provozuje, uvádí bezpečnostní přehled. Vlastní instalace zůstává na env, pokud se její provozovatel nerozhodne jinak; pod env server kvůli klíčům nedělá žádné odchozí volání, takže odpojené instalace se tato sekce netýká.

ProměnnáVýchozíPoznámky
VITRINKA_KEYS_PROVIDERenvenv nebo openbao.
VITRINKA_OPENBAO_ADDR—URL transit enginu, jen v privátní síti. Povinné pro openbao.
VITRINKA_OPENBAO_MOUNTtransitCesta transit mountu.
VITRINKA_OPENBAO_KEYvitrinka-kekNázev transit klíče; každý zabalený DEK nese id poskytovatele openbao:<key>.
VITRINKA_OPENBAO_ROLE_ID VITRINKA_OPENBAO_SECRET_ID—Přihlášení AppRole. Na straně OpenBao roli navažte na privátní adresu datového hostitele. Tajné.
VITRINKA_OPENBAO_TOKEN—Statický token místo AppRole — jen pro vývoj. Tajné.
VITRINKA_OPENBAO_CAsystémové kořenyBalík CA pro privátní certifikát na transit endpointu — cesta k PEM souboru, nebo přímo text PEM (hodnota začínající -----BEGIN; doslovné sekvence \n se rozbalí) tam, kde kontejner nepřipojuje žádný soubor hostitele.
VITRINKA_DEK_REVERIFY15mJak často se DEK každého otevřeného workspace znovu ověřuje proti úložišti klíčů.

Kontrola při startu

Při startu server přes poskytovatele rozbalí master klíč a pak spustí stejnou kontrolu klíčů jako env: každý uložený zabalený DEK se jednou dešifruje přes transit a každé dešifrování přistane jako řádek workspace.dek_unwrap v auditní stopě s důvodem verify. Jakékoli selhání — nedostupný engine, odmítnutá AppRole, DEK, který už nejde dešifrovat — spuštění odmítne s pojmenovanou nápravou, přesně jako neplatný VITRINKA_KEK. Server nikdy neobsluhuje nad úložištěm klíčů, které nedokázal prověřit.

Opakované ověřování

Otevření workspace rozbalí jeho DEK přes transit (důvod open) a drží ho v paměti. Každých VITRINKA_DEK_REVERIFY pool nájemců znovu dešifruje zabalený DEK každého otevřeného workspace (důvod reverify); neshoda nebo odmítnutí workspace z poolu vyřadí a výsledek zaznamená jako zamítnutý. Klíč odvolaný nebo odrotovaný v OpenBao tak přestane obsluhovat do jednoho intervalu, bez restartu. Smyčka nikdy nedrží zámek poolu přes síťové volání, takže pomalý klíčový server zdrží opakované ověření, ne požadavek. Rotace zapisuje důvod rewrap; kryptografické smazání nic nerozbaluje a zapisuje se na vlastní řádek workspace.dek.shred, který nově uvádí i poskytovatele. Klíčový server vede vlastní auditní zařízení jako nezávislý záznam týchž volání.

Přesun do úložiště klíčů a zpět

rewrap-deks je migrační dveře v obou směrech. -to openbao přebalí každý DEK z KEK v prostředí do transit klíče, jedna transakce na řádek, a k každému otiskne nové id poskytovatele; právě id poskytovatele na řádku dovoluje řádkům env a openbao uprostřed běhu koexistovat, takže přerušený průchod dokončíte tím, že ho spustíte znovu. Master klíč se stěhuje s ním: pod openbao je uložený zabalený v řídicí databázi a rozbalený jednou při startu, takže prostředí drží jen přihlašovací údaje AppRole a žádný dlouhodobý klíčový materiál.

vitrinka rewrap-deks -data /data -old-kek <hex> -to openbao            # nanečisto: spočítá řádky per poskytovatel, nic nezapíše
vitrinka rewrap-deks -data /data -old-kek <hex> -to openbao -execute
vitrinka rewrap-deks -data /data -to env -new-kek <hex> -execute       # návrat: znovu přebalí pod KEK z prostředí

Spouštějte se zastaveným serverem, s nastavenými proměnnými OpenBao pro stranu openbao a s KEK z prostředí (přepínač nebo VITRINKA_REWRAP_OLD_KEK / VITRINKA_REWRAP_NEW_KEK) pro stranu env; kontrola klíčů při dalším startu prověří cíl, než se obsluha obnoví.

Opuštění úložiště klíčů je záměrný sestup: po -to env je KEK zpátky v prostředí a stopa rozbalování končí na hostiteli. Dělejte to jen kvůli vyřazení klíčového serveru, který nahrazujete, a napřed přebalte do jeho nástupce.

Když je úložiště klíčů nedostupné

Start selže uzavřeně. Běžící server degraduje po jednom workspace: už otevřené workspace obsluhují dál, dokud jim neselže další opakované ověření, neotevřený workspace otevřít nejde a jeho požadavky odpovídají 503 s pojmenovaným úložištěm klíčů. Neúspěšné opakované ověření se zapíše do logu a započítá do vitrinka_tenant_dek_reverify_failures_total, který vydává listener VITRINKA_METRICS_ADDR — výstrahu na něj nastavte ve svém monitoringu. Krátký výpadek sítě nic nestojí; dlouhý výpadek ukončí obsluhu do jednoho intervalu VITRINKA_DEK_REVERIFY, ne naráz. Obnovte klíčový server a další otevření uspěje bez restartu.

Export auditu

Auditní stopa opouští hostitele jako hashem řetězené dávky podepsané vlastním klíčem instalace; proměnné, cíle a postup s audit-verify najdete v Auditní stopě.

Na této stránce