Files
git.stella-ops.org/docs/modules/gateway/identity-header-policy.md
StellaOps Bot 7503c19b8f Add determinism tests for verdict artifact generation and update SHA256 sums script
- Implemented comprehensive tests for verdict artifact generation to ensure deterministic outputs across various scenarios, including identical inputs, parallel execution, and change ordering.
- Created helper methods for generating sample verdict inputs and computing canonical hashes.
- Added tests to validate the stability of canonical hashes, proof spine ordering, and summary statistics.
- Introduced a new PowerShell script to update SHA256 sums for files, ensuring accurate hash generation and file integrity checks.
2025-12-24 02:17:34 +02:00

104 lines
6.0 KiB
Markdown

# Gateway · Identity Header Policy for Router Dispatch (Draft v0.1)
## Status
- Draft; intended for implementation via a dedicated sprint.
- Last updated: 2025-12-23 (UTC).
## Why This Exists
The Gateway is the single HTTP ingress point and routes requests to internal microservices over Router transports. Many services (and legacy components) still rely on **header-based identity context** (tenant/scopes/actor) rather than (or in addition to) `HttpContext.User` claims.
This creates a hard security requirement:
- **Clients must never be able to inject/override “roles/scopes” headers** that the downstream service trusts.
- The Gateway must derive the effective identity from the validated JWT/JWK token (or explicit anonymous identity) and **overwrite** downstream identity headers accordingly.
## Current State (Repo Reality)
The Gateway WebService currently contains middleware that propagates claims into request headers:
- `src/Gateway/StellaOps.Gateway.WebService/Middleware/ClaimsPropagationMiddleware.cs`
- `src/Gateway/StellaOps.Gateway.WebService/Middleware/TenantMiddleware.cs`
### Known gaps vs intended behavior
1) **Spoofing risk:** claim propagation uses “set if missing”, so client-supplied headers can pass through unmodified.
2) **Claim type mismatch:** current middleware uses `tid`, but canonical tenant claim type is `stellaops:tenant` (`StellaOpsClaimTypes.Tenant`).
3) **Scope claim mismatch:** tokens may use `scp` (individual scope items) and/or `scope` (space-separated). Current middleware reads only `scope`.
4) **Docs drift:** `docs/api/gateway/tenant-auth.md` describes `X-Stella-*` headers and scope override behavior that is not implemented in the Gateway WebService.
## Policy Goals
- **No client-controlled identity headers:** the Gateway rejects or strips identity headers coming from external clients.
- **Gateway-controlled propagation:** the Gateway sets downstream identity headers based on validated token claims or a defined anonymous identity.
- **Compatibility bridge:** support both `X-Stella-*` and `X-StellaOps-*` header naming during migration.
- **Determinism:** header values are canonicalized (whitespace, ordering) and do not vary across equivalent requests.
## Reserved Headers (Draft)
The following headers are considered **reserved identity context** and must not be trusted from external clients:
- Tenant / project:
- `X-StellaOps-Tenant`, `X-Stella-Tenant`
- `X-StellaOps-Project`, `X-Stella-Project`
- Scopes / roles:
- `X-StellaOps-Scopes`, `X-Stella-Scopes`
- Actor / subject (if used for auditing):
- `X-StellaOps-Actor`, `X-Stella-Actor`
- Token proof / confirmation (if propagated):
- `cnf`, `cnf.jkt`
**Internal/legacy pass-through keys to also treat as reserved:**
- `sub`, `scope`, `scp`, `tid` (legacy), `stellaops:tenant` (if ever used as a header key)
## Overwrite Rules (Draft)
For non-system paths (i.e., requests that will be routed to microservices):
1) **Strip** all reserved identity headers from the incoming request.
2) **Compute** effective identity from the authenticated principal:
- `sub` from JWT `sub` (`StellaOpsClaimTypes.Subject`)
- `tenant` from `stellaops:tenant` (`StellaOpsClaimTypes.Tenant`)
- `project` from `stellaops:project` (`StellaOpsClaimTypes.Project`) when present
- `scopes` from:
- `scp` claims (`StellaOpsClaimTypes.ScopeItem`) if present, else
- split `scope` (`StellaOpsClaimTypes.Scope`) by spaces
3) **Write** downstream headers (compat mode):
- Tenant:
- `X-StellaOps-Tenant: <tenant>`
- `X-Stella-Tenant: <tenant>` (optional during migration)
- Project (optional):
- `X-StellaOps-Project: <project>`
- `X-Stella-Project: <project>` (optional during migration)
- Scopes:
- `X-StellaOps-Scopes: <space-delimited scopes>`
- `X-Stella-Scopes: <space-delimited scopes>` (optional during migration)
- Actor:
- `X-StellaOps-Actor: <sub>` (unless another canonical actor claim is defined)
### Anonymous mode
If `Gateway:Auth:AllowAnonymous=true` and the request is unauthenticated:
- Set an explicit anonymous identity so downstream services never interpret “missing header” as privileged:
- `X-StellaOps-Actor: anonymous`
- `X-StellaOps-Scopes: ` (empty) or `anonymous` (choose one and document)
- Tenant behavior must be explicitly defined:
- either reject routed requests without tenant context, or
- require a tenant header even in anonymous mode and treat it as *untrusted input* that only selects a tenancy partition (not privileges).
## Scope Override Header (Offline/Pre-prod)
Some legacy flows allow setting scopes via headers (for offline kits or pre-prod bundles).
Draft enforcement:
- Default: **forbid** client-provided scope headers (`X-StellaOps-Scopes`, `X-Stella-Scopes`) and return 403 (deterministic error code).
- Optional controlled override: allow only when `Gateway:Auth:AllowScopeHeader=true`, and only for explicitly allowed environments (offline/pre-prod).
- Even when allowed, the override must not silently escalate a request beyond what the token allows unless the request is explicitly unauthenticated and the environment is configured for offline operation.
## Implementation Notes (Draft)
### Suggested refactor
Replace the current “set-if-missing” propagation with a single middleware:
- `IdentityHeaderPolicyMiddleware`
- strips reserved headers
- overwrites headers from claims
- stores normalized values in `HttpContext.Items` (tenant, actor, scope set) for use by rate limits, routing decisions, and audit logs
### Tests
- Unit tests: spoofed identity headers are removed and overwritten.
- Unit tests: claim type mapping uses `StellaOpsClaimTypes.*` correctly.
- Integration tests: routed request arrives at microservice with correct identity headers.
## Related Documents
- Gateway architecture: `docs/modules/gateway/architecture.md`
- Tenant auth contract (Web V): `docs/api/gateway/tenant-auth.md` (note: currently drifts from implementation)
- Router ASP.NET bridge: `docs/modules/router/aspnet-endpoint-bridge.md`