feat(zddc-server): debug-level dump of every request's full headers

ACLMiddleware now slog.Debug's the configured email-header name, the
observed value at that name, and the full r.Header map on every request.
Off at the default INFO log level; enable per-pod with ZDDC_LOG_LEVEL=debug.

Motivated by debugging the X-Auth-Request-Email passthrough chain — when
access logs show email=anonymous, /.admin/whoami is unreachable (the
admin gate requires a non-empty email, which is the chicken-and-egg).
The debug log line dumps headers without the gate, so an operator can
identify whichever header name the upstream proxy is actually setting
(X-Forwarded-User, X-Forwarded-Email, Remote-User, X-Authentik-Email,
etc.) and adjust ZDDC_EMAIL_HEADER accordingly.

The debug-level dump captures auth tokens and cookies along with
everything else; safe in dev clusters, not appropriate for production
unless the operator is comfortable with the trade-off. README documents
the trade-off in the Admin Debug Page section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZDDC 2026-04-28 17:53:55 -05:00
parent 83cd5a6bbc
commit 15ccf554d2
2 changed files with 16 additions and 0 deletions

View file

@ -190,6 +190,10 @@ push code/images but cannot `kubectl exec` into the running container. It surfac
`kubectl exec -- env | grep ^ZDDC_` for diagnosing chart / deployment overrides. `kubectl exec -- env | grep ^ZDDC_` for diagnosing chart / deployment overrides.
- **`/.admin/logs`** — recent log entries (last 500) from an in-memory ring buffer. - **`/.admin/logs`** — recent log entries (last 500) from an in-memory ring buffer.
Optional `?level=info|warn|error|debug` and `?since=<RFC3339>` query params. Optional `?level=info|warn|error|debug` and `?since=<RFC3339>` query params.
At `ZDDC_LOG_LEVEL=debug` every request also logs its full header map under
`msg=request headers` — useful for diagnosing proxy / SSO header passthrough
(e.g. confirming which header carries the email). Note: that dump includes
auth tokens and cookies; only enable debug in trusted environments.
- **`/.admin/`** — HTML dashboard that fetches the three JSON endpoints client-side. - **`/.admin/`** — HTML dashboard that fetches the three JSON endpoints client-side.
### Authorization ### Authorization

View file

@ -20,6 +20,18 @@ const EmailKey contextKey = "email"
func ACLMiddleware(cfg config.Config, next http.Handler) http.Handler { func ACLMiddleware(cfg config.Config, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
email := r.Header.Get(cfg.EmailHeader) email := r.Header.Get(cfg.EmailHeader)
// DEBUG-level header dump for diagnosing proxy / SSO header
// passthrough. Off by default (LogLevel info); enable with
// ZDDC_LOG_LEVEL=debug. Logs the configured header name, the
// observed value at that name, and the full request header
// map so an operator can see exactly what reached the binary.
// Note: at debug level this also captures auth tokens, cookies,
// and anything else upstream proxies forward — only enable in
// trusted environments.
slog.Debug("request headers",
"configured", cfg.EmailHeader,
"observed", email,
"headers", r.Header)
ctx := context.WithValue(r.Context(), EmailKey, email) ctx := context.WithValue(r.Context(), EmailKey, email)
next.ServeHTTP(w, r.WithContext(ctx)) next.ServeHTTP(w, r.WithContext(ctx))
}) })