# SDK Protection Middleware

## 1. Worum geht es?

Die SDK Protection Middleware schuetzt die Compliance-SDK-Endpunkte vor einer bestimmten Art von Angriff: der **systematischen Enumeration**. Was bedeutet das?

> *Ein Wettbewerber registriert sich als zahlender Kunde und laesst ein Skript langsam und verteilt alle TOM-Controls, alle Pruefaspekte und alle Assessment-Kriterien abfragen. Aus den Ergebnissen rekonstruiert er die gesamte Compliance-Framework-Logik.*

Der klassische Rate Limiter (100 Requests/Minute) hilft hier nicht, weil ein cleverer Angreifer langsam vorgeht -- vielleicht nur 20 Anfragen pro Minute, dafuer systematisch und ueber Stunden. Die SDK Protection erkennt solche Muster und reagiert darauf.

!!! info "Kern-Designprinzip"
    **Normale Nutzer merken nichts.** Ein Lehrer, der im TOM-Modul arbeitet, greift typischerweise auf 3-5 Kategorien zu und wiederholt Anfragen an gleiche Endpunkte. Ein Angreifer durchlaeuft dagegen 40+ Kategorien in alphabetischer Reihenfolge. Genau diesen Unterschied erkennt die Middleware.

---

## 2. Wie funktioniert der Schutz?

Die Middleware nutzt ein **Anomaly-Score-System**. Jeder Benutzer hat einen Score, der bei 0 beginnt. Verschiedene verdaechtige Verhaltensweisen erhoehen den Score. Ueber die Zeit sinkt er wieder ab. Je hoeher der Score, desto staerker wird der Benutzer gebremst.

Man kann es sich wie eine Ampel vorstellen:

| Score | Ampel | Wirkung | Beispiel |
|-------|-------|---------|----------|
| 0-29 | Gruen | Keine Einschraenkung | Normaler Nutzer |
| 30-59 | Gelb | 1-3 Sekunden Verzoegerung | Leicht auffaelliges Muster |
| 60-84 | Orange | 5-10 Sekunden Verzoegerung, reduzierte Details | Deutlich verdaechtiges Verhalten |
| 85+ | Rot | Zugriff blockiert (HTTP 429) | Sehr wahrscheinlich automatisierter Angriff |

### Score-Zerfall

Der Score sinkt automatisch: Alle 5 Minuten wird er mit dem Faktor 0,95 multipliziert. Ein Score von 60 faellt also innerhalb einer Stunde auf etwa 30 -- wenn kein neues verdaechtiges Verhalten hinzukommt.

---

## 3. Was wird erkannt?

Die Middleware erkennt fuenf verschiedene Anomalie-Muster:

### 3.1 Hohe Kategorie-Diversitaet

**Was:** Ein Benutzer greift innerhalb einer Stunde auf mehr als 40 verschiedene SDK-Kategorien zu.

**Warum verdaechtig:** Ein normaler Nutzer arbeitet in der Regel mit 3-10 Kategorien. Wer systematisch alle durchlaeuft, sammelt vermutlich Daten.

**Score-Erhoehung:** +15

```
Normal:   tom/access-control → tom/access-control → tom/encryption → tom/encryption
                               (3 verschiedene Kategorien in einer Stunde)

Verdaechtig: tom/access-control → tom/encryption → tom/pseudonymization → tom/integrity
             → tom/availability → tom/resilience → dsfa/threshold → dsfa/necessity → ...
                               (40+ verschiedene Kategorien in einer Stunde)
```

### 3.2 Burst-Erkennung

**Was:** Ein Benutzer sendet mehr als 15 Anfragen an die gleiche Kategorie innerhalb von 2 Minuten.

**Warum verdaechtig:** Selbst ein eifriger Nutzer klickt nicht 15-mal pro Minute auf denselben Endpunkt. Das deutet auf automatisiertes Scraping hin.

**Score-Erhoehung:** +20

### 3.3 Sequentielle Enumeration

