Commit Graph
8 Commits
Author SHA1 Message Date
duffyduckandClaude Opus 5 ab0d6214f2 Audit-Siegel: Platzhalter zaehlt nicht als Schluessel + Betriebsfalle dokumentiert
.env.example zeigt jetzt wie bei den anderen Secrets einen sichtbaren
Platzhalter an der Variablen statt eines leeren Werts - verstaendlicher, aber
mit Schutz dagegen: ein nicht ersetzter Platzhalter (enthaelt < oder >, oder
beginnt mit change/dein/your/hier) gilt NICHT als Schluessel. Sonst wuerde mit
einem oeffentlich im Repository stehenden Wert gesiegelt, was Sicherheit
vortaeuscht. Das Backend warnt in dem Fall im Log und laesst das Siegel aus.
Verifiziert: mit Platzhalter geschriebene Zeile bleibt hashVersion 2.

Dabei aufgefallen und dokumentiert: Wird das Siegel nach Aktivierung wieder
abgeschaltet (Schluessel fehlt, z. B. beim Rebuild verloren), sind die in
dieser Zeit entstandenen Eintraege ungesiegelt und werden beanstandet, sobald
der Schluessel zurueck ist. Das ist Absicht - ein ungesiegelter Eintrag
inmitten gesiegelter ist von einer Faelschung nicht zu unterscheiden. Warnung
in README und .env.example.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 19:24:59 +02:00
duffyduckandClaude Opus 5 6de3a91aa7 .env.example: erklaert, warum beim Audit-Siegel kein Beispielwert steht
Die leeren Werte bei AUDIT_HMAC_KEY/AUDIT_HMAC_KEY_OLD wirkten wie ein
Versehen. Sie sind Absicht: leer bedeutet "Siegel aus" (fail-safe), und ein
Beispielwert waere hier gefaehrlicher als keiner - er stuende oeffentlich im
Repository, und jeder koennte damit Eintraege siegeln, waehrend der Betreiber
sich gesiegelt waehnt. Anders als bei JWT_SECRET, wo ein Platzhalter sinnvoll
ist, weil die Anwendung ohne Wert gar nicht laeuft.

Entsprechender Hinweis jetzt direkt ueber beiden Variablen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 19:21:33 +02:00
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
duffyduckandClaude Opus 5 93cb5ffd27 Doku: Audit-Siegel (AUDIT_HMAC_KEY) verstaendlich erklaert
README und .env.example erklaeren jetzt zuerst in Alltagssprache, was das
Audit-Log ist, wogegen der Schluessel schuetzt und was passiert, wenn man ihn
weglaesst oder verliert - inklusive Bild vom Notarstempel. Die technische
Ebene bleibt vollstaendig erhalten, in der README als aufklappbarer Block
(Hash-Versionen 1/2/3, Version-Floor, Loeschungs-Manifest, Rueckgabefelder von
/verify, bekannte Grenze) und in .env.example als eigener Abschnitt.

Ausserdem dokumentiert: Schluesselwechsel ueber AUDIT_HMAC_KEY_OLD ohne
Rehash, pro Umgebung ein eigener Schluessel, und die Warnung zu den beiden
Endpunkten mit Nebenwirkung (rehash/cleanup).

AUDIT_HMAC_KEY zusaetzlich in die Production-Checkliste aufgenommen.

Korrigiert: Die Integritaetspruefung ist NICHT ueber die Oberflaeche
erreichbar (verifyIntegrity wird von keiner Komponente genutzt) - die Doku
zeigt jetzt den API-Aufruf. Rechte, Endpunkte und Rueckgabefelder gegen den
Code geprueft.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 19:06:35 +02:00
duffyduckandClaude Opus 5 044a12f73e Externer Anker: Audit-Kette HMAC-signiert (Hash-Version 3)
Schliesst den nach R166/R167 verbliebenen Grenzfall: Bis Version 2 war die
Kette selbsttragend - wer die DB schreiben kann, konnte jede Zeile aendern und
alle Folgehashes konsistent nachziehen, die Pruefung meldete "gueltig".

Version 3 signiert denselben Inhalt per HMAC-SHA256 mit AUDIT_HMAC_KEY, einem
Schluessel ausserhalb der Datenbank. Ohne ihn laesst sich keine gueltige
Signatur erzeugen; reiner DB-Schreibzugriff genuegt nicht mehr.

Fail-safe: Ohne Schluessel wird weiter Version 2 geschrieben, es faellt nichts
aus. Signierte Zeilen gelten dann als nicht pruefbar (unverifiableEntries) und
ausdruecklich nicht als manipuliert. AUDIT_HMAC_KEY_OLD erlaubt einen
Schluesselwechsel ohne Rehash.

