OpenSandbox auf dem NDM-Server
Übersicht
OpenSandbox wird auf dem NDM-Server als eigener Docker-Service betrieben. Die Anwendung stellt eine API bereit, über die das NDM-Backend isolierte Sandboxes für Paketanalysen und das Ausführen von Code erstellen kann.
Die grundlegende Architektur sieht so aus:
NDM Backend
│
│ OpenSandbox SDK / API
▼
ndm-opensandbox
│
│ Sandbox Runtime
▼
isolierte Sandbox
OpenSandbox läuft dabei nicht direkt im Backend-Container, sondern als eigener Service. Dadurch bleiben Backend und Sandbox-Infrastruktur voneinander getrennt.
Docker-Setup
Der OpenSandbox-Service wird über Docker Compose gestartet. Verwendet wird das offizielle OpenSandbox-Server-Image:
opensandbox:
image: opensandbox/server:latest
container_name: ndm-opensandbox
ports:
- "8090:8090"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
extra_hosts:
- "host.docker.internal:host-gateway"
Der Docker-Socket wird benötigt, damit OpenSandbox Sandbox-Container verwalten kann.
host.docker.internal wird über host-gateway verfügbar gemacht, damit der Container bei Bedarf den Docker-Host erreichen kann.
Die OpenSandbox-Konfiguration wird zusätzlich über eine Konfigurationsdatei in den Container eingebunden. Der Pfad wird über SANDBOX_CONFIG_PATH angegeben.
Kommunikation mit dem Backend
Das Backend verwendet das OpenSandbox Python SDK.
Da sich Backend und OpenSandbox im Docker-Netzwerk befinden, wird OpenSandbox intern über den Compose-Service-Namen angesprochen:
opensandbox:8090
Für die Authentifizierung wird ein API-Key verwendet, der als Umgebungsvariable an den OpenSandbox-Service und das Backend übergeben wird.
Die interne Docker-Adresse wird nur innerhalb des Docker-Netzwerks verwendet. Sie muss nicht über Caddy oder eine öffentliche Domain erreichbar sein.
Warum ein eigener Container?
OpenSandbox wurde bewusst als eigener Service aufgesetzt.
Dadurch:
- bleibt das Django-Backend vom Sandbox-System getrennt,
- kann OpenSandbox unabhängig neu gestartet oder aktualisiert werden,
- können Sandbox-Ressourcen getrennt vom Backend verwaltet werden,
- muss das Backend selbst keine Sandbox-Container verwalten,
- kann die Sandbox-Infrastruktur später leichter erweitert oder ausgetauscht werden.
Das Backend übernimmt damit hauptsächlich die fachliche Logik, während OpenSandbox für das Erstellen und Verwalten der isolierten Ausführungsumgebung zuständig ist.
Sandbox-Test
Für den ersten Proof of Concept wurde aus dem Backend eine Sandbox erstellt und darin Code ausgeführt.
Der Ablauf ist vereinfacht:
Backend
↓
Sandbox.create(...)
↓
OpenSandbox Server
↓
isolierte Sandbox
↓
Code ausführen
↓
Output / Fehler an Backend
↓
Sandbox.destroy()
Die Sandbox wird nach der Analyse wieder zerstört. Dadurch bleibt die Ausführungsumgebung nicht dauerhaft bestehen.
Im weiteren Verlauf wurde der PoC von einem einfachen echo-Test auf die Ausführung von JavaScript mit Node.js erweitert. Dafür kann beispielsweise ein Node-Alpine-Image als Sandbox-Umgebung verwendet werden.
gVisor
Für die eigentliche Sandbox-Isolation soll gVisor (runsc) verwendet werden.
Die Idee ist:
OpenSandbox
↓
Sandbox Runtime
↓
gVisor / runsc
↓
Sandbox-Prozess
Damit soll der ausgeführte Code stärker vom normalen Docker-Host isoliert werden, als dies bei einer normalen Docker-Runtime der Fall wäre.
Firecracker wurde für diesen Aufbau nicht weiterverfolgt, da es für den vorgesehenen OpenSandbox-Einsatz nicht die passende Runtime-Lösung darstellt.
Health Check
Für die Überwachung wurde zunächst geprüft, ob OpenSandbox über einen eigenen HTTP-Endpunkt erreichbar ist.
Dabei wurde festgestellt, dass ein angenommener Endpunkt wie
http://opensandbox:8090/health
nicht automatisch garantiert ist.
Der Health Check muss daher auf einen tatsächlich von der eingesetzten OpenSandbox-Version bereitgestellten Endpunkt bzw. auf eine geeignete API-Anfrage abgestimmt werden.
Aktueller Stand
Auf dem NDM-Server läuft OpenSandbox als:
ndm-opensandbox
und lauscht auf Port:
8090
Das NDM-Backend kann über das interne Docker-Netzwerk mit OpenSandbox kommunizieren und über das Python SDK Sandboxes erstellen, Code ausführen und die Sandboxes anschließend wieder entfernen.
Die Integration ist damit als technische Grundlage für die zukünftige Paket-Analyse im NDM-System eingerichtet.