Sprint 7+8: Journey UX fixes + identity envelope shared middleware
Sprint 7 — Deep journey fixes:
S7-T01: Trust & Signing empty state with "Go to Signing Keys" CTA
S7-T02: Notifications 3-step setup guide (channel→rule→test)
S7-T03: Topology validate step skip — "Skip Validation" when API fails,
with validateSkipped signal matching agentSkipped pattern
S7-T04: VEX export note on Risk Report tab linking to VEX Ledger
Sprint 8 — Identity envelope shared middleware (ARCHITECTURE):
S8-T01: New UseIdentityEnvelopeAuthentication() extension in
StellaOps.Router.AspNet. Reads X-StellaOps-Identity-Envelope headers,
verifies HMAC-SHA256 via GatewayIdentityEnvelopeCodec, creates
ClaimsPrincipal with sub/tenant/scopes/roles. 5min clock skew.
S8-T02: Concelier refactored — removed 78 lines of inline impl,
now uses shared one-liner
S8-T03: Scanner — UseIdentityEnvelopeAuthentication() added
S8-T04: JobEngine — UseIdentityEnvelopeAuthentication() added
S8-T05: Timeline — UseIdentityEnvelopeAuthentication() added
S8-T06: Integrations — UseIdentityEnvelopeAuthentication() added
S8-T07: docs/modules/router/IDENTITY_ENVELOPE_MIDDLEWARE.md
All services now authenticate ReverseProxy requests via gateway envelope.
Scanner scan submit should now work with authenticated identity.
Angular: 0 errors. .NET (6 services): 0 errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
113
docs/modules/router/IDENTITY_ENVELOPE_MIDDLEWARE.md
Normal file
113
docs/modules/router/IDENTITY_ENVELOPE_MIDDLEWARE.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# Identity Envelope Middleware
|
||||
|
||||
## What
|
||||
|
||||
`UseIdentityEnvelopeAuthentication()` is a shared ASP.NET Core middleware that reads
|
||||
gateway-signed identity envelope headers and hydrates `HttpContext.User` with the
|
||||
enclosed claims. It lives in `StellaOps.Router.AspNet` and is consumed by every
|
||||
downstream microservice that receives proxied requests from the Router gateway.
|
||||
|
||||
## Why
|
||||
|
||||
When the Router gateway forwards a request via YARP ReverseProxy, it strips the
|
||||
original `Authorization: Bearer <jwt>` header. Instead, it signs the authenticated
|
||||
user's identity into two custom headers:
|
||||
|
||||
- `X-StellaOps-Identity-Envelope` -- Base64URL-encoded JSON payload
|
||||
- `X-StellaOps-Identity-Envelope-Signature` -- HMAC-SHA256 signature
|
||||
|
||||
Downstream services need a way to recover the caller's identity from these headers
|
||||
without each service re-implementing the same verification logic. The shared
|
||||
middleware eliminates duplication and ensures consistent claim mapping everywhere.
|
||||
|
||||
## How to use
|
||||
|
||||
In the service's `Program.cs`, register the middleware **before** `UseAuthentication()`:
|
||||
|
||||
```csharp
|
||||
using StellaOps.Router.AspNet;
|
||||
|
||||
// ...
|
||||
|
||||
app.UseIdentityEnvelopeAuthentication(); // <-- must come first
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
```
|
||||
|
||||
The service's `.csproj` must reference `StellaOps.Router.AspNet` (which transitively
|
||||
brings in `StellaOps.Router.Common` containing the codec).
|
||||
|
||||
## Configuration
|
||||
|
||||
The middleware reads the HMAC-SHA256 signing key from one of two sources (first wins):
|
||||
|
||||
| Source | Key |
|
||||
|---|---|
|
||||
| `IConfiguration` | `Router:IdentityEnvelopeSigningKey` |
|
||||
| Environment variable | `STELLAOPS_IDENTITY_ENVELOPE_SIGNING_KEY` |
|
||||
|
||||
In the docker-compose environment the key is injected via `x-router-microservice-defaults`
|
||||
so all services share the same value automatically.
|
||||
|
||||
## Claim mapping
|
||||
|
||||
When a valid, non-expired envelope is verified, the middleware creates a
|
||||
`ClaimsPrincipal` with authentication type `StellaRouterEnvelope` and the following
|
||||
claims:
|
||||
|
||||
| Claim type | Source |
|
||||
|---|---|
|
||||
| `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier` | `envelope.Subject` |
|
||||
| `sub` | `envelope.Subject` |
|
||||
| `stellaops:tenant` | `envelope.Tenant` |
|
||||
| `tenant` | `envelope.Tenant` |
|
||||
| `stellaops:project` | `envelope.Project` |
|
||||
| `project` | `envelope.Project` |
|
||||
| `scope` (one per scope) | `envelope.Scopes` |
|
||||
| `http://schemas.microsoft.com/ws/2008/06/identity/claims/role` (one per role) | `envelope.Roles` |
|
||||
|
||||
## Architecture flow
|
||||
|
||||
```
|
||||
Browser
|
||||
|
|
||||
| Authorization: Bearer <jwt>
|
||||
v
|
||||
Gateway (StellaOps.Gateway.WebService)
|
||||
| 1. Validates JWT
|
||||
| 2. Signs identity into envelope headers (HMAC-SHA256)
|
||||
| 3. Strips Authorization header
|
||||
| 4. Forwards via YARP ReverseProxy
|
||||
v
|
||||
Downstream Service (Scanner, JobEngine, Timeline, Integrations, Concelier, ...)
|
||||
| UseIdentityEnvelopeAuthentication()
|
||||
| 1. Reads X-StellaOps-Identity-Envelope + Signature headers
|
||||
| 2. Verifies HMAC-SHA256 signature
|
||||
| 3. Checks clock skew (5 min tolerance)
|
||||
| 4. Hydrates HttpContext.User
|
||||
v
|
||||
UseAuthentication() / UseAuthorization()
|
||||
(standard ASP.NET pipeline continues with the hydrated principal)
|
||||
```
|
||||
|
||||
## Error handling
|
||||
|
||||
The middleware never throws. All failures (missing headers, missing key, bad signature,
|
||||
expired envelope) are logged at Warning level under the `StellaOps.IdentityEnvelope`
|
||||
logger category. The request continues unauthenticated, allowing the standard JWT
|
||||
bearer handler to attempt authentication normally.
|
||||
|
||||
## Adopted services
|
||||
|
||||
| Service | File |
|
||||
|---|---|
|
||||
| Concelier | `src/Concelier/StellaOps.Concelier.WebService/Program.cs` |
|
||||
| Scanner | `src/Scanner/StellaOps.Scanner.WebService/Program.cs` |
|
||||
| JobEngine | `src/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.WebService/Program.cs` |
|
||||
| Timeline | `src/Timeline/StellaOps.Timeline.WebService/Program.cs` |
|
||||
| Integrations | `src/Integrations/StellaOps.Integrations.WebService/Program.cs` |
|
||||
|
||||
## Source
|
||||
|
||||
- Middleware extension: `src/Router/__Libraries/StellaOps.Router.AspNet/IdentityEnvelopeMiddlewareExtensions.cs`
|
||||
- Envelope model and codec: `src/Router/__Libraries/StellaOps.Router.Common/Identity/GatewayIdentityEnvelope.cs`
|
||||
Reference in New Issue
Block a user