mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-21 04:57:48 +00:00
test: add R-round regression and security suite
- fail-on-old regression tests for every shipped fix (R-rounds) - fuzz targets (parseJWT, bearer), concurrency-stress, shuffle-flake guards - coverage-closing contract tests (health-check backend, TLS-posture reuse) - r154 ID-token fixture built from parts to avoid false-positive secret scan
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
package traefikoidc
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestForwardAuthorizedClearsForgedIdentityHeaders is an R95 regression:
|
||||
// forwardAuthorized owns the identity headers it injects upstream. A
|
||||
// client-supplied forged value (e.g. X-User-Groups: admin) must never
|
||||
// survive to the backend when the middleware computes no value for that
|
||||
// header (e.g. an authenticated user with no groups) — otherwise a
|
||||
// backend authorizing on X-User-Groups would be spoofed. Before the fix
|
||||
// the headers were only conditionally Set, never unconditionally Deleted.
|
||||
func TestForwardAuthorizedClearsForgedIdentityHeaders(t *testing.T) {
|
||||
oidc := &TraefikOidc{
|
||||
next: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}),
|
||||
logger: NewLogger("error"),
|
||||
groupClaimName: "groups",
|
||||
roleClaimName: "roles",
|
||||
minimalHeaders: true,
|
||||
}
|
||||
|
||||
// Authenticated user with NO groups and NO roles (p.Claims has neither).
|
||||
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
req.Header.Set("X-User-Groups", "admin")
|
||||
req.Header.Set("X-User-Roles", "superuser")
|
||||
req.Header.Set("X-Forwarded-User", "[email protected]")
|
||||
req.Header.Set("X-Auth-Request-User", "forged")
|
||||
rw := httptest.NewRecorder()
|
||||
p := &principal{Identifier: "realuser", Claims: map[string]interface{}{"sub": "subject"}}
|
||||
oidc.forwardAuthorized(rw, req, p)
|
||||
|
||||
// Backend must not see any client-supplied value the middleware decided not to set.
|
||||
if got := req.Header.Get("X-User-Groups"); got != "" {
|
||||
t.Fatalf("forged X-User-Groups survived to backend: %q", got)
|
||||
}
|
||||
if got := req.Header.Get("X-User-Roles"); got != "" {
|
||||
t.Fatalf("forged X-User-Roles survived to backend: %q", got)
|
||||
}
|
||||
if got := req.Header.Get("X-Auth-Request-User"); got != "" {
|
||||
t.Fatalf("forged X-Auth-Request-User survived to backend: %q", got)
|
||||
}
|
||||
// X-Forwarded-User is re-emitted with the authoritative principal
|
||||
// identifier, overriding the forged value.
|
||||
if got := req.Header.Get("X-Forwarded-User"); got != "realuser" {
|
||||
t.Fatalf("expected X-Forwarded-User to be the authoritative identifier %q, got %q", "realuser", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user