docs: document authz trust boundary and annotate RequireRoles
This commit is contained in:
17
docs/SECURITY_BOUNDARY.md
Normal file
17
docs/SECURITY_BOUNDARY.md
Normal file
@@ -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**.
|
||||||
@@ -39,6 +39,9 @@ func ActorFromContext(ctx context.Context) (Actor, bool) {
|
|||||||
return actor, true
|
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 {
|
func RequireRoles(next http.Handler, allowedRoles ...string) http.Handler {
|
||||||
allowed := make(map[string]struct{}, len(allowedRoles))
|
allowed := make(map[string]struct{}, len(allowedRoles))
|
||||||
for _, role := range allowedRoles {
|
for _, role := range allowedRoles {
|
||||||
|
|||||||
Reference in New Issue
Block a user