**Was:** Die letzten 10 aufgerufenen Kategorien sind zu mindestens 70% in alphabetischer oder numerischer Reihenfolge.

**Warum verdaechtig:** Menschen springen zwischen Kategorien -- sie arbeiten thematisch, nicht alphabetisch. Ein Skript dagegen iteriert oft ueber eine sortierte Liste.

**Score-Erhoehung:** +25

```
Verdaechtig: assessment_general → compliance_general → controls_general
             → dsfa_measures → dsfa_necessity → dsfa_residual → dsfa_risks
             → dsfa_threshold → eh_general → namespace_general
             (alphabetisch sortiert = Skript-Verhalten)
```

### 3.4 Ungewoehnliche Uhrzeiten

**Was:** Anfragen zwischen 0:00 und 5:00 Uhr UTC.

**Warum verdaechtig:** Lehrer arbeiten tagsüber. Wer um 3 Uhr morgens SDK-Endpunkte abfragt, ist wahrscheinlich ein automatisierter Prozess.

**Score-Erhoehung:** +10

### 3.5 Multi-Tenant-Zugriff

**Was:** Ein Benutzer greift innerhalb einer Stunde auf mehr als 3 verschiedene Mandanten (Tenants) zu.

**Warum verdaechtig:** Ein normaler Nutzer gehoert zu einem Mandanten. Wer mehrere durchprobiert, koennte versuchen, mandantenuebergreifend Daten zu sammeln.

**Score-Erhoehung:** +15

---

## 4. Quota-System (Mengenbegrenzung)

Zusaetzlich zum Anomaly-Score gibt es klassische Mengenbegrenzungen in vier Zeitfenstern:

| Tier | pro Minute | pro Stunde | pro Tag | pro Monat |
|------|-----------|-----------|---------|-----------|
| **Free** | 30 | 500 | 3.000 | 50.000 |
| **Standard** | 60 | 1.500 | 10.000 | 200.000 |
| **Enterprise** | 120 | 5.000 | 50.000 | 1.000.000 |

Wenn ein Limit in irgendeinem Zeitfenster ueberschritten wird, erhaelt der Nutzer sofort HTTP 429 -- unabhaengig vom Anomaly-Score.

---

## 5. Architektur

### Datenfluss eines SDK-Requests

```
Request kommt an
     │
     ▼
┌─────────────────────────────────────────────────────────────┐
│  Ist der Pfad geschuetzt?                                    │
│  (/api/sdk/*, /api/v1/tom/*, /api/v1/dsfa/*, ...)           │
│  Nein → direkt weiterleiten                                  │
└──────────────┬──────────────────────────────────────────────┘
               │ Ja
               ▼
┌─────────────────────────────────────────────────────────────┐
│  User + Tier + Kategorie extrahieren                         │
│  (aus Session, API-Key oder X-SDK-Tier Header)               │
└──────────────┬──────────────────────────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────────────────────────┐
│  Multi-Window Quota pruefen                                  │
│  (Minute / Stunde / Tag / Monat)                             │
│  Ueberschritten → HTTP 429 zurueck                          │
└──────────────┬──────────────────────────────────────────────┘
               │ OK
               ▼
┌─────────────────────────────────────────────────────────────┐
│  Anomaly-Score laden (aus Valkey)                            │
│  Zeitbasierten Zerfall anwenden (×0,95 alle 5 min)           │
└──────────────┬──────────────────────────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────────────────────────┐
│  Anomalie-Detektoren ausfuehren:                             │
│  ├── Diversity-Tracking     (+15 wenn >40 Kategorien/h)      │
│  ├── Burst-Detection        (+20 wenn >15 gleiche/2min)      │
│  ├── Sequential-Enumeration (+25 wenn sortiert)              │
│  ├── Unusual-Hours          (+10 wenn 0-5 Uhr UTC)           │
│  └── Multi-Tenant           (+15 wenn >3 Tenants/h)          │
└──────────────┬──────────────────────────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────────────────────────┐
│  Throttle-Level bestimmen                                    │
│  Level 3 (Score ≥85) → HTTP 429                              │
│  Level 2 (Score ≥60) → 5-10s Delay + reduzierte Details      │
│  Level 1 (Score ≥30) → 1-3s Delay                            │
│  Level 0             → keine Einschraenkung                  │
└──────────────┬──────────────────────────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────────────────────────┐
│  Request weiterleiten                                        │
│  Response-Headers setzen:                                    │
│  ├── X-SDK-Quota-Remaining-Minute/Hour                       │
│  ├── X-SDK-Throttle-Level                                    │
│  ├── X-SDK-Detail-Reduced (bei Level ≥2)                     │
│  └── X-BP-Trace (HMAC-Watermark)                             │
└─────────────────────────────────────────────────────────────┘
```

