fix(audit): record real client IP behind Traefik #444

Merged
nrupard merged 2 commits from fix/PMS-587-audit-client-ip into main 2026-07-13 18:53:53 +02:00
Member

Audit log entries recorded the socket peer address, which behind Traefik is the proxy rather than the client (rendering as - in the audit page and CSV export). Resolve the real client IP from the X-Forwarded-For header, trusting it only when the peer falls inside a configured proxy CIDR so a spoofed header from a direct client cannot poison the recorded address. Mirrors Bunyip's extract_client_ip + TRUSTED_PROXY_CIDR handling.

Adds src/utils/client_ip.rs with a pure, unit-tested extract_client_ip walking the forwarded chain right-to-left to the first untrusted hop, plus a TRUSTED_PROXY_CIDR allowlist (defaulting to loopback + RFC1918/ULA/link-local so a Docker/LAN Traefik works out of the box). Wires it into the AuditCtx request extractor (covers every entity-mutation audit row) and the three auth-side IP capture sites (login, logout, Google callback). Direct requests still record the peer and never panic on a missing or garbled header.

#PMS-587

Audit log entries recorded the socket peer address, which behind Traefik is the proxy rather than the client (rendering as `-` in the audit page and CSV export). Resolve the real client IP from the X-Forwarded-For header, trusting it only when the peer falls inside a configured proxy CIDR so a spoofed header from a direct client cannot poison the recorded address. Mirrors Bunyip's extract_client_ip + TRUSTED_PROXY_CIDR handling. Adds src/utils/client_ip.rs with a pure, unit-tested extract_client_ip walking the forwarded chain right-to-left to the first untrusted hop, plus a TRUSTED_PROXY_CIDR allowlist (defaulting to loopback + RFC1918/ULA/link-local so a Docker/LAN Traefik works out of the box). Wires it into the AuditCtx request extractor (covers every entity-mutation audit row) and the three auth-side IP capture sites (login, logout, Google callback). Direct requests still record the peer and never panic on a missing or garbled header. #PMS-587
fix(audit): record real client IP behind Traefik
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 1m48s
Integration / integration tests (pull_request) Successful in 7m53s
E2E / Playwright against staging (pull_request) Successful in 37s
b3954a148e
Audit log entries recorded the socket peer address, which behind Traefik is the proxy rather than the client (rendering as `-` in the audit page and CSV export). Resolve the real client IP from the X-Forwarded-For header, trusting it only when the peer falls inside a configured proxy CIDR so a spoofed header from a direct client cannot poison the recorded address. Mirrors Bunyip's extract_client_ip + TRUSTED_PROXY_CIDR handling.

Adds src/utils/client_ip.rs with a pure, unit-tested extract_client_ip walking the forwarded chain right-to-left to the first untrusted hop, plus a TRUSTED_PROXY_CIDR allowlist (defaulting to loopback + RFC1918/ULA/link-local so a Docker/LAN Traefik works out of the box). Wires it into the AuditCtx request extractor (covers every entity-mutation audit row) and the three auth-side IP capture sites (login, logout, Google callback). Direct requests still record the peer and never panic on a missing or garbled header.

#PMS-587
Merge remote-tracking branch 'origin/main' into fix/PMS-587-audit-client-ip
All checks were successful
E2E / Playwright against staging (pull_request) Successful in 3m41s
Integration / integration tests (pull_request) Successful in 7m57s
Check / fmt + clippy + build + tests (pull_request) Successful in 10m55s
Create release / Gate (release-branch merges only) (pull_request) Successful in 1s
Create release / Create release from merged PR (pull_request) Has been skipped
af6f8d9c05
nrupard scheduled this pull request to auto merge when all checks succeed 2026-07-13 18:46:58 +02:00
nrupard deleted branch fix/PMS-587-audit-client-ip 2026-07-13 18:53:53 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!444
No description provided.