# BreakPilot Authentifizierung & Autorisierung ## Uebersicht BreakPilot verwendet einen **Hybrid-Ansatz** fuer Authentifizierung und Autorisierung: ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ AUTHENTIFIZIERUNG │ │ "Wer bist du?" │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ HybridAuthenticator │ │ │ │ ┌─────────────────────┐ ┌─────────────────────────────────┐ │ │ │ │ │ Keycloak │ │ Lokales JWT │ │ │ │ │ │ (Produktion) │ OR │ (Entwicklung) │ │ │ │ │ │ RS256 + JWKS │ │ HS256 + Secret │ │ │ │ │ └─────────────────────┘ └─────────────────────────────────┘ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ AUTORISIERUNG │ │ "Was darfst du?" │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ rbac.py (Eigenentwicklung) │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌───────────────────┐ │ │ │ │ │ Rollen-Hierarchie│ │ PolicySet │ │ DEFAULT_PERMISSIONS│ │ │ │ │ │ 15+ Rollen │ │ Bundesland- │ │ Matrix │ │ │ │ │ │ - Erstkorrektor │ │ spezifisch │ │ Rolle→Ressource→ │ │ │ │ │ │ - Klassenlehrer │ │ - Niedersachsen │ │ Aktion │ │ │ │ │ │ - Schulleitung │ │ - Bayern │ │ │ │ │ │ │ └─────────────────┘ └─────────────────┘ └───────────────────┘ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ``` ## Warum dieser Ansatz? ### Alternative Loesungen (verworfen) | Tool | Problem fuer BreakPilot | |------|-------------------------| | **Casbin** | Zu generisch fuer Bundesland-spezifische Policies | | **Cerbos** | Overhead: Externer PDP-Service fuer ~15 Rollen ueberdimensioniert | | **OpenFGA** | Zanzibar-Modell optimiert fuer Graph-Beziehungen, nicht Hierarchien | | **Keycloak RBAC** | Kann keine ressourcen-spezifischen Zuweisungen (User X ist Erstkorrektor fuer Package Y) | ### Vorteile des Hybrid-Ansatzes 1. **Keycloak fuer Authentifizierung:** - Bewährtes IAM-System - SSO, Federation, MFA - Apache-2.0 Lizenz 2. **Eigenes rbac.py fuer Autorisierung:** - Domaenenspezifische Logik (Korrekturkette, Zeugnis-Workflow) - Bundesland-spezifische Regeln - Zeitlich begrenzte Zuweisungen - Key-Sharing fuer verschluesselte Klausuren --- ## Authentifizierung (auth/keycloak_auth.py) ### Konfiguration ```python # Entwicklung: Lokales JWT (Standard) JWT_SECRET=your-secret-key # Produktion: Keycloak KEYCLOAK_SERVER_URL=https://keycloak.breakpilot.app KEYCLOAK_REALM=breakpilot KEYCLOAK_CLIENT_ID=breakpilot-backend KEYCLOAK_CLIENT_SECRET=your-client-secret ``` ### Token-Erkennung Der `HybridAuthenticator` erkennt automatisch den Token-Typ: ```python # Keycloak-Token (RS256) { "iss": "https://keycloak.breakpilot.app/realms/breakpilot", "sub": "user-uuid", "realm_access": {"roles": ["teacher", "admin"]}, ... } # Lokales JWT (HS256) { "iss": "breakpilot", "user_id": "user-uuid", "role": "admin", ... } ``` ### FastAPI Integration ```python from auth import get_current_user @app.get("/api/protected") async def protected_endpoint(user: dict = Depends(get_current_user)): # user enthält: user_id, email, role, realm_roles, tenant_id return {"user_id": user["user_id"]} ``` --- ## Autorisierung (klausur-service/backend/rbac.py) ### Rollen (15+) | Rolle | Beschreibung | Bereich | |-------|--------------|---------| | `erstkorrektor` | Erster Prüfer | Klausur | | `zweitkorrektor` | Zweiter Prüfer | Klausur | | `drittkorrektor` | Dritter Prüfer | Klausur | | `klassenlehrer` | Klassenleitung | Zeugnis | | `fachlehrer` | Fachlehrkraft | Noten | | `fachvorsitz` | Fachkonferenz-Leitung | Fachschaft | | `schulleitung` | Schulleiter/in | Schule | | `zeugnisbeauftragter` | Zeugnis-Koordination | Zeugnis | | `sekretariat` | Verwaltung | Schule | | `data_protection_officer` | DSB | DSGVO | | ... | | | ### Ressourcentypen (25+) ```python class ResourceType(str, Enum): EXAM_PACKAGE = "exam_package" # Klausurpaket STUDENT_SUBMISSION = "student_submission" CORRECTION = "correction" ZEUGNIS = "zeugnis" FACHNOTE = "fachnote" KOPFNOTE = "kopfnote" BEMERKUNG = "bemerkung" ... ``` ### Aktionen (17) ```python class Action(str, Enum): CREATE = "create" READ = "read" UPDATE = "update" DELETE = "delete" SIGN_OFF = "sign_off" # Freigabe BREAK_GLASS = "break_glass" # Notfall-Zugriff SHARE_KEY = "share_key" # Schlüssel teilen ... ``` ### Permission-Pruefung ```python from klausur_service.backend.rbac import PolicyEngine engine = PolicyEngine() # Pruefe ob User X Klausur Y korrigieren darf allowed = engine.check_permission( user_id="user-uuid", action=Action.UPDATE, resource_type=ResourceType.CORRECTION, resource_id="klausur-uuid" ) ``` --- ## Bundesland-spezifische Policies ```python @dataclass class PolicySet: bundesland: str abitur_type: str # "landesabitur" | "zentralabitur" # Korrekturkette korrektoren_anzahl: int # 2 oder 3 anonyme_erstkorrektur: bool # Sichtbarkeit zk_visibility_mode: ZKVisibilityMode # BLIND | SEMI | FULL eh_visibility_mode: EHVisibilityMode # Zeugnis kopfnoten_enabled: bool ... ``` ### Beispiel: Niedersachsen ```python NIEDERSACHSEN_POLICY = PolicySet( bundesland="niedersachsen", abitur_type="landesabitur", korrektoren_anzahl=2, anonyme_erstkorrektur=True, zk_visibility_mode=ZKVisibilityMode.BLIND, eh_visibility_mode=EHVisibilityMode.SUMMARY_ONLY, kopfnoten_enabled=True, ) ``` --- ## Workflow-Beispiele ### Klausurkorrektur-Workflow ``` 1. Lehrer laedt Klausuren hoch └── Rolle: "lehrer" + Action.CREATE auf EXAM_PACKAGE 2. Erstkorrektor korrigiert └── Rolle: "erstkorrektor" (ressourcen-spezifisch) + Action.UPDATE auf CORRECTION 3. Zweitkorrektor ueberprueft └── Rolle: "zweitkorrektor" + Action.READ auf CORRECTION └── Policy: zk_visibility_mode bestimmt Sichtbarkeit 4. Drittkorrektor (bei Abweichung) └── Rolle: "drittkorrektor" + Action.SIGN_OFF ``` ### Zeugnis-Workflow ``` 1. Fachlehrer traegt Noten ein └── Rolle: "fachlehrer" + Action.CREATE auf FACHNOTE 2. Klassenlehrer prueft └── Rolle: "klassenlehrer" + Action.READ auf ZEUGNIS └── Action.SIGN_OFF freigeben 3. Zeugnisbeauftragter final └── Rolle: "zeugnisbeauftragter" + Action.SIGN_OFF 4. Schulleitung unterzeichnet └── Rolle: "schulleitung" + Action.SIGN_OFF ``` --- ## Dateien | Datei | Beschreibung | |-------|--------------| | `backend/auth/__init__.py` | Auth-Modul Exports | | `backend/auth/keycloak_auth.py` | Hybrid-Authentifizierung | | `klausur-service/backend/rbac.py` | Autorisierungs-Engine | | `backend/rbac_api.py` | REST API fuer Rollenverwaltung | --- ## Konfiguration ### Entwicklung (ohne Keycloak) ```bash # .env ENVIRONMENT=development JWT_SECRET=dev-secret-32-chars-minimum-here ``` ### Produktion (mit Keycloak) ```bash # .env ENVIRONMENT=production JWT_SECRET= KEYCLOAK_SERVER_URL=https://keycloak.breakpilot.app KEYCLOAK_REALM=breakpilot KEYCLOAK_CLIENT_ID=breakpilot-backend KEYCLOAK_CLIENT_SECRET= ``` --- ## Sicherheitshinweise 1. **Secrets niemals im Code** - Immer Umgebungsvariablen verwenden 2. **JWT_SECRET in Produktion** - Mindestens 32 Bytes, generiert mit `openssl rand -hex 32` 3. **Keycloak HTTPS** - KEYCLOAK_VERIFY_SSL=true in Produktion 4. **Token-Expiration** - Keycloak-Tokens kurz halten (5-15 Minuten) 5. **Audit-Trail** - Alle Berechtigungspruefungen werden geloggt