8.2 KiB
Architektur und Vertrauensgrenzen
Komponenten
Forgejo / GitHub
|
| HTTPS, fest erlaubte Hosts, commit-gebundene Metadaten
v
+-----------------------+ JSON-Datei oder MariaDB
| PHP Store auf Apache |------------------------------+
| Sync + Admin + API v1 | |
+-----------------------+ |
| freigegebener Katalog |
v |
+-----------------------+ Unix-Socket +--------------------------+
| NetBox Store Plugin |--------------->| privilegierter Host-Agent|
| unprivilegierte UI | | erneute Prüfung + Lifecycle|
+-----------------------+ +--------------------------+
|
v
NetBox-Virtualenv, Konfiguration,
Migrationen, Static Files, Dienste
Der Store ist eine eigenständige PHP-Anwendung. Apache liefert HTML, Assets und API direkt aus. NetBox benötigt keinen Zugriff auf die Store-Datenbank, und der Store erhält keinen Schreibzugriff auf einen NetBox-Host.
Zustandsmodell
Der persistierte Zustand enthält mindestens diese fachlichen Ebenen:
- Source: Provider, API-/Basis-URL, Owner/Organisation und Synchronisierungsstatus.
- Plugin: Anzeige- und Installationsmetadaten, Repository, README-Snapshot, Paket-/Importname und NetBox-Kompatibilität.
- Release: Version, Download-URL, SHA-256, Größe, Commit und Kompatibilität. Da ein Upstream-Asset trotz gleicher URL ersetzt werden kann, wird es bei jedem erfolgreichen Sync erneut gehasht.
- Audit/Admin-Zustand: Freigaben, Ablehnungen und sicherheitsrelevante Änderungen.
Die JSON-Implementierung speichert denselben logischen Zustand wie der MariaDB-Adapter. Sie ist für eine einzelne Store-Instanz gedacht und schützt Schreibvorgänge mit Sperre und atomischem Austausch. MariaDB erlaubt einen extern verwalteten, transaktionalen Persistenzdienst. Ein gleichzeitiger Wechsel zwischen beiden Treibern ist kein Replikationsmechanismus.
Import-Pipeline
- Eine Quelle wird serverseitig konfiguriert; Tokens werden über Umgebungsvariablen referenziert und nicht als Katalogdaten gespeichert.
- Der Provider-Adapter listet Repositories und Releases. Netzwerkzugriffe sind auf HTTPS und eine explizite Hostliste begrenzt. Private/reservierte Adressen sind standardmäßig gesperrt.
- Vor dem Lesen von README oder Packaging-Metadaten wird ein Commit-SHA festgehalten. Relative README-Ressourcen werden an diesen Stand gebunden.
- Kandidaten werden aus Topic,
pyproject.toml/vergleichbarer Packaging-Konfiguration und der NetBox-PluginConfigerkannt. Fehlende oder widersprüchliche Installationsfelder verhindern eine Freigabe. - Externes Markdown wird in HTML umgewandelt und sanitisiert. Unsichere Schemata und nicht erlaubtes HTML werden nicht in die Store-Seite übernommen.
- Neue Datensätze oder installrelevante Änderungen landen wieder im Freigabezustand
pending.
GitHub verwendet dasselbe interne Source-/Plugin-/Release-Modell. Provider-spezifisch bleiben nur Authentifizierung, Pagination und API-Formate.
Freigabegatter
Source, Plugin und Release werden getrennt bewertet. Ein Plugin darf auch ohne installierbares Release sichtbar sein; dann liefert die API releases: [] und latest_version: null. Für einen sichtbaren Plugin-Eintrag gelten:
- Quelle und Plugin sind aktiv und freigegeben.
- Das Plugin besitzt vollständige Paket-, Import- und Kompatibilitätsdaten.
Ein Release wird diesem Plugin nur dann öffentlich beigefügt, wenn zusätzlich gilt:
- Das Release ist freigegeben und als unveränderlich markiert.
- Artifact-URL, SHA-256 und positive Dateigröße sind vorhanden.
- Die gespeicherte Freigabemarkierung gehört exakt zum aktuell freigegebenen Payload.
Die Freigabemarkierung heißt aus Protokollkompatibilitätsgründen approved_payload_sha256. Clients behandeln den 64-stelligen Hexwert als opaken Store-Marker. Er ersetzt nicht den separaten SHA-256 der heruntergeladenen Artifact-Datei.
API-Vertrag
GET /api/v1/plugins/ liefert eine paginierte Antwort:
{
"api_version": "v1",
"count": 1,
"page": 1,
"page_size": 50,
"next": null,
"previous": null,
"results": []
}
GET /api/v1/plugins/{slug}/ liefert das Plugin direkt. Sein Kernschema ist:
{
"api_version": "v1",
"slug": "netbox-example",
"name": "Example",
"summary": "Example plugin",
"description": "Description",
"repository_url": "https://git.example/repo",
"latest_version": "1.2.3",
"package_name": "netbox-example",
"import_name": "netbox_example",
"min_netbox_version": "4.6.5",
"max_netbox_version": "4.6.8",
"approved": true,
"status": "approved",
"releases": []
}
GET /api/v1/plugins/{slug}/releases/{version}/ liefert ein Release direkt:
{
"version": "1.2.3",
"download_url": "https://artifacts.example/netbox_example-1.2.3-py3-none-any.whl",
"sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"artifact_size": 12345,
"commit_sha": "",
"min_netbox_version": "4.6.5",
"max_netbox_version": "4.6.8",
"published_at": "2026-08-24T12:00:00Z",
"approved": true,
"status": "approved",
"immutable": true,
"approved_payload_sha256": "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"
}
Unbekannte, nicht freigegebene und unvollständige Datensätze werden gegenüber öffentlichen Clients nicht wie installierbare Einträge behandelt.
Lifecycle-Sequenz
- Ein berechtigter NetBox-Benutzer wählt eine Aktion; echte Mutationen erfordern zusätzlich Superuser-Rechte, CSRF-Prüfung und die Eingabe des exakten Slugs.
- Das NetBox-Plugin liest den freigegebenen Katalog und sendet nur Aktion, Slug, Version, Actor/Request-ID und Store-Freigabemarker an den Unix-Socket.
- Der Agent akzeptiert den Auftrag idempotent und speichert seinen Zustand in SQLite. NetBox wartet nicht auf einen möglichen eigenen Neustart.
- Der Agent ruft Plugin und Release selbst erneut aus dem Store ab. Er vertraut nicht allein auf die vom Webprozess gelieferten Metadaten.
- Er erzwingt Host-/DNS-Regeln, NetBox-Version, Wheel-Dateiname, Paket-/Importname, Dateigröße, Artifact-SHA-256 und den exakten Freigabemarker.
- Host-Änderungen laufen serialisiert unter einem globalen Lock. Installationen bleiben zunächst deaktiviert; Aktivierung ist eine eigene Aktion.
- Der Audit-Eintrag in NetBox fragt den Agent-Status später ab und gleicht Erfolg, Fehler oder manuell zu bereinigenden Zustand ab.
Sicherheitsgrenzen
- Admin-Zugangsdaten existieren nicht als Standardwerte. Alle drei Credential-Variablen müssen gemeinsam gesetzt sein.
- Admin-Aktionen verwenden serverseitige Sessions mit geschütztem Cookie, HMAC-gebundene CSRF-Tokens und Login-Ratenbegrenzung.
- Source-Tokens dürfen nur an ihren konfigurierten Ursprung gesendet werden. Artifact-Hosts erhalten keine Store-Zugangsdaten.
- Der öffentliche Store-Prozess ist nicht privilegiert gegenüber NetBox. Nur der separate, root-konfigurierte Agent darf die Virtualenv, verwaltete Include-/Requirements-Dateien und Dienste verändern.
- Der Unix-Socket benötigt Dateisystemrechte und Linux-Peer-Credential-Prüfung. Die NetBox-Service-UID oder -GID muss explizit erlaubt sein.
- Der Agent startet mit
dry_run = true, blockiert Selbstverwaltung und verwendet feste Argumentlisten statt Shell-Kommandos. - Das aktuelle Verfahren ist kein vollständiges Supply-Chain-Framework. Artifact-Build-Provenienz, Signierung, Abhängigkeitsbereitstellung und Recovery nach bereits angewandten Migrationen bleiben Betreiberaufgaben.
Betriebsgrenzen
Der JSON-Treiber ist für genau eine Store-Installation auf einem lokalen Dateisystem ausgelegt. Apache-Worker und der lokale Scheduler koordinieren sich dabei über die Dateisperre. Bei mehreren Hosts/Replikaten ist MariaDB zu verwenden, und Scheduler/Sync müssen so betrieben werden, dass nicht mehrere Instanzen dieselbe Quelle gleichzeitig bearbeiten. Store-Daten, Agent-Journal, Backups, Konfiguration und Token-Dateien gehören in die reguläre Backup- und Restore-Planung.