Files
opencrm/backend/.env.example
T
duffyduckandClaude Opus 5 fb0915df12 Audit-Siegel: Umstiegsweg dokumentiert + Rotations-Fussangel entschaerft
Frage aus dem Betrieb: bestehende Installation hat noch keinen
AUDIT_HMAC_KEY - was passiert beim nachtraeglichen Setzen? Antwort jetzt in
README und .env.example: setzen, neu starten, fertig. Bestehende Eintraege
bleiben unveraendert gueltig, neue werden gesiegelt, alt und neu koexistieren
ohne Fehlalarm. Nachgemessen auf gemischtem Bestand (4903 x V1, 57 x V2,
67 x V3): 0 Beanstandungen. Rueckwirkend siegeln ist nicht moeglich.

Dabei zwei Fehler in der eigenen Doku gefunden und korrigiert:

1. Behauptet war, nach dem Leeren von AUDIT_HMAC_KEY_OLD seien alte Eintraege
   "nicht mehr pruefbar". Tatsaechlich werden sie als MANIPULIERT gemeldet -
   ein falscher Schluessel ist von einer Faelschung nicht zu unterscheiden.
   Gemessen: 67 Eintraege als manipuliert. Nur wenn GAR KEIN Schluessel
   gesetzt ist, gilt "nicht pruefbar". Doku entsprechend korrigiert, inkl.
   Warnung, das Feld nicht voreilig zu leeren.

2. AUDIT_HMAC_KEY_OLD bot nur einen Platz. Beim ZWEITEN Wechsel waeren alle
   mit dem ersten Schluessel gesiegelten Eintraege faelschlich als
   manipuliert erschienen (reproduziert: 67). Das Feld nimmt jetzt eine
   kommagetrennte Liste entgegen; verifiziert: mit beiden Alt-Schluesseln
   0 Beanstandungen, mit nur dem juengsten 67.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 19:14:24 +02:00

102 lines
4.9 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.
#
# 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.
AUDIT_HMAC_KEY=
# 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>
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)