Was das Portal von PaaSbox für deine Cluster verwahrt, wie jeder Teil die anderen prüft, und was ein Angreifer mit einer geleakten Datenbank, einem geleakten Schlüssel oder einem laufenden Portal unter seiner Kontrolle tun könnte. Die Gründe hinter dem Entwurf stehen unter So funktioniert es; diese Seite listet die Fakten.
Dein Hetzner-Token, das dein ganzes Projekt öffnet, lesend und schreibend
Verschlüsselt
Das k3s-Server-Token, in jeder Version, die ein behaltener Snapshot noch braucht
Verschlüsselt
Das k3s-Agent-Token
Verschlüsselt
Das Hetzner-Token, das im Cluster benutzt wird (ein eigenes oder eine Kopie des ersten)
Verschlüsselt
Die S3-Schlüssel deines Snapshot-Buckets, wenn du sie nicht selbst hältst
Verschlüsselt
Die geheimen Optionen von Add-ons, etwa DNS-Tokens
Verschlüsselt
Eine versiegelte Kubeconfig, bis sie abgeholt ist
Verschlüsselt, höchstens 5 Minuten; das Siegel kann das Portal nicht öffnen
Die Schlüssel von pbx-agent
Nur die öffentlichen
Registrierungs-Tokens
Nur Hashes
Deine API-Schlüssel In Arbeit
Nur Hashes; ein Schlüssel wird einmal angezeigt, wenn er entsteht
Das Audit-Log der Aufrufe über API und MCP In Arbeit
Die Argumente, ohne jedes Geheimnis
Die verschlüsselten Felder liegen verschlüsselt in der Datenbank des Portals, mit Schlüsseln, die außerhalb von ihr verwahrt werden. Die Geheimnisse, die das Portal an pbx-agent schickt, sind so versiegelt, dass nur der pbx-agent dieses Clusters sie öffnen kann.
Verwahrt nie
Admin-Kubeconfigs oder ihre Tokens
Sie entstehen auf dem Node und werden an den Schlüssel dessen versiegelt, der gefragt hat
/etc/rancher/k3s/k3s.yaml, die Admin-Datei auf dem Server
Das Portal liest sie nie
Die privaten Schlüssel von pbx-agent
Sie entstehen auf dem Node und verlassen ihn nie
Den Inhalt deiner Snapshots
Sie gehen vom Node in deinen Bucket
Die Daten deiner Workloads oder ihre Secrets
Server-Token und S3-Schlüssel zusammen könnten einen Snapshot öffnen, und ein Snapshot enthält jedes Secret deines Clusters. Das ist der Preis einer Wiederherstellung, ohne dass du an der Tastatur sitzt. Hältst du die Schlüssel des Buckets selbst, sieht das Portal sie nie und kann deine Snapshots nicht lesen; eine Wiederherstellung funktioniert dann nur, solange die API des Clusters läuft, und eine Wiederherstellung auf einen neuen Server bräuchte deine Schlüssel. In Arbeit Selbst gehaltene Schlüssel sind auf einem echten Cluster noch nicht gelaufen. Siehe Backups einrichten.
Die User Data eines neuen Servers enthalten ein Registrierungs-Token, einmal benutzbar, 30 Minuten gültig und an den Cluster und den Namen des Nodes gebunden. Das Portal prüft über die Hetzner-API, dass der Server das Label des Clusters und den Namen des Nodes trägt, und prüft den Hash des Images, das der Node tatsächlich gebootet hat, gegen das Release. Erst dann gibt es die Konfiguration des Nodes heraus.
Schlüssel, die auf dem Node entstehen
Beim ersten Start erzeugt pbx-agent einen Signaturschlüssel und einen Verschlüsselungsschlüssel. Die privaten Hälften verlassen den Server nie. Das Portal wechselt sie alle 90 Tage.
Signierte Anfragen
Jede Anfrage nach der Registrierung ist über Methode, Pfad, einen Zeitstempel und einen Hash des Inhalts signiert. Das Portal lehnt eine Uhrabweichung über 60 Sekunden ab und eine Signatur, die es in den letzten 120 Sekunden schon gesehen hat.
Versiegelte Geheimnisse
Jedes Geheimnis, das das Portal schickt, ist für den Schlüssel des Nodes verschlüsselt. pbx-agent lehnt ein Dokument ab, in dem ein Geheimnis im Klartext ankommt.
Nichts Dauerhaftes in den User Data
User Data bleiben vom Server aus lesbar, solange er existiert. Sie enthalten nur die Download-Adresse und die Prüfsumme von pbx-agent, die Adresse des Portals, die ID des Clusters, den Namen des Nodes und das Registrierungs-Token, das nach Gebrauch oder Ablauf nutzlos ist. Das Node-Image sperrt Pods von der Metadaten-Adresse aus.
Signierte Releases
Ein Release ist mit einem Schlüssel signiert, den ich offline verwahre: nie auf dem Portal, nie in der CI. pbx-agent trägt zwei öffentliche Schlüssel fest eingebaut und lehnt ein Release ab, das keiner von beiden signiert hat. Er aktualisiert sich nur auf eine Version, die in einem solchen Release steht, und geht zur vorigen zurück, wenn die neue das Portal nicht innerhalb von 10 Minuten erreicht. In Arbeit Diese Rückkehr hat auf einem echten Server noch nicht ausgelöst.
Versiegelte Kubeconfigs
Eine Kubeconfig entsteht auf dem Node und wird für einen Schlüssel verschlüsselt, den nur der Anfragende hält: einen Schlüssel, den dein Browser für diese eine Anfrage erzeugt, oder den eigenen Schlüssel eines Agenten. Das Portal reicht die versiegelte Kopie einmal weiter und kann sie nicht lesen.
Geheime Optionen von Add-ons
Landen in Kubernetes-Secrets, die k3s im Ruhezustand verschlüsselt, nie in anderen Objekten.
In Arbeit Die REST-API und die MCP-Tools sind Code, noch nicht an einem echten Cluster gelaufen. Leitplanken für Agenten sagt, was jede Grenze verhindert und was nicht.
Grenze
Was sie tut
Team-Schlüssel
Ein Team-Admin legt einen Schlüssel für ein Team an, mit einem Ablauf nach 30 Tagen, 90 Tagen, einem Jahr oder ohne, und kann ihn sofort widerrufen. Höchstens 25 aktive Schlüssel pro Team.
Scopes
k3s:read, k3s:write, k3s:access, k3s:destructive. Jeder Aufruf braucht genau einen; ein Schlüssel hält nur, was sein Agent braucht.
Die Person hinter dem Schlüssel
Der Schlüssel handelt als die Person, die ihn angelegt hat, und die muss noch aktives Mitglied des Teams sein. Ein Scope engt ein, was diese Person darf; er erweitert es nie.
Zerstörende Aufrufe
Einen Cluster anlegen, löschen, abkoppeln und wiederherstellen braucht k3s:destructive, einen Team-Admin als Besitzer des Schlüssels und den Namen des Clusters, eingetippt als Bestätigung.
Kubeconfigs
Versiegelt an den eigenen Schlüssel des Agenten; eine Kubeconfig, die über einen Schlüssel angefragt wurde, kann nur dieser Schlüssel abholen.
Ratenlimits
120 Aufrufe pro Minute pro Schlüssel, davon 20, die etwas ändern.
Audit-Log
Jeder MCP-Aufruf und jeder REST-Aufruf, der etwas ändert oder eine Kubeconfig herausgibt, auch abgelehnte: wer, über welchen Schlüssel, was, mit welchen Argumenten (ohne Geheimnisse) und wie es ausging. Team-Admins lesen es im Portal.
Chiffretexte, öffentliche Schlüssel und die Hashes von Registrierungs-Tokens und API-Schlüsseln. Die Schlüssel, die die Chiffretexte entschlüsseln, liegen nicht in der Datenbank. Die Argumente im Audit-Log, die keine Geheimnisse tragen.
Ein Angreifer, der das laufende Portal kontrolliert, könnte
Warum
Alles in deinem Hetzner-Projekt anlegen, ändern und löschen, nicht nur die Ressourcen des Clusters
Das Portal hält dein Hetzner-Token. Darum gehören deine Cluster in ein eigenes Projekt.
pbx-agent um eine Admin-Kubeconfig bitten und damit als cluster-admin auf jedem Cluster handeln, den es verwaltet
Kubeconfigs ausstellen ist eine der Operationen von pbx-agent
Eine Wiederherstellung eines älteren Snapshots anstoßen, die den Zustand des Clusters zurücksetzt
Wiederherstellen ist eine der Operationen von pbx-agent
Die Einstellungen ändern, die das Portal verwaltet: Add-ons und ihre Optionen aus dem Release des Clusters, den Snapshot-Zeitplan und, wenn das Portal die S3-Schlüssel hält, das Snapshot-Ziel
pbx-agent wendet den Sollzustand an, den das Portal schickt
Den Cluster abkoppeln oder löschen
Löschen ist die Aufgabe des Provisioners
Deine Snapshots öffnen
Mit dem Server-Token und den S3-Schlüsseln beim Portal
Es könnte nicht
Warum
Einen beliebigen Befehl auf deinem Server ausführen
pbx-agent hat eine feste Liste von Operationen und keinen Kanal für Befehle
Ein Release, das ich nicht signiert habe, oder eine Version von pbx-agent, die in keinem solchen Release steht, auf einem laufenden Node installieren
Der Release-Schlüssel liegt nicht auf dem Portal
/etc/rancher/k3s/k3s.yaml lesen, die Daten deiner Workloads, oder Snapshots in einem Bucket, dessen Schlüssel du selbst hältst
Das Portal bekommt sie nie
Ein Server, der angelegt wird, während das Portal kompromittiert ist, ist eine andere Sache: Er lädt den pbx-agent, der in seinen User Data steht, geprüft gegen eine Prüfsumme, die das Portal dort einträgt.
Eine fremde Maschine versucht, sich zu registrieren
Das Token gilt einmal, 30 Minuten lang, für einen Node-Namen; ID und Labels des Servers werden über die Hetzner-API geprüft; das gebootete Image wird geprüft
Ein Pod liest die Metadaten-Adresse
Er bekommt keine Antwort: Das Node-Image sperrt Pods davon aus
Auch ohne Sperre fände er nur ein benutztes oder abgelaufenes Token
Eine Anfrage wird wiederholt oder abgefangen
Wiederverwendung einer Anfrage, Preisgabe eines Geheimnisses
TLS, signierte Anfragen mit Zeitstempel, der Replay-Cache, versiegelte Geheimnisse
Ein API-Schlüssel wird geleakt In Arbeit
Wer ihn hat, handelt im Rahmen seiner Scopes, als sein Besitzer
Scopes, die Rolle des Besitzers im Team, eingetippte Namen und ein Team-Admin für zerstörende Aufrufe, Ratenlimits, das Audit-Log; widerrufe den Schlüssel auf der Seite der API-Schlüssel
Dein Konto wird übernommen
Der Angreifer benutzt das Portal als du
Eingetippte Bestätigungen, Mails an die Admins des Teams, kurze Laufzeiten der Kubeconfigs
Missbrauch durch mich
Operationen, die ich anstoße
Jede Operation zeigt, wer sie angefragt hat, Personal eingeschlossen; Wiederherstellungen und Kubeconfigs gehen per Mail an deine Admins
PaaSbox verschwindet
Das Portal und seine DNS-Zone sind weg
Der Cluster läuft weiter; du hast root, das Server-Token auf der Platte des Servers und die Snapshots in deinem Bucket; siehe Ohne PaaSbox weiterbetreiben
Getestet im Labor, dann auf meinen eigenen Clustern, dann auf dem Kanal early, bevor sie stable erreichen. Zwei Fehlschläge unter den ersten fünf Upgrades auf ein Release halten es an.
Mails an die Admins deines Teams
Wann immer eine Wiederherstellung oder eine Kubeconfig angefragt wird, mit der Person, die gefragt hat, Personal als solches gekennzeichnet. Fehlgeschlagene Upgrades, ausgefallene Snapshots, ablaufende Zertifikate und ein Cluster, der sich 24 Stunden nicht gemeldet hat, gehen ebenfalls per Mail raus.
Ein Name in deinem Cluster
Jede Kubeconfig ist ein ServiceAccount, benannt nach der Person, für die sie ausgestellt wurde, im Namespace pbx-access; ihre Aufrufe erreichen die Kubernetes-API unter diesem Namen. Ein Audit-Log von Kubernetes über diese Aufrufe führt der Node nicht.
Wer gefragt hat
Jede Operation zeigt, wer sie angefragt hat, meine eingeschlossen, auf dem Reiter Operations des Clusters.
Eingetippte Bestätigungen
Für eine Wiederherstellung, ein Abkoppeln und ein Löschen.
Kurze Laufzeiten
Kubeconfigs leben höchstens 24 Stunden.
Was du tun kannst
Die Cluster in einem eigenen Hetzner-Projekt halten, die Schlüssel des Buckets selbst halten, die Adressbereiche der API eingrenzen, jedem Agenten einen Schlüssel mit nur den Scopes geben, die er braucht, und den Bucket in einem Projekt oder bei einem Anbieter halten, den das Hetzner-Token nicht erreicht.
Ein weiterer Schutz ist eine Idee für eine spätere Version, weder gebaut noch eingeplant: deine Zustimmung, außerhalb des Portals, bevor eine Wiederherstellung oder eine Admin-Kubeconfig ausgestellt wird.
Läuft als root, weil eine Wiederherstellung k3s anhalten und wieder starten muss, während die Kubernetes-API nicht erreichbar ist. Er lauscht auf nichts.
Diagnose
Wird nur gesammelt, nachdem du es für diese eine Anfrage erlaubt hast; nie Secrets, Tokens oder Umgebungsdateien.
Secrets
k3s verschlüsselt Secrets im Ruhezustand.
Das Root-Dateisystem
Nur lesbar, Teil des Images, dessen Prüfsumme das signierte Release nennt.
Port 22
Von der Firewall geschlossen; das Image hat kein root-Passwort. Root auf dem Server bekommen zeigt die Wege hinein.