added install script for agent
changed backend to agent
This commit is contained in:
+29
-30
@@ -12,8 +12,8 @@ Sortiert nach Risikoklasse. Datei-/Zeilenreferenzen beziehen sich auf den Stand
|
||||
- README/`docs/deployment.md` entsprechend anpassen (noch offen).
|
||||
|
||||
- [x] **2. `API_TOKEN` im Node-Agent zur Pflicht machen** ✅ erledigt
|
||||
- `backend/src/config.js:44` — Start schlägt fehl wenn Token fehlt oder kürzer als 32 Zeichen.
|
||||
- `backend/src/index.js` — `if (!config.apiToken) next()` entfernt; Token-Prüfung immer aktiv.
|
||||
- `agent/src/config.js:44` — Start schlägt fehl wenn Token fehlt oder kürzer als 32 Zeichen.
|
||||
- `agent/src/index.js` — `if (!config.apiToken) next()` entfernt; Token-Prüfung immer aktiv.
|
||||
|
||||
- [x] **3. HTTPS zwischen Management und Agent erzwingen** ✅ erledigt
|
||||
- `management/src/routes/nodes.js:102-112` — `validateBaseUrl` erzwingt `https://`. Escape-Hatch `ALLOW_INSECURE_AGENT_HTTP=true` nur für Dev.
|
||||
@@ -29,16 +29,14 @@ Sortiert nach Risikoklasse. Datei-/Zeilenreferenzen beziehen sich auf den Stand
|
||||
- Audit-Event `login_blocked` und `login_failed` implementiert.
|
||||
- Hinweis: Kein externer `express-rate-limit` nötig, eigenständige Implementierung ausreichend.
|
||||
|
||||
- [ ] **6. Restore atomarisieren — kein direktes `dd` auf Produktiv-Volume**
|
||||
- Datei: `backend/src/executor.js:92` (`streamResticDumpToDd`), `backend/src/routes/restore.js`
|
||||
- Aktuell: Wenn `restic dump` abbricht, sind GB bereits auf der VM-Disk → Disk irreversibel kaputt.
|
||||
- Fix-Optionen:
|
||||
- In temporäres ZFS-Volume schreiben, danach Größen-/Hash-Verifikation, dann atomarer `zfs rename`/clone-Swap.
|
||||
- Oder: vor Restore automatisch Disk-Snapshot anlegen; bei Fehler rollback.
|
||||
- Größe vorab prüfen (`restic stats` vs. `zfs get volsize`).
|
||||
- [x] **6. Restore atomarisieren — kein direktes `dd` auf Produktiv-Volume** ✅ staged Restore umgesetzt
|
||||
- Datei: `agent/src/executor.js:92` (`streamResticDumpToDd`), `agent/src/routes/restore.js`
|
||||
- Umsetzung: Restore schreibt zuerst in ein temporäres ZFS-Volume, prüft die Größe vorab und tauscht danach per `zfs rename` gegen das Produktiv-Volume.
|
||||
- Das alte Volume bleibt als `*.pre-restore-*` Rollback-Kopie erhalten.
|
||||
- Bei Fehlern vor dem Swap wird nur das temporäre Volume entfernt; bei Fehlern nach dem Swap versucht der Agent den alten Volume-Namen wiederherzustellen.
|
||||
|
||||
- [ ] **7. Backup-Verifikation einbauen**
|
||||
- Datei: `backend/src/routes/backup.js` (VM-Pfad ~Z.71, Container-Pfad ~Z.137)
|
||||
- Datei: `agent/src/routes/backup.js` (VM-Pfad ~Z.71, Container-Pfad ~Z.137)
|
||||
- Aktuell: Bei Pipe-Fehler (`zfs send` !=0, `createReadStream`-Abbruch) committed restic ggf. einen unvollständigen Snapshot mit Status „success".
|
||||
- Fix:
|
||||
- Vor Start erwartete Größe ermitteln (`zfs get volsize` / `used`).
|
||||
@@ -57,14 +55,15 @@ Sortiert nach Risikoklasse. Datei-/Zeilenreferenzen beziehen sich auf den Stand
|
||||
- Offen: `management/.env.example` hat `SESSION_COOKIE_SECURE=false` — in Deployment-Doku explizit als "in Produktion auf `true` setzen" dokumentieren.
|
||||
|
||||
- [ ] **10. Race beim Sichtbarmachen des Snapshot-Devices**
|
||||
- Datei: `backend/src/routes/backup.js:57`
|
||||
- Datei: `agent/src/routes/backup.js:57`
|
||||
- Aktuell: 2 s `sleep` reicht nicht garantiert.
|
||||
- Fix: Polling-Schleife auf `fs.access(snapshotDevice)` mit Timeout; zusätzlich `udevadm trigger && udevadm settle`.
|
||||
|
||||
- [ ] **11. Persistenter Job- und Lock-Store im Agent**
|
||||
- Datei: `backend/src/jobs.js`
|
||||
- Aktuell: in-memory; bei Crash gehen laufende Jobs verloren, Locks bleiben hängen oder verschwinden inkonsistent (z.B. ZFS `volmode=dev`).
|
||||
- Fix: SQLite-Tabelle für Jobs/Locks. Beim Start: alle `running`/`queued` Jobs zu `failed` markieren, Cleanup-Pfad ausführen.
|
||||
- [x] **11. Persistenter Job- und Lock-Store im Agent** ✅ erledigt
|
||||
- Datei: `agent/src/jobs.js`
|
||||
- Umsetzung: Agent speichert Jobs in SQLite (`AGENT_DATABASE_PATH`).
|
||||
- Beim Start werden `running`/`queued` Jobs als `failed` markiert, damit Management einen finalen Zustand pollen kann und VM-Locks nicht hängen bleiben.
|
||||
- Offen für später: ressourcenspezifische Cleanup-Recovery für abgebrochene Host-Operationen.
|
||||
|
||||
- [ ] **12. Toten `SESSION_SECRET` aufräumen**
|
||||
- Datei: `management/src/config.js:8`
|
||||
@@ -72,7 +71,7 @@ Sortiert nach Risikoklasse. Datei-/Zeilenreferenzen beziehen sich auf den Stand
|
||||
- Fix: Variable und zugehörigen `.env.example`-Eintrag entfernen, oder Session-IDs HMAC-signieren und Variable dann sinnvoll nutzen.
|
||||
|
||||
- [ ] **13. Snapshot-ID-Prefix-Matching eindeutig machen**
|
||||
- Datei: `backend/src/validators.js:66`
|
||||
- Datei: `agent/src/validators.js:66`
|
||||
- Aktuell: `startsWith` — bei Prefix-Kollision wird stillschweigend der erste Treffer genommen.
|
||||
- Fix: Bei >1 Treffer 409 zurückgeben; UI auf 12-Hex-Prefix umstellen.
|
||||
|
||||
@@ -81,12 +80,12 @@ Sortiert nach Risikoklasse. Datei-/Zeilenreferenzen beziehen sich auf den Stand
|
||||
- Fix: Mindestens Rollen `admin` / `operator` / `viewer`. Restore nur für `admin`.
|
||||
|
||||
- [ ] **15. ENV-Escaping in `writeEnvSettings` verbessern**
|
||||
- Datei: `backend/src/config.js:105`
|
||||
- Datei: `agent/src/config.js:105`
|
||||
- Aktuell: Nur `\` und `"` escaped; `$`, Backticks, Newlines nicht.
|
||||
- Fix: Eigener Serializer mit korrektem Escaping aller Sonderzeichen.
|
||||
|
||||
- [ ] **16. Settings-Endpunkt sperren bis `API_TOKEN` initial gesetzt ist**
|
||||
- Datei: `backend/src/routes/settings.js`
|
||||
- Datei: `agent/src/routes/settings.js`
|
||||
- Hängt mit Fix #2 zusammen — nach #2 automatisch erfüllt, hier zur Sicherheit dokumentieren/testen.
|
||||
|
||||
---
|
||||
@@ -99,18 +98,18 @@ Sortiert nach Risikoklasse. Datei-/Zeilenreferenzen beziehen sich auf den Stand
|
||||
|
||||
- [ ] **18. Systemd-Hardening für den Agent**
|
||||
- Datei: `deploy/systemd/incus-backup-agent.service`
|
||||
- Hinzufügen: `NoNewPrivileges=true`, `ProtectSystem=strict`, `ProtectHome=true`, `PrivateTmp=true`, `ReadWritePaths=/dev/zvol /var/lib/incus /opt/incus-backup-ui/backend`, `CapabilityBoundingSet=...`, eingeschränkte `AmbientCapabilities`.
|
||||
- Hinzufügen: `NoNewPrivileges=true`, `ProtectSystem=strict`, `ProtectHome=true`, `PrivateTmp=true`, `ReadWritePaths=/dev/zvol /var/lib/incus /opt/incus-backup-ui/agent`, `CapabilityBoundingSet=...`, eingeschränkte `AmbientCapabilities`.
|
||||
|
||||
- [ ] **19. `npm start` durch direkten `node`-Aufruf ersetzen**
|
||||
- Datei: beide `deploy/systemd/*.service`
|
||||
- `ExecStart=/usr/bin/node src/index.js` — kein npm-Wrapper-Prozess, kein PATH-Risiko.
|
||||
|
||||
- [ ] **20. CORS am Agent entfernen**
|
||||
- Datei: `backend/src/index.js:16`
|
||||
- Datei: `agent/src/index.js:16`
|
||||
- Agent wird nie aus dem Browser angesprochen → Angriffsfläche raus.
|
||||
|
||||
- [ ] **21. `schedules.json`-Pfad explizit konfigurierbar**
|
||||
- Datei: `backend/src/scheduler.js:6`
|
||||
- Datei: `agent/src/scheduler.js:6`
|
||||
- Aktuell: `process.cwd()`-abhängig.
|
||||
- Fix: über Env (`SCHEDULES_PATH`) absolut konfigurieren, Default unter `/var/lib/incus-backup-agent/`.
|
||||
|
||||
@@ -127,16 +126,16 @@ Sortiert nach Risikoklasse. Datei-/Zeilenreferenzen beziehen sich auf den Stand
|
||||
- Pro VM und global (z.B. max N parallele Streams nach S3). Disk-Space-/Quota-Check vor Start.
|
||||
|
||||
- [ ] **25. `incus snapshot delete` Retry verallgemeinern**
|
||||
- Datei: `backend/src/routes/backup.js:303`
|
||||
- Datei: `agent/src/routes/backup.js:303`
|
||||
- Aktuell: Substring-Match auf englische Stderr — bricht bei lokalisierten Builds.
|
||||
- Fix: Generischer Retry (n Versuche, Backoff) bei nicht-0 Exit-Code.
|
||||
|
||||
- [ ] **26. Restic-`ls` streamen statt vollständig in RAM laden**
|
||||
- Datei: `backend/src/routes/snapshots.js:19`
|
||||
- Datei: `agent/src/routes/snapshots.js:19`
|
||||
- Für Container-Backups mit vielen Files relevant.
|
||||
|
||||
- [ ] **27. Container-Restore implementieren oder Container-Backup deaktivieren**
|
||||
- Datei: `backend/src/routes/restore.js:21`
|
||||
- Datei: `agent/src/routes/restore.js:21`
|
||||
- Aktuell: 501. Backups laufen, aber nicht wiederherstellbar = Backup-Theater.
|
||||
- Fix: Sicheren `zfs receive`-Workflow umsetzen oder Container-Backup im UI/API ausschalten bis fertig.
|
||||
|
||||
@@ -151,8 +150,8 @@ Sortiert nach Risikoklasse. Datei-/Zeilenreferenzen beziehen sich auf den Stand
|
||||
- [ ] **30. `frontend/dist/` ist eingecheckt** — ignorieren und löschen.
|
||||
- [ ] **31. `incus-backup-ui-plan.md` auf Secrets/Bucket-Namen prüfen** bevor OSS.
|
||||
- [ ] **32. Container-Limit (Restore fehlt) prominent in README dokumentieren.**
|
||||
- [ ] **33. Scheduler-Jitter einbauen** (`management/src/scheduler.js`, `backend/src/scheduler.js`) — sonst belasten viele Nodes synchron S3.
|
||||
- [ ] **34. `formatBytes` deduplizieren** (`backend/src/routes/backup.js`, `restore.js`) → `executor.js` oder `utils.js`.
|
||||
- [ ] **33. Scheduler-Jitter einbauen** (`management/src/scheduler.js`, `agent/src/scheduler.js`) — sonst belasten viele Nodes synchron S3.
|
||||
- [ ] **34. `formatBytes` deduplizieren** (`agent/src/routes/backup.js`, `restore.js`) → `executor.js` oder `utils.js`.
|
||||
- [ ] **35. `.env`-Dateipermissions dokumentieren** — `chmod 600` im Deployment-Doc verlangen.
|
||||
- [ ] **36. Schema-Versionierung statt `addColumnIfMissing`** — z.B. `schema_version`-Tabelle + nummerierte Migrationen.
|
||||
- [ ] **37. `audit_events.details` Größenlimit** oder JSON-Spalte (SQLite hat JSON1).
|
||||
@@ -175,7 +174,7 @@ Sortiert nach Risikoklasse. Datei-/Zeilenreferenzen beziehen sich auf den Stand
|
||||
|
||||
---
|
||||
|
||||
## Status-Übersicht kritische Punkte (Stand 2026-05-21)
|
||||
## Status-Übersicht kritische Punkte (Stand 2026-06-04)
|
||||
|
||||
| # | Titel | Status |
|
||||
|---|-------|--------|
|
||||
@@ -184,15 +183,15 @@ Sortiert nach Risikoklasse. Datei-/Zeilenreferenzen beziehen sich auf den Stand
|
||||
| 3 | HTTPS Management↔Agent | ✅ erledigt |
|
||||
| 4 | CORS-Whitelist + SameSite=Strict | ✅ erledigt |
|
||||
| 5 | Brute-Force-Schutz Login | ✅ erledigt |
|
||||
| 6 | Restore atomarisieren | ⬜ offen |
|
||||
| 6 | Restore atomarisieren | ✅ staged Restore umgesetzt |
|
||||
| 7 | Backup-Verifikation | ⬜ offen |
|
||||
| 8 | Bearer-Token aus localStorage | ✅ erledigt |
|
||||
| 9 | Session-Cookie `Secure`-Flag | ⚠️ teilweise |
|
||||
|
||||
## Nächste Prioritäten
|
||||
|
||||
1. **#6/#7** Restore- und Backup-Verifikation — größter Aufwand, größter Impact auf Datenintegrität.
|
||||
1. **#7** Backup-Verifikation weiter härten — Pipeline-/Stream-Fehler testen und vollständiger absichern.
|
||||
2. **#9** `SESSION_COOKIE_SECURE=true` in Deployment-Doku festschreiben.
|
||||
3. **#12** Toten `SESSION_SECRET` entfernen.
|
||||
4. **#15** ENV-Escaping vervollständigen (`$`, Backticks, Newlines).
|
||||
5. **#11** Job- und Lock-Store auf SQLite persistieren (Crash-Sicherheit).
|
||||
5. **#11 Folgearbeit** ressourcenspezifische Cleanup-Recovery nach Agent-Crash definieren.
|
||||
|
||||
Reference in New Issue
Block a user