R183-01: PUT /retention-policies/{id} nahm retentionDays 0 ohne Bestaetigung an
und protokollierte es als MEDIUM - waehrend cleanup, seal und rehash alle ein
Confirm-Gate haben und die Folge CRITICAL ist. Die geladene Waffe war ungegatet,
der Abzug gegatet. Fix: Absenken verlangt confirm SHORTEN, wird als CRITICAL mit
Vorher/Nachher protokolliert, Untergrenze 30 Tage fuer Authentication/AuditLog.
R183-02: Nach dem Cleanup meldete verify "Keine Manipulation" bei valid:false
und 3010 endgueltig geloeschten Anmeldeprotokollen - der Befund stand nur im
Feld, die Prosa beruhigte. Fix: ehrliche Formulierung bei Luecken, und das
Gegenbuch ruft /verify mit und wertet valid:false hart, egal wie der Text
klingt.
R183-03: verify warnte dauerhaft "Altbestand nicht versiegelt", waehrend
seal-backlog zu Recht ablehnte. Eine unaufloesbare Warnung lernt man zu
ignorieren. Fix: eigener Zustand nicht_noetig, echte Warnung nennt den Befehl.
Heartbeat-Wachhund: Bleibt ein Dienstkonto laenger still als
SERVICE_ACCOUNT_MAX_SILENCE_MINUTES (Standard 180), gibt es SUSPICIOUS/CRITICAL.
Ohne je gesehene Anmeldung wird geschwiegen statt geraten, pro Ausfall genau
eine Meldung. Verifiziert in allen drei Faellen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
129 lines
6.3 KiB
Bash
129 lines
6.3 KiB
Bash
# Backend nutzt seit v1.1 die zentrale Root-.env im Projektverzeichnis.
|
|
# → siehe ../.env.example für alle Variablen
|
|
#
|
|
# Diese Datei bleibt als Legacy-Fallback: wenn /.env nicht existiert,
|
|
# liest das Backend backend/.env (z.B. für isolierte Backend-Tests).
|
|
|
|
# Database
|
|
DATABASE_URL="mysql://user:password@localhost:3306/opencrm"
|
|
|
|
# JWT
|
|
JWT_SECRET="your-super-secret-jwt-key-change-in-production"
|
|
# Access kurz (XSS-Schutz, nur JS-Memory). Refresh lang im httpOnly-Cookie.
|
|
JWT_EXPIRES_IN="15m"
|
|
JWT_REFRESH_EXPIRES_IN="7d"
|
|
|
|
# Encryption (for portal credentials)
|
|
ENCRYPTION_KEY="32-byte-hex-key-for-aes-256-gcm"
|
|
|
|
# Server
|
|
PORT=3001
|
|
NODE_ENV=development
|
|
|
|
# ==================== AUDIT-SIEGEL ====================
|
|
# Was ist das Audit-Log?
|
|
# OpenCRM protokolliert luekenlos, wer wann welche Daten gesehen oder
|
|
# geaendert hat. Das ist die Beweisspur, wenn es Streit gibt oder der
|
|
# Datenschutz nachfragt.
|
|
#
|
|
# Wogegen schuetzt dieser Schluessel?
|
|
# Ohne ihn koennte jemand mit Zugriff auf die Datenbank einen Eintrag
|
|
# nachtraeglich umschreiben - zum Beispiel einen fehlgeschlagenen
|
|
# Login-Versuch in einen erfolgreichen verwandeln - und die Faelschung so
|
|
# glattziehen, dass die Pruefung sie fuer echt haelt.
|
|
# Mit dem Schluessel bekommt jeder Eintrag ein Siegel, das sich nur mit
|
|
# diesem Schluessel erzeugen laesst. Wer ihn nicht hat, kann nichts
|
|
# faelschen, ohne dass es auffliegt. Bildlich: Der Schluessel ist der
|
|
# Stempel des Notars - die Akte liegt zwar im Schrank, aber den Stempel
|
|
# hat nur der Notar.
|
|
#
|
|
# Wie einrichten?
|
|
# Einmalig einen Schluessel erzeugen und hier eintragen:
|
|
# openssl rand -hex 32
|
|
# Pro Umgebung ein EIGENER Schluessel (Entwicklung, Test, Produktion).
|
|
#
|
|
# Was passiert, wenn ich ihn weglasse?
|
|
# Nichts faellt aus. Das Audit-Log laeuft normal weiter, nur eben ohne
|
|
# dieses zusaetzliche Siegel.
|
|
#
|
|
# Ich habe bisher keinen Schluessel - kann ich ihn nachtraeglich setzen?
|
|
# Ja. Schluessel erzeugen, eintragen, Backend neu starten - fertig.
|
|
# Bestehende Eintraege bleiben unveraendert gueltig, ab dem Neustart
|
|
# werden neue gesiegelt. Alt und neu liegen nebeneinander, es gibt
|
|
# dadurch KEINE Fehlalarme. Rueckwirkend siegeln geht nicht - je frueher
|
|
# gesetzt, desto groesser der geschuetzte Zeitraum.
|
|
#
|
|
# ACHTUNG: einmal gesetzt, nicht wieder abschalten.
|
|
# Fehlt der Schluessel spaeter (z. B. beim Container-Rebuild verlorengegangen),
|
|
# laeuft alles weiter - aber die in dieser Zeit entstandenen Eintraege sind
|
|
# ungesiegelt und werden beanstandet, sobald der Schluessel wieder da ist.
|
|
# Ein ungesiegelter Eintrag inmitten gesiegelter ist von einer Faelschung
|
|
# nicht zu unterscheiden. Also: in die Deploy-Checkliste aufnehmen.
|
|
#
|
|
# Was passiert, wenn ich ihn verliere?
|
|
# Laesst du das Feld LEER, gelten die gesiegelten Eintraege als
|
|
# "nicht pruefbar" - NICHT als gefaelscht, also kein Fehlalarm. Der
|
|
# Nachweis fuer diesen Zeitraum ist aber weg.
|
|
# Traegst du stattdessen einen NEUEN Schluessel ein, ohne den alten unten
|
|
# zu hinterlegen, werden die alten Eintraege als "manipuliert" gemeldet -
|
|
# ein falscher Schluessel ist von einer Faelschung nicht zu unterscheiden.
|
|
# Deshalb: Schluessel sichern, so wie ein Passwort.
|
|
#
|
|
# Eigenen Wert erzeugen mit: openssl rand -hex 32
|
|
# Der Platzhalter unten zaehlt NICHT als Schluessel - laesst du ihn stehen,
|
|
# bleibt das Siegel aus (es wird also nicht versehentlich mit einem oeffentlich
|
|
# bekannten Wert gesiegelt). Leer lassen ist ebenfalls in Ordnung.
|
|
AUDIT_HMAC_KEY=<hier-eigenen-wert-eintragen>
|
|
|
|
# Frueher verwendete Schluessel - beim Wechsel hier eintragen.
|
|
# Moechtest du den Schluessel oben austauschen (z. B. weil du vermutest,
|
|
# dass er in falsche Haende geraten ist), trage den ALTEN Schluessel hier
|
|
# ein und den NEUEN oben. Dann bleiben die bisherigen Eintraege pruefbar,
|
|
# waehrend neue schon mit dem neuen Schluessel gesiegelt werden.
|
|
#
|
|
# ACHTUNG: Dieses Feld NICHT voreilig leeren. Solange Eintraege existieren,
|
|
# die mit einem alten Schluessel gesiegelt wurden, muessen sie hier stehen.
|
|
# Sonst werden diese Eintraege als "manipuliert" gemeldet (nicht als
|
|
# "nicht pruefbar"). Gefahrlos leeren kannst du erst, wenn die betroffenen
|
|
# Eintraege durch die Aufbewahrungsfristen ohnehin geloescht sind.
|
|
#
|
|
# Mehrfach gewechselt? Mehrere Schluessel kommagetrennt, juengster zuerst:
|
|
# AUDIT_HMAC_KEY_OLD=<vorheriger>,<davor>,<ganz alter>
|
|
#
|
|
# Beim ersten Einrichten leer lassen - erst beim Schluesselwechsel noetig.
|
|
AUDIT_HMAC_KEY_OLD=
|
|
|
|
# --- Technisch (fuer Entwickler/Admins) ---------------------------------
|
|
# Verfahren : HMAC-SHA256 ueber alle Inhaltsspalten eines Audit-Eintrags,
|
|
# inkl. previousHash (Verkettung). Entspricht Hash-Version 3.
|
|
# Abdeckung : Version 1 = 7 Felder (Altbestand), Version 2 = alle 24
|
|
# Inhaltsspalten (SHA-256, unsigniert), Version 3 = wie 2, aber
|
|
# HMAC-signiert. Die erwartete Version wird aus der Kette
|
|
# abgeleitet (Version-Floor), nicht aus der Selbstauskunft der
|
|
# Zeile - sonst liesse sich per Downgrade die schwaechere
|
|
# Pruefung erzwingen.
|
|
# Fail-safe : Ohne Schluessel schreibt der Dienst weiter Version 2. Bereits
|
|
# signierte Zeilen landen dann in `unverifiableEntries`,
|
|
# ausdruecklich NICHT in `tamperedEntries`.
|
|
# Rotation : AUDIT_HMAC_KEY_OLD (kommagetrennte Liste) wird bei der
|
|
# Pruefung zusaetzlich akzeptiert - Wechsel ohne Rehash. Ein
|
|
# falscher/fehlender Alt-Schluessel liefert einen HMAC-Mismatch
|
|
# und damit einen Manipulations-Befund; das ist nicht von einer
|
|
# echten Faelschung unterscheidbar und daher Absicht.
|
|
# Grenze : Schuetzt gegen DB-Schreibzugriff ohne Schluessel. Wer Schluessel
|
|
# UND Datenbank hat, kann die Kette konsistent neu rechnen.
|
|
# Erzeugung : openssl rand -hex 32 (256 Bit)
|
|
|
|
# ==================== DIENSTKONTO-WACHHUND ====================
|
|
# Nach wie vielen Minuten Stille eines Dienstkontos (z. B. des Gegenbuchs)
|
|
# ein Sicherheitsereignis erzeugt wird.
|
|
#
|
|
# Hintergrund: Die planmaessigen Anmeldungen selbst sind bewusst als Routine
|
|
# eingestuft, damit sie die CRITICAL-Stufe nicht entwerten. Das Signal ist
|
|
# deshalb die ABWESENHEIT: Wer das Gegenbuch stilllegt, setzt darauf, dass
|
|
# Stille nicht auffaellt.
|
|
#
|
|
# Faustregel: etwa das Dreifache des Gegenbuch-Takts. Bei stuendlichem Takt
|
|
# also 180. Ohne Dienstkonten im System passiert nichts.
|
|
SERVICE_ACCOUNT_MAX_SILENCE_MINUTES=180
|