From 000c82747ceadea35bce7089d04a6ed2048b8744 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 11 May 2026 12:23:16 +0800 Subject: [PATCH] docs: document authz trust boundary and annotate RequireRoles --- docs/SECURITY_BOUNDARY.md | 17 +++++++++++++++++ internal/http/middleware/authz.go | 3 +++ 2 files changed, 20 insertions(+) create mode 100644 docs/SECURITY_BOUNDARY.md diff --git a/docs/SECURITY_BOUNDARY.md b/docs/SECURITY_BOUNDARY.md new file mode 100644 index 0000000..2740d18 --- /dev/null +++ b/docs/SECURITY_BOUNDARY.md @@ -0,0 +1,17 @@ +# Security Boundary + +## Trust Model + +### `RequireRoles` RBAC Middleware + +Location: `internal/http/middleware/authz.go:RequireRoles` + +- **What it does**: Enforces role-based access control (RBAC) by checking the `X-CS-Actor-ID` and `X-CS-Actor-Role` headers against an allow-list of permitted roles. +- **What it does NOT do**: It does **not** verify the authenticity, integrity, or origin of these headers. A malicious client can forge both headers. +- **Trust boundary**: This middleware assumes that an upstream component (API Gateway, reverse proxy, or JWT validation layer) has already performed real authentication and has stripped or validated any forged headers before they reach this service. + +## Production Deployment Requirements + +- An API Gateway or ingress controller must authenticate requests using JWT, mTLS, or an equivalent mechanism **before** forwarding them to `ai-customer-service`. +- The gateway must sanitize or reject unauthorized `X-CS-Actor-*` headers. +- Direct exposure of the service to the public internet without an authenticating gateway is **not supported**. diff --git a/internal/http/middleware/authz.go b/internal/http/middleware/authz.go index 075facb..c246701 100644 --- a/internal/http/middleware/authz.go +++ b/internal/http/middleware/authz.go @@ -39,6 +39,9 @@ func ActorFromContext(ctx context.Context) (Actor, bool) { return actor, true } +// RequireRoles enforces RBAC allow-listing. It does NOT authenticate the actor headers. +// SECURITY: This middleware trusts the upstream gateway to authenticate the actor headers. +// In production, an API Gateway or JWT middleware must run before this layer. func RequireRoles(next http.Handler, allowedRoles ...string) http.Handler { allowed := make(map[string]struct{}, len(allowedRoles)) for _, role := range allowedRoles {