Zum Inhalt springen

Sicherheit

Envoryx ist ein Entwicklungswerkzeug für dein eigenes Netz und startet Container für dich über den Docker-Socket. Das ist eine Menge Macht - deshalb lohnt es sich zu wissen, wo die Grenzen liegen und worauf du achten solltest.

Envoryx läuft mit eingebundenem /var/run/docker.sock, und Zugriff auf diesen Socket ist im Grunde root auf dem Host. Ein Werkzeug, das Container anlegt, kommt darum nicht herum - also setzt Envoryx sich selbst Grenzen.

Container-Definitionen baut es nur aus einem festen Katalog, und der kann die gefährlichen Dinge gar nicht ausdrücken: keinen privilegierten Modus, keine zusätzlichen Capabilities, kein Host-Netzwerk, keinen Gerätezugriff, keine beliebigen Bind-Mounts. Container laufen mit no-new-privileges und ohne NET_RAW. Bevor Envoryx etwas ändert, prüft es das Label envoryx.managed=true am Ziel. Container, Netze und Volumes, die es nicht selbst angelegt hat, rührt es deshalb nie an - sie tauchen nur lesend auf der Seite Docker auf. Dasselbe gilt für alles, was ein anderes Envoryx auf dem Host angelegt hat: Dessen Label envoryx.instance nennt die andere Instanz, und diese hier lässt die Finger davon (mehrere Instanzen auf einem Host). Und die API nimmt überhaupt keine Container-IDs an: Sie spricht von Projekt + Dienst und sucht den Container auf dem Server selbst heraus, sodass niemand sie auf einen beliebigen Container richten kann.

Willst du das weiter eingrenzen, schalte einen Socket-Proxy wie tecnativa/docker-socket-proxy dazwischen und setz DOCKER_HOST=tcp://docker-socket-proxy:2375. Envoryx braucht die Gruppen CONTAINERS, IMAGES, NETWORKS, VOLUMES, EXEC, EVENTS, INFO, VERSION und POST, dazu BUILD, wenn du eigene Images aus einem Dockerfile im Projekt baust, und SYSTEM für die Volume-Größen im Ressourcenverlauf. SWARM, NODES, SECRETS, CONFIGS, PLUGINS und COMMIT können aus bleiben.

Ein Socket-Proxy filtert nach Endpunkt, nicht danach, was eine Anfrage verlangt. Sind CONTAINERS und POST offen, kann wer Envoryx kontrolliert weiterhin einen privilegierten Container anlegen. Der Proxy grenzt also ein, was ein Fehler erreicht, aber ein übernommenes Envoryx ist trotzdem root auf dem Host. Der eigentliche Schutz ist, Envoryx selbst abzuschirmen: HTTPS, nicht offen im Internet, und Konten nur für Leute, denen du die Container der Projekte anvertrauen würdest.

Passwörter werden mit argon2id gehasht und müssen mindestens 10 Zeichen lang sein. Eine Sitzung endet nach 12 Stunden ohne Aktivität und spätestens nach 7 Tagen (ENVORYX_SESSION_IDLE_TIMEOUT, ENVORYX_SESSION_ABSOLUTE_TIMEOUT). Lieferst du Envoryx über HTTPS aus, setz ENVORYX_SECURE_COOKIES=true - dann geht das Sitzungs-Cookie nie unverschlüsselt über die Leitung.

Fehlgeschlagene Anmeldungen bremst Envoryx pro Adresse und Benutzername, Passwörter raten wird also schnell mühsam. Änderst du dein Passwort, werden alle anderen Sitzungen beendet - praktisch, wenn du vermutest, dass irgendwo noch ein Browser angemeldet ist.

Ausgesperrt? Siehe Fehlerbehebung → Zugang verloren.

Ein Token (sie beginnen mit stq_) wird einmal angezeigt und danach nur noch als Hash gespeichert. Gib jedem Client einen eigenen Token mit dem kleinsten Scope, den er braucht, und beschränke ihn wo möglich auf Projekte - dann kann ein geleakter CI-Token nicht allzu viel anrichten. Tokens können keine weiteren Tokens anlegen, kein Passwort ändern, keine Benutzer verwalten und den Secret Key nicht anzeigen, und der MCP-Endpunkt nimmt nur Tokens an, nie ein Sitzungs-Cookie.

