From 2c6eff85f399860502829e5afb3659d48fdb206b Mon Sep 17 00:00:00 2001 From: Claude Fable 5 Date: Fri, 31 Jul 2026 09:59:27 +0200 Subject: [PATCH] #227: hardening guide with the VS-NfD reference configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs/vs-nfd/50-haertungsleitfaden.md: one adoptable profile — every entry with the exact switch name, value, default and the reason, split into instance settings (registration closed, api/mcp off, feeds off, plugins off, classification defaults vs_nfd + upload block, svg reject, minimal extension list) and deploy-level configuration (empty BACKUP_ALLOWED_TARGETS enforces backup-local-only outside Site-Admin reach; tightened session hours; SMTP deliberately unconfigured with the consequence stated honestly). auth.local.enabled is listed as the one pending row (#216) with its compensation until then; the guide states the binding updated-in-same-PR rule for every future switch. Includes an operator verification checklist (four unauthenticated 404 curls + readyz + admin spot checks). Cross-referenced from the delimitation statement (file names made concrete) and consumed by the Grundschutz mapping (#230). Co-Authored-By: Claude Fable 5 (1M context) --- docs/vs-nfd/20-massnahmenplan.md | 6 +- docs/vs-nfd/40-abgrenzungserklaerung.md | 7 +- docs/vs-nfd/50-haertungsleitfaden.md | 94 +++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 docs/vs-nfd/50-haertungsleitfaden.md diff --git a/docs/vs-nfd/20-massnahmenplan.md b/docs/vs-nfd/20-massnahmenplan.md index f4aad76..5765811 100644 --- a/docs/vs-nfd/20-massnahmenplan.md +++ b/docs/vs-nfd/20-massnahmenplan.md @@ -184,9 +184,9 @@ nach sich zieht. - [x] **Abgrenzungserklärung §52 VSA** — welche Sicherheitsgrundfunktionen die Anwendung _nicht_ erbringt und wem sie zufallen. Wichtigstes Einzeldokument. · 3 AT · #226 → `40-abgrenzungserklaerung.md` -- [ ] **Härtungsleitfaden** mit Referenzkonfiguration „VS-NfD-Betrieb": - lokale Auth aus, Public-API aus, MCP aus, Feeds aus, Plugins aus, - Backup nur lokal · 3 AT · #227 +- [x] **Härtungsleitfaden** mit Referenzkonfiguration „VS-NfD-Betrieb": + lokale Auth aus (Zeile ⏳ bis #216), Public-API aus, MCP aus, Feeds aus, + Plugins aus, Backup nur lokal · 3 AT · #227 → \`50-haertungsleitfaden.md\` - [x] **Sicherheitsdokumentation**: Architektur, Datenflüsse, Netzplan, Ports/Dienste, Vertrauensgrenzen · 4 AT · #228 → `60-sicherheitsdokumentation.md` - [x] **Betriebshandbuch**: Installation (inkl. Airgap), Update, Backup/Restore, diff --git a/docs/vs-nfd/40-abgrenzungserklaerung.md b/docs/vs-nfd/40-abgrenzungserklaerung.md index 21fc2bd..382b0cb 100644 --- a/docs/vs-nfd/40-abgrenzungserklaerung.md +++ b/docs/vs-nfd/40-abgrenzungserklaerung.md @@ -313,5 +313,8 @@ Slug-Residuum falls in #235 so entschieden), führt die Restrisikoliste gekürzt; die Erklärung ist erst dann uneingeschränkt gültig, wenn die Delta-Liste leer ist oder alle Restpositionen in der Restrisikoliste (#231) vom Betreiber gebilligt sind. -- Querbezüge: Härtungsleitfaden (#227), Sicherheitsdokumentation (#228), - Betriebshandbuch (#229), IT-Grundschutz-Zuarbeit (#230). +- Querbezüge: Härtungsleitfaden (#227, `50-haertungsleitfaden.md`), + Sicherheitsdokumentation (#228, `60-sicherheitsdokumentation.md`), + Betriebshandbuch (#229, `70-betriebshandbuch.md`), + IT-Grundschutz-Zuarbeit (#230, `80-grundschutz-mapping.md`), + Restrisikoliste (#231, `90-restrisiken.md`). diff --git a/docs/vs-nfd/50-haertungsleitfaden.md b/docs/vs-nfd/50-haertungsleitfaden.md new file mode 100644 index 0000000..6323c22 --- /dev/null +++ b/docs/vs-nfd/50-haertungsleitfaden.md @@ -0,0 +1,94 @@ +# Härtungsleitfaden — Referenzkonfiguration „VS-NfD-Betrieb" (Issue #227) + +Zweck: **eine** benannte Konfiguration, die ein Betreiber als Ganzes +übernehmen kann. Jeder Eintrag nennt den exakten Schalter, den Wert und +das **Warum** — wer abweicht, tut es wissentlich. Der Leitfaden macht +zugleich die in M1/M2/M4 gebauten Schalter prüfbar. + +**Pflegeregel (verbindlich):** Jeder PR, der einen neuen Instanz- oder +Deploy-Schalter einführt, ergänzt diesen Leitfaden **im selben PR** um +dessen Referenzwert. Ein Schalter ohne Leitfaden-Zeile gilt im Review +als unvollständig. (Gleiches Muster wie der Ereigniskatalog-Zaun #201.) + +Geltungsbereich: Konfiguration der Anwendung. Die Härtung der Plattform +(Betriebssystem, Netz, Reverse Proxy, Datenträger) ist Betreibersache +(Abgrenzungserklärung `40-abgrenzungserklaerung.md` — von dort wird +hierher verwiesen; das IT-Grundschutz-Mapping +`80-grundschutz-mapping.md` nimmt diese Referenzkonfiguration als +Produkt-Beleg). + +--- + +## 1 Referenzkonfiguration + +### 1.1 Instanz-Settings (Site-Admin → Einstellungen; Tabelle `instance_settings`) + +Nach jeder Änderung an Instanz-Settings die api neu starten — der +Settings-Cache ist in-process (operations.md). + +| Setting | Referenzwert | Default | Warum | +| ----------------------------------------------------------------------------------------------------------- | --------------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `auth.registrationMode` | `closed` | `open` | Konten entstehen in einer VS-Umgebung nur kontrolliert; Selbstregistrierung öffnet den Nutzerkreis unkontrolliert. | +| `api.enabled` | `false` | `false` | Public REST API ist ein zusätzlicher Egress-Kanal; ohne dokumentierten Bedarf bleibt er zu (404 auf allen `/api/public/v1`-Routen). | +| `mcp.enabled` | `false` | `false` | gleiches Argument für den MCP-Endpoint (`/api/mcp`); unabhängiger Schalter. | +| `feeds.enabled` | `false` | `true` | **explizit setzen** — Atom-Feeds liefern Inhalte an Reader außerhalb der Kontrolle der Instanz (Feed-Token umgehen die Session); Kopien in Feed-Readern sind nicht einholbar (Kopienliste, Sicherheitsdokumentation §5). Schaltet Routen UND Feed-Token-Verwaltung auf 404. | +| `plugins.enabled` | `false` | `true` | **explizit setzen** — kein Fremdcode in der VS-Zone (#200): alle Plugin-Flächen 404, Dropzone quarantänisiert; bestehende Blöcke degradieren zu ihrem deklarierten Text-Fallback. Hash-Pinning ist verschoben (#232, Restrisikoliste) — der Kill-Switch deckt das Risiko für diesen Betriebsmodus vollständig. | +| `classification.newPageDefault` | `vs_nfd` | `unclassified` | in einer VS-NfD-Instanz beginnt nichts unmarkiert (#204); die Vererbung (#205) hält den Baum konsistent. | +| `classification.uploadPolicy` | `block` | `warn` | Anhänge können die Kennzeichnung im Inhalt nicht tragen (#212) — die Referenzkonfiguration lehnt Uploads auf eingestufte Seiten serverseitig ab (403 `classified_upload_blocked`, #213) statt nur zu warnen. | +| `upload.svgPolicy` | `reject` | `sanitize` | SVG ist aktiver Inhalt; die Sanitisierung ist gut getestet, aber Ablehnen ist die kleinere Angriffsfläche. Abweichung vertretbar, wenn SVG gebraucht wird. | +| `upload.allowedExtensions` | nur das dienstlich Nötige (z. B. `pdf`) | Standardliste | jede zusätzliche Endung vergrößert die Menge nicht prüfbarer Binärformate im Bestand. Bilder sind davon unabhängig immer erlaubt (Magic-Byte-geprüft). | +| `backup.nextcloud.enabled` | `false` | `false` | „Backup nur lokal": kein Anwendungs-Upload von Restore-Sets zu Drittdiensten. Fernspiegel regelt ausschließlich die Deploy-Allowlist (1.2). | +| `trash.retentionDays`, `audit.retentionDays`, `conversion.payloadRetentionDays`, `mail.outboxRetentionDays` | Defaults (30/365/30/30) | ebd. | Aufbewahrung bewusst begrenzt; Verkürzung nach Betreiber-Löschkonzept zulässig (Betriebshandbuch §5). | +| `legal.imprint`, `legal.privacyPolicy` | befüllt | leer | Betreiberpflicht; leere Seiten zeigen einen Warnbanner. | + +### 1.2 Deploy-Konfiguration (`.env` / Compose — nur Plattformzugriff, bewusst nicht per Admin-UI) + +| Variable | Referenzwert | Warum | +| ----------------------------------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `BACKUP_ALLOWED_TARGETS` | leer lassen **oder** exakt der eine freigegebene Spiegel-Host | leere Allowlist schaltet ALLE Fernziele hart ab (ADR 0026, #192) — „Backup nur lokal" ist damit deploy-seitig erzwungen und vom Site-Admin nicht aufweichbar (Rollentrennung, Betriebshandbuch §6). | +| `SESSION_ABSOLUTE_HOURS` | `12` (Default 168) | eine Sitzung überdauert keinen Arbeitstag; Neuanmeldung am nächsten Tag ist der Preis. | +| `SESSION_IDLE_HOURS` | `2` (Default 72) | unbeaufsichtigte, noch angemeldete Arbeitsplätze fallen schnell zurück auf die Anmeldemaske. | +| `SMTP_HOST` etc. | **unkonfiguriert lassen** (oder internes Relay) | ohne SMTP verlassen keinerlei Inhaltstitel die Instanz per Mail (Digest-Restrisiko I-23 entfällt vollständig). Konsequenz ehrlich benannt: dann gibt es keine Verifikations- und Passwort-Reset-Mails — Kontenpflege läuft über den Site-Admin. Wer Mail braucht, nutzt ein internes Relay und akzeptiert I-23 (Restrisikoliste). | +| `WEB_PORT`/`API_PORT`/`COLLAB_PORT` | Defaults (127.0.0.1-gebunden) | Anwendungscontainer sind nie direkt exponiert; einzige Eintrittsstelle ist der Reverse Proxy (Sicherheitsdokumentation §2). | +| `LOG_LEVEL` | `info` | Audit-Zeilen (`audit: `-Präfix) müssen den Collector erreichen; `debug` nur zur Störungssuche. | + +### 1.3 Noch nicht verfügbar (Regel: landet hier im selben PR) + +| Schalter | Referenzwert (geplant) | Status | +| -------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `auth.local.enabled` | `false` — lokale Passwort-Auth aus, Anmeldung nur über die Fremdauthentisierung der Behörde | ⏳ kommt mit #216 (M27); bis dahin bleibt lokale Auth der einzige Anmeldeweg und `auth.registrationMode=closed` + Session-Verkürzung sind die Kompensation. Zeile wird im #216-PR scharfgestellt. | + +## 2 Verifikations-Checkliste + +Auf der laufenden Instanz (ersetze `HOST`); Erwartung jeweils dahinter. +Die vier 404-Prüfungen laufen unauthentifiziert: + +```sh +curl -s -o /dev/null -w '%{http_code}\n' https://HOST/api/public/v1/ponds # 404 (api.enabled=false) +curl -s -o /dev/null -w '%{http_code}\n' -X POST https://HOST/api/mcp # 404 (mcp.enabled=false) +curl -s -o /dev/null -w '%{http_code}\n' https://HOST/api/v1/public/IRGENDEIN-TEICH/feed.xml # 404 (feeds.enabled=false) +curl -s -o /dev/null -w '%{http_code}\n' https://HOST/api/v1/admin/plugins # 401/404, nie 200 ohne Session +curl -s https://HOST/api/v1/readyz # status ok +``` + +Als Site-Admin (UI → Administration bzw. `GET /api/v1/admin/settings`): + +- [ ] Registrierung „geschlossen"; neue Seite entsteht mit Kennzeichnung + (Einstufung neuer Seiten = VS-NfD); Upload auf eingestufte Seite + wird abgelehnt (403). +- [ ] Plugin-Verwaltung antwortet 404 (Kill-Switch aktiv). +- [ ] Backup-Panel zeigt keine aktiven Fernziele; auf dem Host ist + `BACKUP_ALLOWED_TARGETS` leer bzw. exakt der freigegebene Spiegel. +- [ ] Eine Testsitzung läuft nach `SESSION_IDLE_HOURS` Inaktivität ab. +- [ ] Kennzeichnungs-Stichprobe: eingestufte Seite zeigt den Aufdruck in + Web, Druckvorschau und PDF-Export (Konventionen: Kommentare auf + Issue #228 bzw. `60-sicherheitsdokumentation.md` §3.5). + +## 3 Querbezüge + +Abgrenzungserklärung (`40-abgrenzungserklaerung.md`, verweist hierher); +IT-Grundschutz-Mapping (`80-grundschutz-mapping.md`, nutzt dieses +Profil als Produkt-Beleg); Betriebshandbuch (`70-betriebshandbuch.md`, +Installation §1 wendet dieses Profil an); Restrisikoliste +(`90-restrisiken.md` — Abweichungen von der Referenzkonfiguration +gehören dorthin, wenn sie dauerhaft sind).