146 lines
8.2 KiB
Markdown
146 lines
8.2 KiB
Markdown
# Architektur und Vertrauensgrenzen
|
|
|
|
## Komponenten
|
|
|
|
```text
|
|
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
|
|
|
|
1. Eine Quelle wird serverseitig konfiguriert; Tokens werden über Umgebungsvariablen referenziert und nicht als Katalogdaten gespeichert.
|
|
2. Der Provider-Adapter listet Repositories und Releases. Netzwerkzugriffe sind auf HTTPS und eine explizite Hostliste begrenzt. Private/reservierte Adressen sind standardmäßig gesperrt.
|
|
3. Vor dem Lesen von README oder Packaging-Metadaten wird ein Commit-SHA festgehalten. Relative README-Ressourcen werden an diesen Stand gebunden.
|
|
4. Kandidaten werden aus Topic, `pyproject.toml`/vergleichbarer Packaging-Konfiguration und der NetBox-`PluginConfig` erkannt. Fehlende oder widersprüchliche Installationsfelder verhindern eine Freigabe.
|
|
5. Externes Markdown wird in HTML umgewandelt und sanitisiert. Unsichere Schemata und nicht erlaubtes HTML werden nicht in die Store-Seite übernommen.
|
|
6. 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:
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
|
|
```json
|
|
{
|
|
"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
|
|
|
|
1. Ein berechtigter NetBox-Benutzer wählt eine Aktion; echte Mutationen erfordern zusätzlich Superuser-Rechte, CSRF-Prüfung und die Eingabe des exakten Slugs.
|
|
2. Das NetBox-Plugin liest den freigegebenen Katalog und sendet nur Aktion, Slug, Version, Actor/Request-ID und Store-Freigabemarker an den Unix-Socket.
|
|
3. Der Agent akzeptiert den Auftrag idempotent und speichert seinen Zustand in SQLite. NetBox wartet nicht auf einen möglichen eigenen Neustart.
|
|
4. Der Agent ruft Plugin und Release selbst erneut aus dem Store ab. Er vertraut nicht allein auf die vom Webprozess gelieferten Metadaten.
|
|
5. Er erzwingt Host-/DNS-Regeln, NetBox-Version, Wheel-Dateiname, Paket-/Importname, Dateigröße, Artifact-SHA-256 und den exakten Freigabemarker.
|
|
6. Host-Änderungen laufen serialisiert unter einem globalen Lock. Installationen bleiben zunächst deaktiviert; Aktivierung ist eine eigene Aktion.
|
|
7. 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.
|