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 Functioneurope-west3) - Schedule:
0 2 * * *UTC (override viasystem_settings/backup_settings.schedule) - Bucket:
gs://${PROJECT_ID}-firestore-backup(override übersystem_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_countmit Filterresponse_code_class != "2xx" - Aggregation:
aligner=ALIGN_RATE,reducer=REDUCE_SUMper 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"(vonrate_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, Fieldseverity == "CRITICAL". Praktischer ist eine Logs-based Metric direkt aus den Function-Logs (secureLogger.errorschreibt 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/infoschreibt strukturierte Felder; PII wird viasecureLogger-Redactor entfernt.- Custom-Felder, die in Alerts genutzt werden:
event– z. B.rate_limit_exceeded,auth_failurefn– Funktionsname (für SMTP-Filter)connectorId,customerId– Routing in Dashboards- Niemals raw Tokens/Passwörter loggen. Code-Review wird durch ESLint-Regel
no-pii-loggingautomatisiert.
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 |