Zum Hauptinhalt springen

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
Wichtig

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.

Wichtig

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.

Anmerkung

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.

Resultat

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.

Fazit

Die Integration ist damit als technische Grundlage für die zukünftige Paket-Analyse im NDM-System eingerichtet.