Align policy simulation auth passthrough at the frontdoor

This commit is contained in:
master
2026-03-10 01:55:51 +02:00
parent d16d7a1692
commit 72084355a6
7 changed files with 109 additions and 1 deletions

View File

@@ -190,6 +190,19 @@ public sealed class GatewayAuthOptions
/// </summary>
public bool EnableTenantOverride { get; set; } = false;
/// <summary>
/// Approved route prefixes where Authorization/DPoP passthrough may be enabled.
/// Routes still need <c>PreserveAuthHeaders=true</c> to preserve auth headers.
/// </summary>
public List<string> ApprovedAuthPassthroughPrefixes { get; set; } =
[
"/connect",
"/console",
"/authority",
"/doctor",
"/api"
];
/// <summary>
/// Emit signed identity envelope headers for router-dispatched requests.
/// </summary>

View File

@@ -131,6 +131,7 @@ builder.Services.AddSingleton(new IdentityHeaderPolicyOptions
.Where(r => r.PreserveAuthHeaders)
.Select(r => r.Path)
.ToList(),
ApprovedAuthPassthroughPrefixes = [.. bootstrapOptions.Auth.ApprovedAuthPassthroughPrefixes],
EnableTenantOverride = bootstrapOptions.Auth.EnableTenantOverride
});

View File

@@ -42,6 +42,15 @@
"DpopEnabled": true,
"MtlsEnabled": false,
"AllowAnonymous": true,
"ApprovedAuthPassthroughPrefixes": [
"/connect",
"/console",
"/authority",
"/doctor",
"/api",
"/policy/shadow",
"/policy/simulations"
],
"Authority": {
"Issuer": "https://authority.stella-ops.local",
"RequireHttpsMetadata": false,
@@ -76,6 +85,8 @@
{ "Type": "ReverseProxy", "Path": "/v1/evidence-packs", "TranslatesTo": "http://advisoryai.stella-ops.local/v1/evidence-packs" },
{ "Type": "ReverseProxy", "Path": "/v1/runs", "TranslatesTo": "http://orchestrator.stella-ops.local/v1/runs" },
{ "Type": "ReverseProxy", "Path": "/v1/advisory-ai", "TranslatesTo": "http://advisoryai.stella-ops.local/v1/advisory-ai" },
{ "Type": "ReverseProxy", "Path": "/policy/simulations", "TranslatesTo": "http://policy-gateway.stella-ops.local/policy/simulations", "PreserveAuthHeaders": true },
{ "Type": "ReverseProxy", "Path": "/policy/shadow", "TranslatesTo": "http://policy-gateway.stella-ops.local/policy/shadow", "PreserveAuthHeaders": true },
{ "Type": "ReverseProxy", "Path": "/policy", "TranslatesTo": "http://policy-gateway.stella-ops.local" },
{ "Type": "ReverseProxy", "Path": "/api/policy", "TranslatesTo": "http://policy-gateway.stella-ops.local/api/policy", "PreserveAuthHeaders": true },
{ "Type": "ReverseProxy", "Path": "/api/risk", "TranslatesTo": "http://policy-engine.stella-ops.local/api/risk", "PreserveAuthHeaders": true },

View File

@@ -415,6 +415,23 @@ public sealed class IdentityHeaderPolicyMiddlewareTests
Assert.Equal("proof-value", context.Request.Headers["DPoP"].ToString());
}
[Fact]
public async Task InvokeAsync_PreservesAuthorizationHeadersForConfiguredPolicyPrefix()
{
_options.JwtPassthroughPrefixes = ["/policy/shadow", "/policy/simulations"];
_options.ApprovedAuthPassthroughPrefixes = ["/connect", "/policy/shadow", "/policy/simulations"];
var middleware = CreateMiddleware();
var context = CreateHttpContext("/policy/shadow/results");
context.Request.Headers.Authorization = "DPoP token-value";
context.Request.Headers["DPoP"] = "proof-value";
await middleware.InvokeAsync(context);
Assert.True(_nextCalled);
Assert.Equal("DPoP token-value", context.Request.Headers.Authorization.ToString());
Assert.Equal("proof-value", context.Request.Headers["DPoP"].ToString());
}
[Fact]
public async Task InvokeAsync_StripsAuthorizationHeadersWhenConfiguredPrefixIsNotApproved()
{