Files
nexarch/docs/OPS-13-PRUEFPROTOKOLL.md
T
patrickandClaude Sonnet 5 47b85b6522
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (pull_request) Canceled after 0s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (pull_request) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (push) Canceled after 0s
Archive-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (pull_request) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
Supply-Chain-Scan (npm) / npm-audit (pull_request) Canceled after 0s
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (pull_request) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (pull_request) Canceled after 0s
CI / Web (dms-browser) (pull_request) Canceled after 0s
CI / Web (pdf-viewer) (pull_request) Canceled after 0s
CI / Web (shl) (pull_request) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (pull_request) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (pull_request) Canceled after 0s
Mail-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (pull_request) Canceled after 0s
OPS-13: Prüfprotokoll und neue AAD-Tests (F-21)
Neue Tests fuer Archive/Mail/Core-kek (Pruefung 1/2 je Stelle,
identisches Muster wie die bereits vorhandenen DMS-Tests). Alle
Pruefungen real gegen Postgres auf Host 204 durchgefuehrt (siehe
Pruefprotokoll), inkl. vollstaendiger Regression von dms/qa02,
internal/kek, internal/ldapsync, internal/webhook.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 22:47:08 +02:00

5.7 KiB
Raw Blame History

OPS-13 – Prüfprotokoll: Additional Authenticated Data bei AES-GCM (F-21)

Datum: 2026-09-26. Testhost: 192.168.1.204, Wegwerf-Postgres-Rollen/-Datenbanken (nach jedem Lauf entfernt).

Umgesetzte Änderung

Alle vier in QA-15/F-21 genannten Stellen binden jetzt ein Additional Authenticated Data (AAD) an ihre AES-256-GCM-Chiffretexte:

Ort AAD-Quelle
dms/internal/crypto/envelope.go (WrapDEK/UnwrapDEK/EncryptStream/DecryptStream) Tenant-Slug (Service.Seal/Open/NewDataKey/UnwrapDataKey — Signatur unverändert, ~30 externe Aufrufstellen nicht angefasst)
archive/internal/backupcrypto/envelope.go (WrapDEK/UnwrapDEK, plus direkte seal/open-Aufrufe in file.go) Tenant-Slug (RepoPassword/EncryptFile/DecryptFile — bereits vorhandener Parameter)
mail/internal/crypto/envelope.go (WrapDEK/UnwrapDEK/EncryptStream/DecryptStream, plus kekversions.go) Tenant-Slug (Service.Seal/Open/OpenAtVersion, ARC-08-KEK-Versionsverwaltung)
internal/kek/master.go (wrap/unwrap, EncryptWithTenantKEK/DecryptWithTenantKEK) und internal/kek/store.go (Tenant-KEK-Verpackung durch den Master-Key) Tenant-ID (Store.CreateForTenant/GetDecrypted/RotateTenantKEK/RotateMasterKey); für die drei realen externen Aufrufer von EncryptWithTenantKEK/DecryptWithTenantKEK: internal/ldapsync (Tenant-ID + Zweck-Bezeichner), internal/webhook (Ziel-URL des Abonnements), cmd/account-api modulekeys (fester Zweck-Bezeichner, siehe „Bekannte Grenze“ unten)

Rückwärtskompatibilität: jedes open/unwrap versucht zuerst mit dem neuen AAD, fällt bei Fehlschlag auf kein-AAD zurück. Vor dieser Änderung versiegelte Datensätze bleiben ohne Neuverschlüsselung lesbar.

Akzeptanzkriterien

  1. Alle vier Stellen binden AAD an ihren Chiffretext — erfüllt, siehe Tabelle oben.
  2. Simulierter Schlüssel-/Chiffretext-Austausch zwischen zwei Kontexten wird erkannt — erfüllt, siehe Prüfung 1 unten für alle vier Stellen.
  3. Bereits verschlüsselte Datensätze bleiben lesbar — erfüllt, siehe Prüfung 2 unten.

Prüfungen (real durchgeführt, nicht nur behauptet)