Restluecke der Versionsgrenze geschlossen: Wird die FRUEHESTE Zeile einer Stufe
herabgestuft, wandert MIN(id) mit - die Grenze allein haette den Downgrade
durchgewunken (der erste Testlauf fiel genau darauf durch). Der Nachfolger ist
jedoch HMAC-signiert und sein previousHash ohne Schluessel nicht faelschbar;
eine unerklaerte Luecke vor einer signierten Zeile gilt deshalb als Befund.

Verifiziert: Inhalt geaendert -> erkannt; Downgrade 3->2 auf der fruehesten
V3-Zeile -> erkannt; dasselbe auf der letzten V3-Zeile (kein Nachfolger) ->
erkannt; ohne Schluessel 0 manipuliert / 2 nicht pruefbar; 40 parallele
Schreiber -> 40/40, 0 Forks, alle V3. tsc + vite build gruen.

AUDIT_HMAC_KEY in .env.example dokumentiert. Der Schluessel selbst liegt nur
lokal in .env (gitignored).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 18:50:57 +02:00
duffyduckandClaude Opus 4.7 48fe69cdab Security-Hardening Runde 17: JWT-TTL + Pentest-Marker-Detection
Pentest Runde 17:

21.1 Access-Token TTL war 7 Tage statt 15min:
docker-compose.yml und .env.example standen schon richtig auf 15m
als Default. Die alten Beispiel-.env-Files (backend/.env.example,
docker/.env.example) hatten noch die alte Konvention "7d". Beide
auf 15m korrigiert + explizites JWT_REFRESH_EXPIRES_IN=7d ergänzt.
Auf prod muss die echte .env entsprechend angepasst werden.

17.5 Alte Pentest-Daten in DB:
Cleanup-Script erweitert um Pentest-Marker-Erkennung:
- Email-Pattern: ^hacker@, ^attacker@, ^pentest@, @evil\.
- XSS-Marker: <script, onerror=, javascript:
- Sonstige: SQL-Injection, Path-Traversal

Bewusst eng gefasst (Marker MUSS am Email-Anfang stehen), damit
legitime Kunden wie "stefanhacker@gmx.de" nicht als Pentest-Daten
durchgehen.

Default: nur warnen + Records auflisten. Opt-In via
CLEANUP_PURGE_PENTEST=true löscht die markierten Customer/User.

Live-verifiziert:
- stefanhacker@gmx.de (echt) → durchgelassen
- hacker@evil.de (Pentest) → erkannt + Warnung
- Mit Purge-Env → gelöscht

18.4 Klartext-Portal-PW-Abruf:
Bewusst drin gelassen (Admin-UI-Komfort). Endpoint ist mit
customers:update-Permission gated + Audit-Log (READ →
PortalPassword) – kein Bypass-Risiko, nur explizite Audit-Pflicht.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 20:06:03 +02:00
duffyduckandClaude Opus 4.7 e145edaa90 docker: zentrale .env + Compose mit MariaDB+OpenCRM+Adminer + Bind-Mounts
Big Move: vom backend-only-Setup zum vollständigen Container-Stack.

📁 Neue Struktur
- /.env (lokal, nicht getrackt) – zentrale Konfiguration für Dev + Docker
- /.env.example – Template mit allen Variablen
- /data/{db,uploads,factory-defaults,backups}/ – Bind-Mounts statt Volumes
  (auf Wunsch: Daten bleiben im Projektverzeichnis)
- /backend/Dockerfile – Multi-Stage Build (Frontend + Backend)
- /backend/docker-entrypoint.sh – wartet auf DB, prisma db push, optional seed

🐳 docker-compose.yml (neu konsolidiert)
- mariadb 10.11 mit Bind-Mount ./data/db
- opencrm-app (Backend serviert Frontend statisch in production)
- adminer mit Theme pepa-linha-dark als DB-UI
- Ports + Pfade + Secrets alle aus .env

🔧 Backend
- index.ts dotenv-Loader: lädt zuerst Root /.env, dann backend/.env als
  Fallback. Funktioniert nahtlos für npm run dev und für Container.
- backend/.env.example als Legacy-Fallback dokumentiert

📝 README
- Quick-Start mit Docker als empfohlener Default (3 Befehle)
- Tabelle der Daten-Verzeichnisse
- Hinweis auf RUN_SEED=true beim ersten Start

⚙ Konfigurierbar via .env
- OPENCRM_PORT (Backend extern), ADMINER_PORT (DB-UI), DB_PORT
- Daten-Pfade (DATA_DIR, DB_DATA_DIR, UPLOADS_DIR etc.)
- DB_NAME/USER/PASSWORD, JWT_SECRET, ENCRYPTION_KEY
- ADMINER_DESIGN (Theme-Auswahl)

Hinweis: Vor dem ersten `docker compose up -d` muss das laufende
`npm run dev`-Backend gestoppt werden (Port + DB-Conflict). Das alte
Volume `opencrm_mariadb_data` bleibt unangetastet als Notfall-Backup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 18:53:19 +02:00
Stefan Hacker e209e9bbca first commit 2026-01-29 01:16:54 +01:00