Files
opencrm/backend/todo.md
T
duffyduck df6eb9724d Security-Hardening Runde 7: SSRF-Schutz + Logout-Endpoint
🛡 SSRF-Schutz in test-connection / test-mail-access
- Admin-User konnte über apiUrl bzw. SMTP/IMAP-Server-Felder
  Connections zu Cloud-Metadata-Endpoints (169.254.169.254,
  metadata.google.internal etc.) auslösen. Internal-Port-Scan
  über Timing-Differenzen war messbar.
- Fix: neuer utils/ssrfGuard.ts blockiert pre-flight 169.254.0.0/16,
  0.0.0.0/8, Multicast/Reserved-Ranges, AWS-IPv6-Metadata,
  IPv6-Link-Local und Cloud-Metadata-Hostnames.
  Loopback (127.0.0.0/8) bleibt erlaubt – legitime Plesk/Postfix-
  Setups sollen weiter funktionieren.

🔒 Logout-Endpoint POST /api/auth/logout
- Setzt tokenInvalidatedAt / portalTokenInvalidatedAt auf jetzt.
  Auth-Middleware prüft das Feld bereits und lehnt Tokens mit
  iat davor ab. Ohne diesen Endpoint blieb ein "abgemeldeter"
  JWT bis Expiry (7d) gültig.

Live-verifiziert:
- 169.254.169.254 / metadata.google.internal / 0.0.0.0 → 400
- 127.0.0.1 (Plesk-Fall) weiter erlaubt
- /me vor Logout 200, nach Logout 401 "Sitzung ungültig"

Geprüft + sauber (Runde 7, kein Bug):
- Public Consent (122-bit Random-UUID nicht brute-force-bar)
- Magic-Bytes-Bypass beim Upload
- PDF manualValues Injection (keine HTML-Render-Surface)
- Query-Filter-Override (?customerId=X) – vom Portal-Filter ignoriert
- Audit-Logs / Email-Config / Backup-Endpoints als Portal: 403

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 07:47:26 +02:00

22 KiB
Raw Blame History

📋 OpenCRM Todo-Liste


🔜 Offen

Manuelle Tests (vor Release durchklicken)

Checklisten für Security + Email-Log-System stehen in docs/TESTING.md. Einmal komplett durchlaufen vor v1.0.0-Release.

🚀 SaaS-Ausbau: Instance-per-Customer + Admin-Portal + GoCardless

Vision: OpenCRM als SaaS anbieten. Jeder Kunde bekommt seine eigene isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung über ein zentrales Admin-Portal.

Architektur-Entscheidung: Weg C (Instance-per-Customer)

  • Pro Kunde eine eigene Docker-Instanz mit eigener DB
  • Keine tenantId im CRM-Code → keine Security-Risiken durch vergessene Filter
  • Komplette Datenisolation (DSGVO-freundlich)
  • Updates können gestaffelt ausgerollt werden (erst 10% testen)
  • Bei Kündigung: Docker-Image + DB-Export als "Mitnehm-Paket"

Bewusst NICHT dabei: eigener Mailserver. Stattdessen Plesk-Integration (die wir schon haben) Kunde bekommt Mail-Zugang über unseren Plesk bei Bedarf.


Admin-Portal (separate App, neben den CRM-Instanzen):

  • Kundenverwaltung: wer hat welchen Plan, Status (Trial/Active/Suspended/Cancelled)
  • "Neuen Kunden anlegen" → Provisioning-Script
    • DB anlegen (Master-DB kennt die Mapping)
    • Docker-Container starten
    • Subdomain konfigurieren (kundenname.deincrm.de via Caddy/Traefik)
    • Initial-Admin-Account erstellen + Einladungs-Email senden
    • Optional: Factory-Defaults für Stammdaten einspielen
  • GoCardless-Integration (Webhook + Dashboard)
  • Instanz-Management: Pause/Resume bei Zahlungsproblemen
  • Logs & Metriken pro Instanz (optional)
  • Support-Bereich (Tickets? oder einfach E-Mail)

Abrechnung mit GoCardless (gocardless.com):

  • Zahlungsmethoden: SEPA-Lastschrift (Hauptfokus) + Kreditkarte (über GoCardless Embedded/Success)
  • 30 Tage kostenlose Testphase ohne Zahlungsmittel
  • Nach Trial: Mandats-Erfassung → regelmäßige Abbuchung
  • Mehrere Pläne (z.B. Basic / Pro / Enterprise) mit unterschiedlichen Features
  • Webhook-Endpoint im Admin-Portal:
    • payment_confirmed → Instanz aktiv lassen
    • payment_failed → Banner im CRM, nach X Tagen pausieren
    • mandate_cancelled → Kündigungs-Flow
  • Rechnungsstellung: GoCardless liefert Zahlungsbelege, aber echte Rechnungen (mit USt-ID, Rechnungsnummer etc.) müssen wir selbst generieren (evtl. über das existierende PDF-Template-System aus dem CRM nutzen)

Provisioning-Flow (grober Entwurf):

  1. Kunde registriert sich auf Landing Page (Name, Firma, E-Mail, Wunsch-Subdomain)
  2. Admin-Portal: Trial-Instanz starten
    • DB erstellen, Docker-Container hochfahren, Caddy-Config für Subdomain
    • Einladungs-Email mit Admin-Login + Passwort-Reset-Link
  3. Tag 25: Erinnerungs-Email "Deine Trial läuft bald ab"
  4. Tag 30: Banner im CRM "Jetzt bezahlen oder pausieren"
  5. Kunde erfasst GoCardless-Mandat im Admin-Portal-Login
  6. Bei erfolgreicher Zahlung: Instanz bleibt aktiv
  7. Bei fehlender Zahlung nach 7 Tagen: Instanz pausiert (DB bleibt, UI zeigt Hinweis)

Technische Bausteine für später:

  • Master-DB mit Tenant-Tabelle (Name, Subdomain, DB-Name, Plan, Status, GoCardlessIDs)
  • Caddy oder Traefik als Reverse-Proxy mit Auto-SSL (Let's Encrypt)
  • Docker-Orchestrierung: einzelne docker-compose.yml pro Kunde oder Docker-Swarm/K8s
  • Backup-Strategie: pro Tenant separate Backups + zentrale Master-DB-Backups
  • Monitoring: ein Fail macht nicht alle down, aber wir müssen es mitbekommen
  • Logs zentral: z.B. Loki + Grafana für aggregierte Logs aller Instanzen

Grobe Zeitschätzung:

  • Admin-Portal (MVP): ~1 Woche
  • GoCardless-Integration + Webhooks: ~3-5 Tage
  • Provisioning-Automatisierung (Docker + Caddy): ~1 Woche
  • Landing Page + Checkout: ~3-5 Tage
  • Tests + Polishing: ~1 Woche
  • Gesamt: ~3-4 Wochen

Vorbereitung JETZT (einfach, macht später Arbeit leichter):

  • Factory-Defaults System (schon erledigt, hilft beim Provisioning)
  • Domain/Label dynamisch per Provider (schon erledigt)
  • Docker-Compose aufräumen, Env-Variablen dokumentieren (klein, ein Tag)
  • Backup-Script robust + wiederherstellbar (haben wir schon weitgehend)

Erledigt