DMS (dms/internal/crypto)

  • Prüfung 1 (TestWrapDEK_AADBindsContext): DEK mit AAD "tenant-a" verpackt, Entpacken mit AAD "tenant-b" liefert ErrDecryptFailed. Bestanden.
  • Prüfung 2 (TestUnwrapDEK_LegacyWithoutAADStillReadable): mit WrapDEK(kek, dek, nil) versiegelter Alt-Datensatz bleibt mit UnwrapDEK(kek, wrapped, []byte("tenant-a")) lesbar. Bestanden.
  • Prüfung 3 (Regression): komplette bestehende internal/crypto-Testsuite (9 Tests) grün, internal/qa02-End-zu-Ende-Suite (6 Tests, echter Postgres, u. a. TestKeyManagement_RewrapKeepsContentReadableWithNewKEKOnly — der reale RewrapDEK-Produktionspfad) grün.

Archive (archive/internal/backupcrypto)

  • Prüfung 1 (TestWrapDEK_AADBindsContext): identisches Muster wie DMS. Bestanden.
  • Prüfung 2 (TestUnwrapDEK_LegacyWithoutAADStillReadable): Bestanden.
  • Prüfung 3 (Regression): 3 Tests grün (Paket hatte zuvor keine eigene Testdatei — neu angelegt, keine Alttests zu brechen).

Mail (mail/internal/crypto)

  • Prüfung 1/2: Bestanden (neue envelope_test.go, gleiches Muster).
  • Prüfung 3 (Regression, echter Postgres): TestKEKVersionStore_RecordIfNewDetectsRotationOnly, TestKEKVersionStore_RevokeBlocksOnlyThatVersion, TestRotation_OldArchiveStaysReadableAfterMasterKeyRotation, TestRotation_CompromisedOldKeyCanBeRevoked — alle 4 grün (ARC-08-KEK-Versionsverwaltung nutzt dieselben Primitive, keine Regression durch die AAD-Umstellung in kekversions.go).

Core (internal/kek, internal/ldapsync, internal/webhook, cmd/account-api)

  • Prüfung 1/2 (TestEncryptWithTenantKEK_AADBindsContext, TestDecryptWithTenantKEK_LegacyWithoutAADStillReadable): Bestanden.
  • Prüfung 3 (Regression, echter Postgres): internal/kek komplette Suite (17 Tests, inkl. TestRotateMasterKey_AllTenantKEKsRemainDecryptableWithSamePlaintext, TestRotateTenantKEK_OnlyAffectsThatTenant — beide nutzen die geänderten wrap/unwrap-Aufrufe in store.go real) grün. internal/ldapsync (8 Tests, inkl. TestConfigStore_WrongTenantKEK_CannotDecrypt) grün. internal/webhook (7 Tests, inkl. TestSubscribe_SecretIsEncryptedAtRest, TestProcessDue_RetriesWithBackoffThenMarksFailed — durchläuft den geänderten Decrypt-Pfad mehrfach mit unterschiedlichen Ziel-URLs) grün. cmd/account-api Bestandstest grün.

Bekannte, dokumentierte Grenze

Diese Kachel bindet AAD an den verfügbaren Kontext (Tenant-Slug/-ID, Ziel-URL, fester Zweck-Bezeichner) — nicht an eine Datensatz-ID. Ein Austausch zwischen zwei Datensätzen desselben Mandanten/Kontexts (z. B. zwei Dokument-Revisionen desselben Tenants) bleibt dadurch unerkannt, da beide dasselbe AAD tragen würden. Eine vollständige Bindung an den einzelnen Datensatz würde eine Datensatz-ID an rund 30 Aufrufstellen in DMS/Mail durchreichen (Service.Seal/Open) bzw. das generische SecretCipher-Interface in internal/moduletrust ändern (betrifft mehrere Module, die dasselbe Interface für Modul-/Sitzungs-Signaturschlüssel nutzen) — beides bewusst außerhalb der "kleinsten Lösung" dieser Kachel. F-21 selbst stuft das Risiko als moderat ein, weil bereits Schreibzugriff auf die Datenbank vorausgesetzt ist; diese Kachel schließt die praktisch bedeutsamste Variante (Kontext-/Mandanten-Verwechslung), nicht die theoretisch verbleibende Variante (Verwechslung innerhalb desselben Kontexts).

Zusammenfassung

Alle Akzeptanzkriterien und Prüfungen bestanden. Keine Regression in den vier betroffenen Modulen (DMS, Archive, Mail, Core) und ihren jeweils sieben echten Aufrufern. Kein Merge, kein Deploy.