docs: mark milestone M6 as complete, update project log
ci / Web (lint, test, audit, build) (push) Successful in 2m5s
ci / Shell and licence headers (push) Successful in 22s
ci / Release build (dry run) (push) Successful in 3m53s
ci / End-to-end (server, agents, BIND, Kea) (push) Successful in 3m38s
ci / Development environment (compose) (push) Successful in 18s
ci / Integration (real BIND and Kea) (push) Successful in 2m27s
install / Installation (debian:12) (push) Successful in 6m1s
install / Installation (debian:13) (push) Successful in 6m58s
install / Installation (ubuntu:22.04) (push) Successful in 6m47s
ci / Protobuf (push) Successful in 1m19s
ci / Go (lint, test, vuln) (push) Successful in 6m1s
install / Installation (rocky:9) (push) Successful in 10m12s
install / Installation (ubuntu:24.04) (push) Successful in 6m50s
release / release (push) Successful in 3m58s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sir_melonchen
2026-10-16 01:14:17 +02:00
co-authored by Claude Opus 5.5
parent a956fc84a1
commit 533082dae2
2 changed files with 38 additions and 23 deletions
+3 -2
View File
@@ -13,9 +13,10 @@ Selbst gehostete DDI-Lösung (DNS, DHCP, IP-Adressverwaltung) im Stil von VitalQ
| M2 Config-Generator (BIND/Kea aus dem Datenmodell, geprüft mit echtem BIND 9.18/9.20 und Kea 2.6/3.2) | abgeschlossen (`v0.3.0`) |
| M3 Agent verwaltet (Registrierung, mTLS, signierte Revisionen, Anwenden mit Prüfung/Health-Check/Rollback, Leases; End-to-End-Test mit BIND und Kea) | abgeschlossen (`v0.4.0`) |
| M4 Pull und Push (Betriebsmodi, „Jetzt ausrollen“, offene Änderungen, Diff, Rollback, Live-Status) | abgeschlossen (`v0.5.0`) |
| M5–M6 | geplant, siehe [ARCHITECTURE.md](docs/ARCHITECTURE.md#11-meilensteine) |
| M5 Cluster und Zonen (DNS-Primary/Secondary mit TSIG, Kea-HA, Zonen und Records, dynamische Zonen, Lease-Übernahme) | abgeschlossen (`v0.6.0`) |
| M6 Auslieferung (Installer für Debian/Ubuntu/EL9, gehärtete systemd-Units, Pakete, Release-Signatur, Messungen, Betriebs- und Sicherheitsdoku) | abgeschlossen (`v0.7.0`) |
Der Management-Server verwaltet Netze und Adressen (QIP-artige Tabelle), Benutzer, Lizenz und Audit-Log. Aus den Daten erzeugt er die BIND- und Kea-Konfiguration als unveränderliche Revisionen (**Ausrollen**). Die Agents (`ddi-agent-dns`, `ddi-agent-dhcp`) registrieren sich mit einem Einmal-Token, holen die signierten Revisionen über mTLS, prüfen und aktivieren sie, rollen bei Fehlern zurück und melden Zustand und Leases (**Agents**, **Leases**).
Installation: [docs/INSTALL.md](docs/INSTALL.md). Der Management-Server verwaltet Netze und Adressen (QIP-artige Tabelle), Zonen und Records, DNS- und DHCP-Cluster, Benutzer, Lizenz und Audit-Log. Aus den Daten erzeugt er die BIND- und Kea-Konfiguration als unveränderliche Revisionen (**Ausrollen**). Die Agents (`ddi-agent-dns`, `ddi-agent-dhcp`) registrieren sich mit einem Einmal-Token, holen die signierten Revisionen über mTLS, prüfen und aktivieren sie, rollen bei Fehlern zurück und melden Zustand und Leases (**Agents**, **Leases**).
## Dokumentation
+35 -21
View File
@@ -6,7 +6,7 @@ Neue Einträge oben im Abschnitt „Verlauf“ ergänzen und den Abschnitt „St
---
## Stand (2026-10-14, nach M5)
## Stand (2026-10-16, nach M6)
| Meilenstein | Status | Tag |
| --- | --- | --- |
@@ -16,32 +16,37 @@ Neue Einträge oben im Abschnitt „Verlauf“ ergänzen und den Abschnitt „St
| M3 Agent verwaltet | fertig, CI grün | `v0.4.0` |
| M4 Pull und Push | fertig, CI grün | `v0.5.0` |
| M5 Cluster und Zonen | fertig, CI grün | `v0.6.0` |
| M6 Auslieferung | **als Nächstes** | – |
| M6 Auslieferung | fertig, CI grün | `v0.7.0` |
| M7 (Standalone, DHCPv6, DNSSEC, Discovery) | nur Schnittstellen vorbereitet (Brief §12) | – |
Branch `main`, alles gepusht nach `https://git.beugsiud.de/beug.k/DDI`. Release `v0.1.0` mit Artefakten auf Gitea veröffentlicht; `v0.2.0` ebenso über den Release-Workflow.
Branch `main`, alles gepusht nach `https://git.beugsiud.de/beug.k/DDI`. Releases mit Artefakten über den Release-Workflow.
### Nächster Schritt: M6 (Auslieferung)
### Nächster Schritt: Abnahme auf echten Maschinen (Brief §14)
Laut Brief: `install.sh`, Release-Build, optional Pakete, `SYSTEM-REQUIREMENTS.md` mit Messungen, `OPERATIONS.md`, `SECURITY.md`, Härtung, End-to-End-Test der Installation in sauberen VMs/Containern (Debian, Ubuntu, Rocky). Der Installer muss dabei einrichten, was bisher nur Entwicklungsumgebung und End-to-End-Test vorgeben: `named.conf` mit `ddi-suite-keys.conf` vor `ddi-suite.conf` und dem Optionen-Include, Zonenverzeichnis unter `/var/lib/bind` (schreibbar für `named`, inkl. `secondary/`), Kea-Pfade (Konfiguration, Socket-Verzeichnis 0750, Lease-Datei, HA-Benutzer- und Passwortdatei lesbar für den Kea-Benutzer), Generator-Einstellungen passend zur Agent-Konfiguration (Punkte 9–10 unten).
M0–M6 sind umgesetzt. Was die CI nicht abdecken kann, steht noch aus:
1. **Release-Signatur einrichten** (nur du): Schlüsselpaar erzeugen, Secret `RELEASE_SIGNING_KEY` in Gitea setzen und den öffentlichen Schlüssel in `scripts/install.sh` (`RELEASE_PUBLIC_KEY_PEM`) eintragen – Anleitung in [RELEASE.md](RELEASE.md). Bis dahin prüft der Installer nur `SHA256SUMS` und warnt.
2. **Abnahme nach Brief §14** auf drei VMs (Debian 12 Server, je eine VM für DNS- und DHCP-Agent): Installation nach [INSTALL.md](INSTALL.md), echter Keygen-Lizenzschlüssel (Punkt 1 unten), Oberfläche im Browser durchklicken (Punkt 2), DHCP mit echtem Client (Lease → Adresstabelle → `manual_dhcp`), Lizenz sperren/Keygen unerreichbar (Lesemodus nach Karenzzeit, DNS/DHCP laufen weiter).
3. Danach bewusst entscheiden, welche offenen Punkte vor einem `v1.0.0` nötig sind (z. B. HA mit TLS, Kea-DDNS, Neuverschlüsselung beim Master-Key-Wechsel).
### Offene Punkte
1. **Keygen live geprüft (2026-10-13), aber noch nicht mit dem Go-Code selbst.** Mit einem zweiten, eigens dafür bereitgestellten Schlüssel (nur in der Umgebung, nirgends gespeichert) die exakte Aufruffolge des `KeygenProvider` nachgespielt und jede Antwort wie `verify()` geprüft: alle signiert, Digest und Signatur gültig. Ablauf: `validate-key` → `NO_MACHINES`, Aktivierung → 201, erneut → 422 `FINGERPRINT_TAKEN` (Erfolg), Validierung → `VALID`, Entitlements → `DDI_Networks`, Heartbeat → 200, Deaktivierung → 204. Lizenz-Metadaten leer, also keine Grenzen. **Offen:** der Go-Code selbst gegen die echte Instanz – per Umgebungsvariable aktivierter Live-Test in der CI (Schlüssel als Gitea-Secret) oder beim ersten echten Betrieb prüfen. `tools/keygen-setup/keygen-setup.sh` ist nie gegen die Instanz gelaufen.
2. **Oberfläche nie im echten Browser bedient**, inzwischen mit vielen neuen Dialogen (Cluster, Zonen, Records, TSIG). Abgesichert durch Vitest-Komponententests und den Smoke-Test des Release-Binaries. Beim ersten Durchklicken (`make dev-up`, `make dev-admin`, `make run-server`, `cd web && npm run dev`) auf Layout-Fehler und Abläufe achten.
3. **Frontend-Bundle:** Seiten werden seit M5 per `React.lazy` nachgeladen; der Hauptteil ist noch 481 KB (154 KB gzip), vor allem Bibliotheken und beide Sprachdateien. Weiter verkleinern: Vendor-Split, Sprachdateien nachladen.
4. **Service-Schicht ohne eigene Abdeckungszahl:** wird über die API-Tests geprüft; Nachweis mit `go test -coverpkg=./server/... ./server/internal/httpapi`.
5. **GitHub-Rate-Limit in der CI:** `setup-go`/`setup-node` holen Manifeste von GitHub (60 Anfragen/Stunde je IP). Bisher nur Warnungen. Falls Jobs scheitern: Go/Node in `scripts/ci/install-tools.sh` selbst mit Prüfsumme installieren.
6. **TanStack Table 9 und React Router 8** sind erschienen; bewusst auf Table 8 / Router 7 geblieben. Upgrade später als eigener Schritt.
7. **Kea-HA:** nur mit Kea ≥ 3.0 (geprüft mit 3.2.1); Benutzer und Passwort liegen in Dateien, weil Kea 3 Klartext-Anmeldedaten ablehnt. Die HA-Verbindung läuft per HTTP mit Basic-Auth, **ohne TLS** (folgt später; Zertifikate könnte die Agent-CA ausstellen). Beide Peers melden dieselben Leases; die doppelte Übernahme in die Adresstabelle ist harmlos.
8. **SOA-Seriennummer bei lokalem Rollback:** Rollbacks über das UI erzeugen eine neue, höhere Revision. Rollt der Agent auf dem Primary lokal zurück, sinkt die Seriennummer dort; Secondaries behalten bis zur nächsten Revision die höhere (ADR 0023).
9. **Zertifikatserneuerung mit verlorener Antwort:** Erhält der Agent die neue Antwort nicht, gilt beim Server schon die neue Seriennummer; der Agent muss neu registriert werden. In `OPERATIONS.md` (M6) beschreiben.
10. **Kea `config-reload` liest die Datei, mit der Kea gestartet wurde.** Weicht `dhcp.config_file` des Agents davon ab, meldet der Reload Erfolg mit alter Konfiguration; nur der Dateivergleich im Health-Check fällt auf. Installer (M6) muss Pfade, Hook-Verzeichnis (Kea 3.x: einkompiliert) und Socket-Verzeichnis (Modus 0750) passend setzen.
11. **Server-Tests mit Zeitbezug:** Agent-Kern- und Agent-API-Tests nutzen kurze Intervalle (50 ms bis 15 s). Bei sporadischen CI-Fehlern dort zuerst an Timing denken.
12. **Nicht umgesetzt aus dem Brief (optional bzw. später):** DNS-Namen dynamischer Leases per Kea-DDNS (`kea-dhcp-ddns`) in eine dynamische Zone schreiben (§5.2, „optional pro Netz“); GSS-TSIG für Active Directory (in `docs/ACTIVE-DIRECTORY.md` als nicht unterstützt beschrieben); Bindung eines Enrollment-Tokens an einen Cluster (ADR 0008) – Mitglieder werden nach der Registrierung im UI zugeordnet.
13. **Cluster-Kleinigkeiten:** Wird ein Agent gelöscht, verlässt er seinen Cluster per Kaskade ohne eigenen Audit-Eintrag am Cluster. Eine noch nicht übertragene Secondary-Zone ist im Health-Check nur „eingeschränkt“; direkt nach dem Ausrollen kann der Secondary kurz `tsig indicates error` melden, wenn er den neuen Schlüssel vor dem Primary aktiviert hat (NOTIFY holt die Zonen danach, im End-to-End-Test beobachtet).
14. **Aus den Messungen (M6, `test/bench`):** CSV-Import war mit ~300 Zeilen/s zu langsam für eine Datei an der Grenze von 50.000 Zeilen (60-s-Timeout); behoben: Netze und vorhandene Einträge werden einmal geladen (~1.100 Zeilen/s, Lauf 95), Frist für den Import 10 min. `GET /addresses` ohne Netzfilter braucht bei 50.000 Einträgen 110–240 ms (Zählung, `ILIKE`-Suche, tiefe Offsets). Jede Revision speichert alle Dateien voll (50.000 Adressen: 4,6 MiB) – Aufbewahrung empfehlen bzw. später deduplizieren.
15. **Schlüsselrotation unvollständig:** Master-Key-Datei kann mehrere Schlüssel halten, aber es gibt kein Neuverschlüsseln vorhandener Werte; keine Rotation für Agent-CA, Bundle-Schlüssel und HA-Passwort (nur über Neuanlage des Clusters). Beschrieben in `OPERATIONS.md`/`SECURITY.md`.
16. **Master-Key-Rechte:** Der Server verweigert `master.key`, wenn Gruppe oder andere lesen dürfen (0400/0600 nötig); ADR 0024 nannte 0640 root:<produkt>. Der Installer muss 0400 mit Eigentümer Dienstbenutzer setzen.
1. **Keygen live geprüft (2026-10-13), aber noch nicht mit dem Go-Code selbst.** Die Aufruffolge des `KeygenProvider` wurde per Skript mit echtem Schlüssel nachgespielt (alle Antworten signiert und gültig; `validate-key` → `NO_MACHINES`, Aktivierung 201, erneut 422 `FINGERPRINT_TAKEN`, Validierung `VALID`, Entitlements `DDI_Networks`, Heartbeat 200, Deaktivierung 204). **Offen:** der Go-Code selbst gegen die echte Instanz, z. B. bei der Abnahme mit `ddi-server license set-key` oder per Live-Test in der CI mit Gitea-Secret. `tools/keygen-setup/keygen-setup.sh` ist nie gegen die Instanz gelaufen.
2. **Oberfläche nie im echten Browser bedient** (inzwischen viele Dialoge: Cluster, Zonen, Records, TSIG). Abgesichert durch Vitest und Smoke-Tests. Bei der Abnahme auf Layout-Fehler und Abläufe achten.
3. **Frontend-Bundle:** Seiten werden nachgeladen; der Hauptteil ist noch 481 KB (154 KB gzip). Weiter verkleinern: Vendor-Split, Sprachdateien nachladen.
4. **Service-Schicht ohne eigene Abdeckungszahl:** Nachweis mit `go test -coverpkg=./server/... ./server/internal/httpapi`.
5. **GitHub-Rate-Limit in der CI:** `setup-go`/`setup-node` holen Manifeste von GitHub. Falls Jobs scheitern: Go/Node in `scripts/ci/install-tools.sh` selbst mit Prüfsumme installieren.
6. **TanStack Table 9 und React Router 8** sind erschienen; bewusst auf Table 8 / Router 7 geblieben.
7. **Kea-HA:** nur mit Kea ≥ 3.0; Zugangsdaten aus Dateien; HA-Verbindung per HTTP mit Basic-Auth **ohne TLS**. Beide Peers melden dieselben Leases (harmlos).
8. **SOA-Seriennummer bei lokalem Rollback:** Rollt der Agent auf dem Primary lokal zurück, sinkt die Seriennummer dort; Secondaries behalten bis zur nächsten Revision die höhere (ADR 0023).
9. **Kea `config-reload` liest die Datei, mit der Kea gestartet wurde.** Der Installer setzt die Pfade passend; wer Kea von Hand umkonfiguriert, siehe `OPERATIONS.md` §10.3.
10. **Server-Tests mit Zeitbezug:** Agent-Kern- und Agent-API-Tests nutzen kurze Intervalle. Bei sporadischen CI-Fehlern zuerst an Timing denken (so auch der AXFR-Integrationstest, behoben durch Start-Reihenfolge).
11. **Nicht umgesetzt aus dem Brief (optional bzw. später):** Kea-DDNS für Namen dynamischer Leases (§5.2, optional); GSS-TSIG; Bindung eines Enrollment-Tokens an einen Cluster (ADR 0008).
12. **Cluster-Kleinigkeiten:** Löschen eines Agents entfernt ihn ohne eigenen Audit-Eintrag aus seinem Cluster; Secondary kann direkt nach dem Ausrollen kurz `tsig indicates error` melden (NOTIFY holt die Zonen danach).
13. **Aus den Messungen:** `GET /addresses` ohne Netzfilter braucht bei 50.000 Einträgen 110–240 ms. Jede Revision speichert alle Dateien voll (50.000 Adressen: 4,6 MiB) – Aufbewahrung (`retention.revisions_keep`) empfehlen bzw. später deduplizieren. Nicht gemessen: Speicher der Agents, 50 verbundene Agents, viele gleichzeitige Benutzer, Kea mit HA.
14. **Schlüsselrotation unvollständig:** kein Neuverschlüsseln vorhandener Werte beim Master-Key-Wechsel; keine Rotation für Agent-CA, Bundle-Schlüssel und HA-Passwort (nur Neuanlage des Clusters). Beschrieben in `OPERATIONS.md`/`SECURITY.md`.
15. **Installer, nicht in der CI geprüft:** `--kea-source distro` (Hooks ohne Pfad), AppArmor/SELinux im erzwingenden Modus (Container setzen sie nicht durch), echte Downloads vom Gitea-Release (die CI nutzt `--from-dir`). EL9 braucht EPEL für Kea von ISC.
16. **Zertifikatserneuerung mit verlorener Antwort:** Agent muss neu registriert werden (`enroll --force`), beschrieben in `OPERATIONS.md` §8.2.
---
@@ -122,6 +127,15 @@ Datenbanktests brauchen `DDI_TEST_DATABASE_URL` (z. B. `postgres://ddi:ddi-dev-o
## Verlauf
### 2026-10-16 – M6 Auslieferung (`v0.7.0`)
- Verträge vorab: [ADR 0024](adr/0024-auslieferung-installer-m6.md), gehärtete Unit-Vorlagen `deploy/systemd/*.service.in`, `scripts/render-units.sh`. Vorher per Probe-Workflow auf einem Wegwerf-Branch geprüft, dass die CI-Runner privilegierte systemd-Container starten können (Debian, Ubuntu, Rocky) und Netz zu Paketquellen, Gitea und Keygen haben. Dann drei Agents (Installer, Release/Server, Messungen/Doku); alle brachen mehrfach am Sitzungslimit ab und liefen nach `SendMessage` weiter. Installer- und Mess-Agent durften für CI-Läufe je einen eigenen Remote-Branch pushen (`m6-installer`, `m6-bench`, danach gelöscht).
- **Installer** `scripts/install.sh`: Rollen `server`, `agent-dns`, `agent-dhcp` auf Debian 12/13, Ubuntu 22.04/24.04, EL9; Vorabprüfung nach `SYSTEM-REQUIREMENTS.md` §3; Prüfsummen und (sobald eingerichtet) Ed25519-Signatur; PostgreSQL mit Peer-Authentifizierung (kein DB-Passwort); Agents laufen als Benutzer ihres Dienstes (`bind`/`named`, `_kea`/`kea`), ohne root; Kea 3.2 aus dem ISC-Repository (EL9 braucht EPEL); markierte Blöcke in `named.conf`, kollidierende Distributionsoptionen umkehrbar auskommentiert; idempotent, `--upgrade`, `--uninstall [--purge]`, `--dry-run`, Aufräumen bei Abbruch. Neu `docs/INSTALL.md`.
- **Installationstest** (Workflow `install`, Lauf 101): je System ein privilegierter systemd-Container, alle Rollen installieren, Agents per Token registrieren, Revision ausrollen, `dig` und Kea-Reservierung prüfen, Hardening und Nicht-root-Prozesse prüfen, zweiter Lauf ohne Änderungen, Upgrade auf eine zweite Version, Deinstallation mit und ohne `--purge`. Auf allen fünf Systemen grün.
- **Release/Server:** `ddi-server license set-key` (stdin, Exit-Codes 0–4), Aufbewahrung (`retention.audit_days`, `retention.revisions_keep`, täglich, nie benutzte Revisionen), `.deb`/`.rpm` mit nfpm, Signatur `SHA256SUMS.sig` im Release-Workflow (Secret `RELEASE_SIGNING_KEY`, Anleitung `docs/RELEASE.md`), Namensprüfung `scripts/check-brand.sh` (ADR 0018).
- **Von den Tests gefunden:** ISC-Kea vergleicht den Socket-Pfad wörtlich mit dem einkompilierten `/var/run/kea` (Lösung: `KEA_CONTROL_SOCKET_DIR=/run/kea` per Drop-in); `kea-dhcp4 -t` braucht Netlink in der Agent-Unit; Rocky-`named.conf` beschränkt `listen-on`/`allow-query` auf localhost; der Server lehnt einen gruppenlesbaren Master-Key ab (ADR korrigiert: 0400); der CSV-Import war mit ~300 Zeilen/s zu langsam für die 50.000-Zeilen-Grenze (jetzt ~1.100/s); der AXFR-Integrationstest war wackelig (Secondary startete vor dem Primary).
- **CI-Lehren:** Ein Runner hatte für das Standard-Build-Netz von Docker kein ausgehendes Netz – Images mit `--network host` bauen. Die CI-Runner haben nur ~1,9 GB freien Platz; der Installationstest prüft deshalb erst, dass die Vorabprüfung abbricht, und nutzt dann `--force`.
### 2026-10-15 – M6 Messungen, Betriebs- und Sicherheitsdoku
- Benchmark `test/bench/` (`make bench`, Workflow `bench`, nur `workflow_dispatch`): Server mit PostgreSQL 17, synthetische Daten (5.000 und 50.000 Einträge) per CSV-Import über die API; BIND 9.20 mit `dnsperf` und Kea 3.2.1 mit `perfdhcp` auf den Dateien aus `GET /config/preview`. Ergebnisse (Lauf 93, Runner 4 vCPU Skylake, 7,7 GiB) in `SYSTEM-REQUIREMENTS.md`; neu `OPERATIONS.md`, `SECURITY.md`.