- 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.
6.0 KiB
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.cssrc/Gateway/StellaOps.Gateway.WebService/Middleware/TenantMiddleware.cs
Known gaps vs intended behavior
- Spoofing risk: claim propagation uses “set if missing”, so client-supplied headers can pass through unmodified.
- Claim type mismatch: current middleware uses
tid, but canonical tenant claim type isstellaops:tenant(StellaOpsClaimTypes.Tenant). - Scope claim mismatch: tokens may use
scp(individual scope items) and/orscope(space-separated). Current middleware reads onlyscope. - Docs drift:
docs/api/gateway/tenant-auth.mddescribesX-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-*andX-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-TenantX-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):
- Strip all reserved identity headers from the incoming request.
- Compute effective identity from the authenticated principal:
subfrom JWTsub(StellaOpsClaimTypes.Subject)tenantfromstellaops:tenant(StellaOpsClaimTypes.Tenant)projectfromstellaops:project(StellaOpsClaimTypes.Project) when presentscopesfrom:scpclaims (StellaOpsClaimTypes.ScopeItem) if present, else- split
scope(StellaOpsClaimTypes.Scope) by spaces
- 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)
- Tenant:
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: anonymousX-StellaOps-Scopes:(empty) oranonymous(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