### Valkey-Datenstrukturen

Die Middleware speichert alle Tracking-Daten in Valkey (Redis-Fork). Wenn Valkey nicht erreichbar ist, wird automatisch auf eine In-Memory-Implementierung zurueckgefallen.

| Zweck | Valkey-Typ | Key-Muster | TTL |
|-------|-----------|------------|-----|
| Quota pro Zeitfenster | Sorted Set | `sdk_protect:quota:{user}:{window}` | Fenster + 10s |
| Kategorie-Diversitaet | Set | `sdk_protect:diversity:{user}:{stunde}` | 3660s |
| Burst-Tracking | Sorted Set | `sdk_protect:burst:{user}:{kategorie}` | 130s |
| Sequenz-Tracking | List | `sdk_protect:seq:{user}` | 310s |
| Anomaly-Score | Hash | `sdk_protect:score:{user}` | 86400s |
| Tenant-Tracking | Set | `sdk_protect:tenants:{user}:{stunde}` | 3660s |

### Watermarking

Jede Antwort enthaelt einen `X-BP-Trace` Header mit einem HMAC-basierten Fingerabdruck. Damit kann nachtraeglich nachgewiesen werden, welcher Benutzer wann welche Daten abgerufen hat -- ohne dass der Benutzer den Trace veraendern kann.

---

## 6. Geschuetzte Endpunkte

Die Middleware schuetzt alle Pfade, die SDK- und Compliance-relevante Daten liefern:

| Pfad-Prefix | Bereich |
|-------------|---------|
| `/api/sdk/*` | SDK-Hauptendpunkte |
| `/api/compliance/*` | Compliance-Bewertungen |
| `/api/v1/tom/*` | Technisch-organisatorische Massnahmen |
| `/api/v1/dsfa/*` | Datenschutz-Folgenabschaetzung |
| `/api/v1/vvt/*` | Verarbeitungsverzeichnis |
| `/api/v1/controls/*` | Controls und Massnahmen |
| `/api/v1/assessment/*` | Assessment-Bewertungen |
| `/api/v1/eh/*` | Erwartungshorizonte |
| `/api/v1/namespace/*` | Namespace-Verwaltung |

Nicht geschuetzt sind `/health`, `/metrics` und `/api/health`.

---

## 7. Admin-Verwaltung

Ueber das Admin-Dashboard koennen Anomaly-Scores eingesehen und verwaltet werden:

| Endpoint | Methode | Beschreibung |
|----------|---------|--------------|
| `/api/admin/middleware/sdk-protection/scores` | GET | Aktuelle Anomaly-Scores aller Benutzer |
| `/api/admin/middleware/sdk-protection/stats` | GET | Statistik: Benutzer pro Throttle-Level |
| `/api/admin/middleware/sdk-protection/reset-score/{user_id}` | POST | Score eines Benutzers zuruecksetzen |
| `/api/admin/middleware/sdk-protection/tiers` | GET | Tier-Konfigurationen anzeigen |
| `/api/admin/middleware/sdk-protection/tiers/{name}` | PUT | Tier-Limits aendern |

---

## 8. Dateien und Quellcode

