Zum Inhalt

Monitoring & Alerting (P7)

Ziel: Live-Betrieb mit minimal überwachten Risiken. Diese Datei ist Ops-Runbook für die GCP-Console-Setup-Schritte. Alle Alerts sollen pro Tenant-Projekt eingerichtet werden (Single-Tenant-Architektur).

1. Daily Firestore Backup

  • Job: scheduledFirestoreBackup (Cloud Function europe-west3)
  • Schedule: 0 2 * * * UTC (override via system_settings/backup_settings.schedule)
  • Bucket: gs://${PROJECT_ID}-firestore-backup (override über system_settings/backup_settings.bucketOverride)

One-time Setup pro Projekt

PROJECT_ID="<tenant-projekt>"

# Bucket anlegen (EU multi-region)
gsutil mb -l eu -p "$PROJECT_ID" "gs://${PROJECT_ID}-firestore-backup"

# Lifecycle: Backups älter als 35 Tage automatisch löschen
cat > /tmp/lifecycle.json <<'JSON'
{
  "lifecycle": {
    "rule": [
      { "action": { "type": "Delete" }, "condition": { "age": 35 } }
    ]
  }
}
JSON
gsutil lifecycle set /tmp/lifecycle.json "gs://${PROJECT_ID}-firestore-backup"

# IAM für den Default-Compute-SA
SA="$(gcloud projects describe "$PROJECT_ID" --format='value(projectNumber)')-compute@developer.gserviceaccount.com"

gcloud projects add-iam-policy-binding "$PROJECT_ID" \
  --member="serviceAccount:${SA}" \
  --role="roles/datastore.importExportAdmin"

gsutil iam ch "serviceAccount:${SA}:roles/storage.admin" \
  "gs://${PROJECT_ID}-firestore-backup"

Restore

# Letztes Backup-Verzeichnis ermitteln
gsutil ls "gs://${PROJECT_ID}-firestore-backup/exports/" | tail -1

# Import (Achtung: schreibt in dieselbe DB!)
gcloud firestore import \
  "gs://${PROJECT_ID}-firestore-backup/exports/2024-12-31/2024-12-31T02:00:00_12345/"

2. Cloud Monitoring – Alert-Policies

Alle Alerts: Notification-Channel security-alerts@<kunde> (E-Mail) + optional PagerDuty/Slack. In der GCP-Console unter Monitoring → Alerting → Create Policy.

2.1 Function Error Rate > 5 %

  • Resource type: cloud_run_revision (Functions v2 laufen auf Cloud Run)
  • Metric: run.googleapis.com/request_count mit Filter response_code_class != "2xx"
  • Aggregation: aligner=ALIGN_RATE, reducer=REDUCE_SUM per Service
  • Condition: Verhältnis (5xx + 4xx ohne 401/403) zu Gesamt > 0.05 für 5 min
  • Auto-close: 30 min

2.2 Auth-Failure-Spike > 50 / min

  • Resource: Logs-based metric auf _rateLimits-Schreibzugriffe oder Cloud Logging Filter: resource.type="cloud_function" AND jsonPayload.event="auth_failure"
  • Threshold: count > 50 in 1 min
  • Hinweis: Quelle ist AuditLogger.logFailure({ action: "auth_*" }).

2.3 RateLimit-Sättigung

  • Logs-based metric: Filter jsonPayload.event="rate_limit_exceeded" (von rate_limiter.js).
  • Alert: > 100 Hits / 5 min für eine Action → Hinweis auf Bot/Brute-Force.

2.4 AuditLog – CRITICAL Events

  • Logs-based metric: Firestore-Collection auditLogs, Field severity == "CRITICAL". Praktischer ist eine Logs-based Metric direkt aus den Function-Logs (secureLogger.error schreibt strukturiert).
  • Alert: count > 0 im 5-min-Fenster → sofortige Mail.

2.5 SMTP-Send-Failures

  • Filter: resource.type="cloud_function" AND jsonPayload.fn IN ("sendCustomerInvitationEmail","sendPriceListEmail","sendDemoRequestEmail") AND severity>=ERROR
  • Threshold: > 5 Fehlschläge / 10 min
  • Hinweis: typische Ursachen: Strato-Quota, falsches Secret, App-Passwort abgelaufen.

3. Operational Logging-Conventions

  • secureLogger.error/warn/info schreibt strukturierte Felder; PII wird via secureLogger-Redactor entfernt.
  • Custom-Felder, die in Alerts genutzt werden:
  • event – z. B. rate_limit_exceeded, auth_failure
  • fn – Funktionsname (für SMTP-Filter)
  • connectorId, customerId – Routing in Dashboards
  • Niemals raw Tokens/Passwörter loggen. Code-Review wird durch ESLint-Regel no-pii-logging automatisiert.

4. Pre-Go-Live-Check

Check Verantwortlich
Bucket + Lifecycle in jedem Tenant-Projekt vorhanden DevOps
scheduledFirestoreBackup deployed & 1× manuell getriggert DevOps
5 Monitoring-Alerts aktiv mit Notification-Channel DevOps
Restore-Probe in Staging dokumentiert DevOps
system_settings/backup_settings.enabled=true (oder Default) Operations