Der SSH-Server auf Port 2222 lässt niemanden in den Envoryx-Container oder auf den Host. Jede Sitzung ist ein docker exec in einen Projektcontainer, als Projektbesitzer. SFTP zeigt genau zwei Ordner: das Projekt und sein persistentes Home. Falsche oder unbekannte API-Tokens werden gezählt: Zehn innerhalb von zehn Minuten sperren die Adresse für fünf Minuten aus dem Projekt aus, 30 über alle Projekte sperren die ganze Adresse. Angebotene Schlüssel und das leere Passwort, das OpenSSH ohne Eingabeaufforderung schickt, zählen nicht, damit sich ein Team hinter einem NAT nicht aus Versehen selbst aussperrt. Die Einzelheiten stehen unter Ausgesperrt?.

Delve (Go), rdbg (Ruby) und JDWP (Java) haben überhaupt keine Authentifizierung: Wer den Port erreicht, kann beliebigen Code im Container ausführen. Xdebug, der Node-Inspector und debugpy sind nicht viel anders. Schalte einen Debug-Port also ein, während du debuggst, danach wieder aus - und nutze sie nicht auf einem Docker-Host, der aus Netzen erreichbar ist, denen du nicht traust.

In /config liegen die Datenbank (mit Projekt-Zugangsdaten und geheimen Variablen), die SSH-Schlüssel und die lokale CA. Beim CA-Schlüssel ist besondere Vorsicht angebracht: Er kann Zertifikate für jeden Namen signieren. Wer ihn hat, kann auf jedem Gerät, das deiner CA vertraut, Websites vortäuschen. Halte den Ordner privat und installiere die CA nur auf Geräten, die dir gehören. Hast du den Verdacht, dass der Schlüssel draußen ist, lösch /config/ca/ - Envoryx legt eine neue CA an, die du dann auf deinen Geräten neu installierst.

Auch Backups enthalten Zugangsdaten und Tokens. Geh mit einem heruntergeladenen Backup um wie mit einer Passwortdatei, und nutze die Verschlüsselung der Offsite-Backups.

Die Geheimnisse, die Envoryx speichert, liegen verschlüsselt: Git-Tokens, geheime Variablen, die Zugangsdaten der Dienste, das Client-Secret für Single Sign-on, Registry-Logins sowie die Einstellungen für Benachrichtigungen, Offsite-Backups und ACME. Den Schlüssel dafür nimmt Envoryx aus ENVORYX_SECRET_KEY am Container oder, ohne die Variable, aus /config/secret.key, die es beim ersten Start anlegt. Die Variable ist der bessere Ort, denn dann enthält eine Kopie von /config (ein Appdata-Backup, ein gestohlenes Plattenabbild) nur verschlüsselte Geheimnisse. openssl rand -base64 32 erzeugt einen passenden Schlüssel, und für den Wechsel von der Datei zur Variable brauchst du sonst nichts: Beim nächsten Start verschlüsselt Envoryx alles mit dem neuen Schlüssel und löscht die Datei.

Einstellungen → Secret Key zeigt die ID des Schlüssels und woher er kommt. Schlüssel anzeigen zeigt den Schlüssel selbst, und das Audit-Log hält fest, dass du ihn angesehen hast. Leg dir eine Kopie außerhalb von Envoryx ab. In Instanz-Backups steckt der Schlüssel nie, ohne diese Kopie kannst du eines also nicht auf einem anderen Host wiederherstellen. Mit der Schlüsseldatei erzeugt Schlüssel ersetzen einen neuen und verschlüsselt alles neu; mit der Variable trägst du dort den neuen Schlüssel ein und den bisherigen für einen Start als ENVORYX_SECRET_KEY_OLD. Deine lokalen Projekt-Backups verschlüsselt Envoryx dabei mit um, aber Instanz-Backups von vorher und die Kopien von Projekt-Backups, die schon auf Offsite-Zielen liegen, brauchen weiterhin den alten Schlüssel. Heb ihn also auf, solange du eins davon noch einspielen könntest. Fehlt einer Wiederherstellung der Schlüssel, nennt sie dir seine ID. Beide Wege, den Schlüssel zu ersetzen, landen im Audit-Log (settings.secret_key_rotated).

Anzeigen und Ersetzen verlangen die Browser-Sitzung eines Admins. API-Tokens werden abgewiesen, auch mit Scope admin - ein geleakter Token soll nicht mit dem Schlüssel zu allen gespeicherten Geheimnissen davonspazieren können.

Eine Freigabe macht ein Projekt ohne jede Anmeldung aus dem Internet erreichbar. Steckt darin etwas, das nicht jeder sehen soll, leg in den Regeln des Projekts ein Passwort drauf - oder teile eine Staging-Kopie statt des echten Projekts.

Projektcontainer erreichen die Ports von Envoryx im Projektnetz, genau wie jedes andere Gerät in deinem LAN. Code, den du in einem Projekt ausführst, vertraust du ungefähr so weit wie Code auf deinem eigenen Rechner - geh mit fremden Repositories also genauso vorsichtig um.