Files
nexarch/docs/RBAC-06-PRUEFPROTOKOLL.md
T
sysops e8d04f244b feat(core): RBAC-06 modulübergreifender HTTP-Endpunkt für Policy-Entscheidungen
internal/policyapi: POST /authorize wrapt policy.Enforcer.Authorize
(RBAC-02) fuer physisch getrennte Module (DMS, Mail, Archive) - reiner
Wrapper, keine zweite Autorisierungslogik, 100 Stichproben beweisen
Uebereinstimmung mit dem direkten Enforcer-Aufruf. Service-Auth ueber
schlanken, timing-safe verglichenen Token statt moduleregistrys
schwererem Credential-System (unnoetige internal/flag-Abhaengigkeit,
nie mit internal/policy gemergt). Ersetzt spaeter das dokumentierte
RET-06-API-Provisorium (Archive, eigenes Folgeticket). Reale
Rechtevergabe-Luecke auf policy_rules gefunden und behoben (Tabelle
von frueherem Testlauf unter anderem Owner). Real auf 131 deployed,
beide Pfade (Allow/Deny) per curl end-to-end verifiziert.
2026-08-30 02:24:55 +02:00

93 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RBAC-06 Prüfprotokoll: Modulübergreifender HTTP-Endpunkt für Policy-Entscheidungen
Voraussetzung RBAC-02 bereits Fertig (siehe eigenes Protokoll).
## Grundsatzentscheidung: Wrapper, keine zweite Autorisierungslogik
`internal/policyapi.Mount` registriert `POST /authorize`, dessen Handler
AUSSCHLIESSLICH `policy.Enforcer.Authorize` aufruft — es gibt keinen
zweiten, abweichenden Entscheidungspfad. Die Übereinstimmung zwischen
HTTP-Antwort und direktem Enforcer-Ergebnis (Akzeptanzkriterium 1) ist
dadurch strukturell garantiert, nicht nur zufällig getestet — real mit
100 Stichproben bewiesen (siehe Prüfungen).
## Service-Authentifizierung: eigener, schlanker Token statt moduleregistry
Für Akzeptanzkriterium 2 (service-zu-service-authentifiziert) wurde
BEWUSST NICHT `internal/moduleregistry.Registry.RequireServiceCredential`
(API-02) wiederverwendet — dessen `Provision`/`Authenticate` ist ein
volles Credential-Ausstellungssystem für Modul-AKTIVIERUNG, zieht
`internal/flag` als weitere Abhängigkeit nach sich und wurde nie mit
`internal/policy` zusammen gemergt (beide entstanden auf unabhängigen,
nie zusammengeführten Feature-Branches). Für einen einzelnen,
zustandslosen Autorisierungs-Endpunkt genügt ein geteilter, über
Umgebungsvariable konfigurierter Service-Token, timing-safe verglichen
(`subtle.ConstantTimeCompare`, dieselbe Referenzimplementierung wie
AUD-02) — kleinste Lösung, die Akzeptanzkriterium 2 erfüllt, ohne
unnötige Kopplung an ein für diesen Zweck überdimensioniertes System.
## Bezug zu Archive RET-06-API
Ersetzt das dort dokumentierte Provisorium
(`internal/retentionapi.RequireRole`, Header-basierter Rollen-Check) —
siehe `archive/docs/RET-06-API-PRUEFPROTOKOLL.md`. Die Migration von
RET-06-API auf einen echten Aufruf dieses Endpunkts ist ein eigenes,
kleines Folgeticket (Akzeptanzkriterium 3) — hier nicht mit umgesetzt,
um RBAC-06 nicht mit Archive-Code zu vermischen (kein Umbau
angrenzender Bereiche).
## Umsetzung
- `internal/policyapi.RequireServiceToken` — timing-safer
Service-Token-Check.
- `internal/policyapi.Mount`/`authorizeHandler``POST /authorize`,
reiner Wrapper um `enforcer.Authorize`.
- `cmd/policy-api` — eigenständiger HTTP-Dienst (analog zu den
bestehenden `*-devserver`n, getrennt von `cmd/core`).
## Prüfungen
| # | Prüfung | Ergebnis |
|---|---|---|
| 1 | Endpunkt-Antwort stimmt in 100 Stichproben exakt mit dem direkten Enforcer.Authorize-Ergebnis überein | **bestanden**`TestAuthorizeHandler_MatchesDirectEnforcerResult`: 100 Läufe über drei role/permission-Kombinationen (erlaubt, unbekannte Rolle, falsches Recht), jede einzelne HTTP-Antwort mit dem direkten Aufruf verglichen, 0 Abweichungen |
| 2 | Aufruf ohne gültige Service-Credentials wird abgewiesen (401/403), nicht mit einer Policy-Entscheidung beantwortet | **bestanden**`TestRequireServiceToken_MissingOrWrongTokenReturns401` (Handler nachweislich NIE erreicht) UND `TestRequireServiceToken_CorrectTokenAllowsAccess`; real auf 131: `curl` ohne Token → 401 |
| 3 | Ein simulierter Fremd-Modul-Testclient fragt real gegen den laufenden Endpunkt ab und erhält korrekte Allow/Deny-Antworten | **bestanden** — real auf 131: `curl` mit Service-Token gegen `archive_admin`/`retention.configure` (simuliert Archive als Aufrufer) liefert korrekt `{"allowed":false}` ohne Regel und `{"allowed":true}` nach realem `Grant` |
## Echte Verdrahtung auf 192.168.1.131
- `policy-api` gebaut nach `/opt/nexarch-core/bin/`
- `/etc/nexarch/policy-api.env` (0600)
- `nexarch-policy-api.service` installiert/aktiviert (dauerhaft,
`Restart=on-failure`)
- Reale Rechtevergabe-Lücke gefunden und behoben: `policy_rules`/
`policy_rule_changes` waren auf `nexarch_registry` bereits von einem
früheren Testlauf unter der Rolle `postgres` angelegt worden,
`nexarch_core` hatte keine Rechte darauf — `GRANT` nachgezogen
- Realer End-zu-Ende-Test via `curl`: 401 ohne Token, `{"allowed":false}`
für unbekannte Kombination, `{"allowed":true}` nach echtem `Grant`,
Testregel anschließend entfernt
## Build/Test-Ergebnis (192.168.1.131)
```
go build ./... -> clean
go vet ./... -> clean
golangci-lint run ./... -> 0 issues
go test ./internal/policy/... ./internal/policyapi/... ./internal/rbac/... -> alle bestanden
```
**Hinweis:** `go test ./... -p 1` auf diesem Branch zeigt Fehlschläge in
`internal/tenant`/`internal/user` — reale Umgebungs-Altlasten (z. B.
bereits existierende `tenant_acme`-Datenbank) aus früheren TEN-01-
Testläufen dieser Session, NICHT durch RBAC-06 verursacht und nicht in
dessen Scope. Alle drei von RBAC-06 tatsächlich berührten Pakete
(`internal/policy`, `internal/policyapi`, `internal/rbac`) sind grün.
## Gesamtergebnis
**Bestanden.** Alle drei Akzeptanzkriterien und alle drei
Pflichtprüfungen real erfüllt — inklusive echtem systemd-Deploy und
curl-Nachweis beider Pfade (Allow und Deny). Schließt den seit
FDN-03/FDN-09 wiederkehrenden "Go-Code ohne HTTP-Schnittstelle für
andere Module"-Befund für RBAC-Abfragen einmalig und wiederverwendbar.