| Datei | Beschreibung |
|-------|--------------|
| `backend/middleware/sdk_protection.py` | Kern-Middleware (~460 Zeilen) |
| `backend/middleware/__init__.py` | Export der Middleware-Klassen |
| `backend/main.py` | Registrierung im FastAPI-Stack |
| `backend/middleware_admin_api.py` | Admin-API-Endpoints |
| `backend/migrations/add_sdk_protection_tables.sql` | Datenbank-Migration |
| `backend/tests/test_middleware.py` | 14 Tests fuer alle Erkennungsmechanismen |

---

## 9. Datenbank-Tabellen

### sdk_anomaly_scores

Speichert Snapshots der Anomaly-Scores fuer Audit und Analyse.

| Spalte | Typ | Beschreibung |
|--------|-----|--------------|
| `id` | UUID | Primaerschluessel |
| `user_id` | VARCHAR(255) | Benutzer-Identifikation |
| `score` | DECIMAL(5,2) | Aktueller Anomaly-Score |
| `throttle_level` | SMALLINT | Aktueller Throttle-Level (0-3) |
| `triggered_rules` | JSONB | Welche Regeln ausgeloest wurden |
| `endpoint_diversity_count` | INT | Anzahl verschiedener Kategorien |
| `request_count_1h` | INT | Anfragen in der letzten Stunde |
| `snapshot_at` | TIMESTAMPTZ | Zeitpunkt des Snapshots |

### sdk_protection_tiers

Konfigurierbare Quota-Tiers, editierbar ueber die Admin-API.

| Spalte | Typ | Beschreibung |
|--------|-----|--------------|
| `tier_name` | VARCHAR(50) | Name des Tiers (free, standard, enterprise) |
| `quota_per_minute` | INT | Maximale Anfragen pro Minute |
| `quota_per_hour` | INT | Maximale Anfragen pro Stunde |
| `quota_per_day` | INT | Maximale Anfragen pro Tag |
| `quota_per_month` | INT | Maximale Anfragen pro Monat |
| `diversity_threshold` | INT | Max verschiedene Kategorien pro Stunde |
| `burst_threshold` | INT | Max gleiche Kategorie in 2 Minuten |

---

## 10. Konfiguration

Die Middleware wird in `main.py` registriert:

```python
from middleware import SDKProtectionMiddleware

app.add_middleware(SDKProtectionMiddleware)
```

Alle Parameter koennen ueber die `SDKProtectionConfig` Dataclass angepasst werden. Die wichtigsten Umgebungsvariablen:

| Variable | Default | Beschreibung |
|----------|---------|--------------|
| `VALKEY_URL` | `redis://localhost:6379` | Verbindung zur Valkey-Instanz |
| `SDK_WATERMARK_SECRET` | (generiert) | HMAC-Secret fuer Watermarks |

---

## 11. Tests

Die Middleware wird durch 14 automatisierte Tests abgedeckt:

```bash
# Alle SDK Protection Tests ausfuehren
docker compose run --rm --no-deps backend \
  python -m pytest tests/test_middleware.py -v -k sdk
```

| Test | Prueft |
|------|--------|
| `test_allows_normal_request` | Normaler Request wird durchgelassen |
| `test_blocks_after_quota_exceeded` | 429 bei Quota-Ueberschreitung |
| `test_diversity_tracking_increments_score` | Viele Kategorien erhoehen den Score |
| `test_burst_detection` | Schnelle gleiche Anfragen erhoehen den Score |
| `test_sequential_enumeration_detection` | Alphabetische Muster werden erkannt |
| `test_progressive_throttling_level_1` | Delay bei Score >= 30 |
| `test_progressive_throttling_level_3_blocks` | Block bei Score >= 85 |
| `test_score_decay_over_time` | Score sinkt ueber die Zeit |
| `test_skips_non_protected_paths` | Nicht-SDK-Pfade bleiben frei |
| `test_watermark_header_present` | X-BP-Trace Header vorhanden |
| `test_fallback_to_inmemory` | Funktioniert ohne Valkey |
| `test_no_user_passes_through` | Anonyme Requests passieren |
| `test_category_extraction` | Korrekte Kategorie-Zuordnung |
| `test_quota_headers_present` | Response-Headers vorhanden |
