// Package policyapi implementiert RBAC-06: einen HTTP-Endpunkt, der // Core RBAC-02s Enforcer.Authorize für andere, physisch getrennte // Go-Module (DMS, Mail, Archive) zugänglich macht — dieselbe // Entscheidung wie der direkte Enforcer-Aufruf, nur per HTTP statt // In-Process. package policyapi import ( "crypto/sha256" "crypto/subtle" "net/http" ) // RequireServiceToken authentifiziert den Aufrufer service-zu-service // über einen geteilten Token (Umgebungsvariable, nie im Code — siehe // Ticket-Abschlussregel), timing-safe verglichen (dieselbe // Referenzimplementierung wie AUD-02: subtle.ConstantTimeCompare, // projektweite Konvention für jeden sicherheitsrelevanten Vergleich). // Bewusst KEIN vollwertiges Credential-Ausstellungssystem // (moduleregistry.Provision/Authenticate) — dieser Endpunkt braucht // keine Modul-Aktivierungsverwaltung, nur einen einzelnen, über // Konfiguration verteilten Zugangsschlüssel (Akzeptanzkriterium 2). func RequireServiceToken(expectedToken string, next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { got := r.Header.Get("X-Service-Token") if got == "" || !timingSafeEqual(got, expectedToken) { http.Error(w, "authentifizierung fehlgeschlagen: gültiges X-Service-Token erforderlich", http.StatusUnauthorized) return } next(w, r) } } func timingSafeEqual(a, b string) bool { ha := sha256.Sum256([]byte(a)) hb := sha256.Sum256([]byte(b)) return subtle.ConstantTimeCompare(ha[:], hb[:]) == 1 }