diff --git a/README.md b/README.md index 49ac17c..96f225d 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,57 @@ -# vuln-builder — modular (CVE / NVD / OSV) +# Vulnerability SQLite Builder – Schema v3 -**Ziel:** Bestehenden SQLite-Builder ohne Datenverlust modularisieren. Ein einzelner Gitea-Runner und ein einzelner Builder-Workflow reichen aus. Das SQL-Schema (v1), Delta-JSONL-Struktur und die Release-Dateinamen bleiben kompatibel zum bisherigen Builder. Die bereits vorhandenen 330-MB-Masterdateien werden **nicht** mitgeliefert. +**Basis:** bereitgestellte `build.py` und bestehendes modulares Builder-Projekt. Das Paket enthält einen vollständigen Satz aus `scripts/build.py`, `scripts/sync_sources.py`, `scripts/run.sh`, `importers/`, `sql/schema.sql`, Tests und einem Workflow-Beispiel. Die vorhandene produktive `.gitea/workflows/build.yml` wird durch die Datei `.example` nicht ersetzt. -## Dateien +## Was Version 3 kann -```text -vuln-builder/ -├── importers/ -│ ├── __init__.py # zentrale Registrierung -│ ├── common.py # Datenbank- und ID-Helfer -│ ├── cve.py # CVEProject V5 -│ ├── nvd.py # NVD-CVE direkt / Wrapper, einfache CPE-OR-Regeln -│ └── osv.py # OSV-Aliasse und betroffene Pakete -├── scripts/ -│ ├── sync_sources.py # bisheriger Gitea-Repo-Cache (übernommen) -│ ├── build.py # Master + Delta + No-Change-Build -│ └── run.sh # Synchronisierung und Build mit flock -├── sql/schema.sql # bestehendes Tabellenlayout (v1) -├── tests/test_builder.py -└── .gitea/workflows/build.yml.example +- CVEProject, NVD, OSV und Red Hat CSAF indexieren; 12 weitere angebundene Repositories werden als `unsupported` in `sources` dokumentiert. +- NVD-CPE-Bedingungsbäume in `cpe_nodes` und `cpe_matches.node_id` **verlustfrei hinsichtlich AND/OR/negate-Baumstruktur** erfassen. Die CPE-Matches sind nicht als voneinander unabhängige Treffer zu interpretieren. +- Red Hat CSAF Advisory-IDs, CVE-Zuordnungen, Produktbäume, Produktstatus und Remediations erhalten (JSON). +- `sources` liefert `revision`, `indexed`, `documents`, `last_sync`, `last_import`, `import_status`, `import_errors`. +- `source-manifest.json` enthält nach erfolgreicher Synchronisierung pro Repo `synced_at`. `last_sync` enthält den Zeitstempel aus diesem Manifest, falls die Revision passt. Bei fehlendem oder altem Manifest bleibt das Feld `NULL`. +- `last_import` wird nur bei einem neu erzeugten Master für erfolgreich indexierte Quellen aktualisiert. Bei `NO_CHANGES` wird die Datenbank **absichtlich nicht neu geschrieben**; für die jüngste Synchronisierung siehe die JSON-Datei `source-manifest.json`. +- Die neue SQLite-Datenbank hat Schema-Version 3. Bei Umstellung von Version 1 oder 2 wird **kein inkompatibles Delta** angeboten; ein neuer Master ist notwendig. +- Schema-3-Deltas enthalten auch `sources`, `meta`, `cpe_nodes` und die beiden Red-Hat-Tabellen. Ein Delta muss **vollständig in einer Transaktion** mit `PRAGMA defer_foreign_keys=ON` angewandt werden. Das Update-Protokoll im Scanner muss diese Tabellen sowie das Schema kennen. + +## Workflow / persistenter Cache + +Die vorhandene Workflow-Datei soll den **im Job-Container** eingebundenen Pfad verwenden: + +```yaml +env: + CACHE_ROOT: /vuln-cache/vuln-builder + SOURCE_READ_TOKEN: ${{ secrets.GITEA_TOKEN }} ``` -## Produktiv übernehmen +Mit deinem Docker-Runner `-v /opt/gitea-builder/cache:/vuln-cache` bedeutet das auf dem Docker-Host: +`/opt/gitea-builder/cache/vuln-builder/releases/`. -1. Zuerst das bestehende `vuln-builder`-Repository **sichern**. `master.db`, `master.db.zst`, alle historischen Delta-Dateien und `manifest.json` an sicherer Stelle sichern. -2. Die vorhandenen Ordner `scripts/` und `sql/` nicht blind ersetzen: vorhandene eigene Workflow-/Script-Anpassungen vergleichen. Dieses Paket enthält die vollständigen drei vorhandenen Importer, den geposteten `sync_sources.py`, ein kompatibles SQL-Schema und ein Ausführungsskript. -3. Dateien nach `VULN/vuln-builder` kopieren, committen, nach `main` pushen. -4. Auf der Gitea-VM prüfen: `git`, `python3` (>= 3.9), `zstd`, `flock`, sowie Zugriff des Runner-Users auf `/opt/gitea-builder/cache/vuln-builder`. -5. Im **bereits vorhandenen** Builder-Workflow die eigentliche Build-Ausführung durch `bash scripts/run.sh` ersetzen; nicht gleichzeitig den Beispiel-Workflow aktivieren. Das Beispiel liegt absichtlich als `.example` vor. -6. Gitea Actions einmal manuell ausführen und `manifest.json` sowie `sources`-Tabelle prüfen. +Die Runner-Konfiguration selbst muss den Docker-Host-Pfad als Quellverzeichnis mounten (siehe bestehende Konfiguration). -## Lokaler Aufruf ohne Git-Synchronisierung +Manueller Build im Job-Container: ```bash -python3 scripts/build.py \ - --sources /opt/gitea-builder/cache/vuln-builder/sources \ - --output /opt/gitea-builder/cache/vuln-builder/releases +export CACHE_ROOT=/vuln-cache/vuln-builder +bash scripts/run.sh ``` -Mit Synchronisierung, bestehender `sources.json` aus `VULN/vuln-status` und Sperre: +Testlauf, wenn `zstd` und `git` verfügbar sind: ```bash -CACHE_ROOT=/opt/gitea-builder/cache/vuln-builder bash scripts/run.sh +python3 -m unittest discover -s tests -v ``` -`SOURCE_READ_TOKEN` ist nur nötig, wenn die `sources.json` Authentifizierung verlangt. Das Originalskript setzt für private Git-Klone vorhandene Git-Credentials auf dem Host voraus; es übergibt `SOURCE_READ_TOKEN` **nicht** automatisch an Git. Bei bestehenden funktionierenden Checkouts brauchst du daran nichts zu ändern. +Datenbank prüfen: -## No-Change und Delta +```bash +sqlite3 /opt/gitea-builder/cache/vuln-builder/releases/master.db \ + 'SELECT name,indexed,documents,last_sync,last_import,import_status FROM sources ORDER BY name;' +``` -- Signatur über **alle Git-Quellrevisionen**, Python-Builder- und Importerdateien und Schema. -- Wenn Signatur gleich und Master-Zstd-SHA stimmt: `NO_CHANGES`, keine neue Version. -- Im ersten Lauf mit dieser modularen Version wird vollständig neu gebaut, weil die Signatur anders ist. -- Bei verändertem Input schreibt der Builder `master.db`, `master.db.zst`, `manifest.json` und `delta--to-.jsonl.zst`. -- Historische Deltas werden nicht absichtlich gelöscht. Das Paket implementiert **keinen** automatischen Release-Uploader und **keinen** Delta-Client. +## Sicherheits- und Funktionsgrenzen -## Status anderer Quellen - -Alle von `sync_sources.py` gelesenen Repositories werden weiterhin als Git-Checkouts synchronisiert. **Nur** `vuln-cve`, `vuln-nvd`, `vuln-osv` besitzen Importer. Die anderen erhalten in der Tabelle `sources` `indexed=0`, `documents=0`. Ein zusätzlicher Importer wird als `importers/.py` angelegt und in `importers/__init__.py` registriert. - -## Sicherheits- und Kompatibilitätshinweise - -- Der NVD-Importer unterstützt direkt gespeicherte NVD-JSON-Datensätze und API-Wrapper `{ "cve": {...} }`. -- CVE-/OSV-Importer entsprechen dem konservativen v1-Ansatz und interpretieren keine komplexen Produkt-/Versionsbedingungen. -- **NVD AND/NOT-Konfigurationen werden nicht als unabhängige Matches abgelegt**. Der neue Parser lässt zusätzlich gesamte komplexe Konfigurationen weg, statt nur problematische Unterzweige herauszufiltern. Dadurch können CPE-Zahlen gegenüber früheren Builds sinken. Solche Fälle benötigen später eine eigene CPE-Bedingungsbaum-Tabelle. -- Die aktuelle v1-Speicherung ist **kein vollständig zuverlässiger Schwachstellenscanner**. Insbesondere fehlen präzise NVD-Bedingungsbäume und herstellerspezifische Importer. -- Ein fehlgeschlagener Parser unterbricht den Release-Build. Der letzte veröffentlichte Master bleibt erhalten, sofern die Fehler vor der finalen Veröffentlichung auftreten. -- Release-Manifest wird als Letztes ersetzt. Die eigentlichen Release-Dateien werden nacheinander ersetzt; für externe Downloader sind unveränderliche Release-Verzeichnisse sinnvoll. +- Nicht als vollständig implementierter Vulnerability-Matcher verwenden: OSV-GIT-Ranges, Produktbeziehungen und NVD-Baum-Auswertung müssen vom Scanner semantisch korrekt interpretiert werden. +- `import_status=unsupported` bedeutet **kein Importer vorhanden**, nicht „keine Schwachstellen“. +- Importfehler brechen die Veröffentlichung ab; deshalb erscheint `failed` nicht in einer erfolgreich veröffentlichten Master-DB. Das Fehlerprotokoll steht im Actions-Log. +- Der `schema.sql`-Satz ist für den **Neuaufbau** gedacht. Auf eine bereits vorhandene SQLite-Datei aufgerufen, führen `CREATE TABLE IF NOT EXISTS` keine Spaltenmigration durch. Vorhandene Master werden vom Builder separat aufgebaut und erst nach Erfolg ersetzt. +- Aufbewahrung alter `delta-*.zst` Dateien ist unverändert. Scanner müssen die aus `manifest.json` bestätigte Version verwenden.