feat(abgleich): Drift-Erkennung, Zeitplan und Uebernahme (#021, #022)

Ein Abgleich liest je Host alle authorized_keys in einem SSH-Aufruf,
als jeweiliger Benutzer, und vergleicht sie mit dem Soll: fehlende,
von Hand geaenderte und unbekannte Keys, falsche Rechte, beschaedigte
Bloecke und veraenderte Private Keys. Befunde werden geoeffnet und
wieder geschlossen, Zustaende von Verwendungen und Host nachgezogen.
Auf dem Host aendert der Abgleich nichts.

Der Zeitplan liegt in pg-boss und feuert auch bei mehreren Workern
nur einmal. Auf der Hostseite stehen Abweichungen und der Ist-Zustand
je Benutzer; unbekannte Keys lassen sich uebernehmen - nur bekannt
machen oder mit Dry-Run in den verwalteten Block holen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 13:02:11 +02:00
co-authored by Claude Opus 5.5
parent 2dad8e5631
commit e518e75022
24 changed files with 1334 additions and 21 deletions
+12 -5
View File
@@ -1,20 +1,27 @@
# #021 Abgleich und Drift-Erkennung
**Status:** offen
**Status:** erledigt
**Meilenstein:** v0.4.0
**Labels:** backend
**Geschätzt:** 3 h **Tatsächlich:** –
**Geschätzt:** 3 h **Tatsächlich:** 0 h 45 min
## Ziel
Periodischer und manueller Abgleich, Befunde je Host/Benutzer.
## Aufgaben
- [ ] Zeitplan konfigurierbar
- [ ] Befundarten
- [x] Zeitplan konfigurierbar
- [x] Befundarten
## Akzeptanzkriterien
- [ ] Integrationstest
- [x] Integrationstest
## Abhängigkeiten
#016
## Notizen / Entscheidungen
- **Ein SSH-Aufruf je Host** liest `authorized_keys` aller Benutzer mit UID 0 oder ≥ 1000 plus aller Benutzer mit Zuweisungen – als jeweiliger Benutzer, base64-kodiert (Zeilenenden und fremde Bytes kommen unversehrt an). Dazu Rechte und Eigentümer von `~/.ssh` und Datei.
- **Befunde** (rein, `src/lib/ssh/abgleich.ts`): fehlender Key im Block, Block von Hand geändert (zusätzlicher Key oder andere Optionen), unbekannter Key außerhalb (bekannte Keys außerhalb sind kein Befund), Rechte (für Gruppe/Welt beschreibbar oder fremder Eigentümer), beschädigter Block, Private Key fehlt oder verändert (Hash gegen den versiegelten Key).
- **Abweichungen** werden geöffnet und – sobald behoben – geschlossen, nie doppelt. Host-Key-Abweichungen bleiben bei #009.
- **Zustände:** Public-Verwendungen AUSGEROLLT ↔ ABWEICHUNG, GEPLANT bleibt bis zum Ausrollen; Host SYNCHRON/DRIFT, letzter Abgleich, erreichbar.
- **Zeitplan** über pg-boss (`SSHKV_SYNC_CRON`, Standard `30 2 * * *`, Europe/Berlin) – liegt in der Datenbank, feuert also auch bei mehreren Workern nur einmal. Hosts mit laufendem Abgleich werden übersprungen.
- **Ändert nichts auf dem Host.** Korrekturen laufen über Dry-Run und Ausrollen.
- `DATEI_GEAENDERT` meldet nur einen beschädigten Block; eine bloße Hash-Änderung ist kein Befund, weil sshkv selbst schreibt.
+8 -4
View File
@@ -1,19 +1,23 @@
# #022 Import bestehender Schlüssel
**Status:** offen
**Status:** erledigt
**Meilenstein:** v0.4.0
**Labels:** backend, ui
**Geschätzt:** 2 h **Tatsächlich:** –
**Geschätzt:** 2 h **Tatsächlich:** 0 h 20 min
## Ziel
Unbekannte Schlüssel eines Hosts übernehmen und zuordnen.
## Aufgaben
- [ ] wird zu Beginn der Phase verfeinert
- [x] wird zu Beginn der Phase verfeinert
## Akzeptanzkriterien
- [ ] wird zu Beginn der Phase verfeinert
- [x] wird zu Beginn der Phase verfeinert
## Abhängigkeiten
#021
## Notizen / Entscheidungen
- **Grundlage ist die letzte Beobachtung** des Abgleichs: Übernommen wird nur, was sshkv dort wirklich gesehen hat.
- **Zwei Wege:** „bekannt“ (nur als Schlüssel aufnehmen – der Befund verschwindet, auf dem Host ändert sich nichts) oder „verwalten“ (Zuweisung mit `ausserhalbEntfernen`: beim nächsten Ausrollen wandert die Zeile mit ihren Optionen in den Block, die alte Zeile außerhalb verschwindet – mit Dry-Run).
- Neues Feld `PublicVerwendung.ausserhalbEntfernen` (Migration `20261012131000`). Ohne dieses Feld fasst sshkv Zeilen außerhalb des Blocks weiterhin nie an.
- Optionen der Zeile werden mit `optionenPruefen` übernommen; unbekannte Optionen verhindern das Verwalten mit klarer Meldung.