Fix router frontdoor readiness and route contracts
This commit is contained in:
@@ -268,4 +268,6 @@ public sealed class GatewayHealthOptions
|
||||
public string DegradedThreshold { get; set; } = "15s";
|
||||
|
||||
public string CheckInterval { get; set; } = "5s";
|
||||
|
||||
public List<string> RequiredMicroservices { get; set; } = [];
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@ public static class GatewayOptionsValidator
|
||||
_ = GatewayValueParser.ParseDuration(options.Health.DegradedThreshold, TimeSpan.FromSeconds(15));
|
||||
_ = GatewayValueParser.ParseDuration(options.Health.CheckInterval, TimeSpan.FromSeconds(5));
|
||||
|
||||
if (options.Health.RequiredMicroservices.Any(service => string.IsNullOrWhiteSpace(service)))
|
||||
{
|
||||
throw new InvalidOperationException("Gateway health required microservices must not contain empty values.");
|
||||
}
|
||||
|
||||
ValidateRoutes(options.Routes);
|
||||
}
|
||||
|
||||
@@ -133,6 +138,23 @@ public static class GatewayOptionsValidator
|
||||
{
|
||||
_ = GatewayValueParser.ParseDuration(route.DefaultTimeout, TimeSpan.FromSeconds(30));
|
||||
}
|
||||
|
||||
if (route.IsRegex && !string.IsNullOrWhiteSpace(route.TranslatesTo))
|
||||
{
|
||||
var regex = new Regex(route.Path);
|
||||
var groupCount = regex.GetGroupNumbers().Length;
|
||||
var refs = Regex.Matches(route.TranslatesTo, @"\$(\d+)");
|
||||
foreach (Match refMatch in refs)
|
||||
{
|
||||
var groupNum = int.Parse(refMatch.Groups[1].Value);
|
||||
if (groupNum >= groupCount)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{prefix}: TranslatesTo references ${groupNum} but regex only has {groupCount - 1} capture groups.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@ public sealed class HealthCheckMiddleware
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context, GatewayServiceStatus status, GatewayMetrics metrics)
|
||||
public async Task InvokeAsync(
|
||||
HttpContext context,
|
||||
GatewayServiceStatus status,
|
||||
GatewayMetrics metrics,
|
||||
GatewayReadinessEvaluator readinessEvaluator)
|
||||
{
|
||||
if (GatewayRoutes.IsMetricsPath(context.Request.Path))
|
||||
{
|
||||
@@ -37,28 +41,34 @@ public sealed class HealthCheckMiddleware
|
||||
var path = context.Request.Path.Value ?? string.Empty;
|
||||
if (path.Equals("/health/live", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await WriteHealthAsync(context, StatusCodes.Status200OK, "live", status);
|
||||
await WriteHealthAsync(context, StatusCodes.Status200OK, "live", status, readinessEvaluator.Evaluate(status));
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.Equals("/health/ready", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var readyStatus = status.IsReady ? StatusCodes.Status200OK : StatusCodes.Status503ServiceUnavailable;
|
||||
await WriteHealthAsync(context, readyStatus, "ready", status);
|
||||
var readiness = readinessEvaluator.Evaluate(status);
|
||||
var readyStatus = readiness.IsReady ? StatusCodes.Status200OK : StatusCodes.Status503ServiceUnavailable;
|
||||
await WriteHealthAsync(context, readyStatus, "ready", status, readiness);
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.Equals("/health/startup", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var startupStatus = status.IsStarted ? StatusCodes.Status200OK : StatusCodes.Status503ServiceUnavailable;
|
||||
await WriteHealthAsync(context, startupStatus, "startup", status);
|
||||
await WriteHealthAsync(context, startupStatus, "startup", status, readinessEvaluator.Evaluate(status));
|
||||
return;
|
||||
}
|
||||
|
||||
await WriteHealthAsync(context, StatusCodes.Status200OK, "ok", status);
|
||||
await WriteHealthAsync(context, StatusCodes.Status200OK, "ok", status, readinessEvaluator.Evaluate(status));
|
||||
}
|
||||
|
||||
private static Task WriteHealthAsync(HttpContext context, int statusCode, string status, GatewayServiceStatus serviceStatus)
|
||||
private static Task WriteHealthAsync(
|
||||
HttpContext context,
|
||||
int statusCode,
|
||||
string status,
|
||||
GatewayServiceStatus serviceStatus,
|
||||
GatewayReadinessReport readiness)
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
context.Response.ContentType = "application/json; charset=utf-8";
|
||||
@@ -67,7 +77,10 @@ public sealed class HealthCheckMiddleware
|
||||
{
|
||||
status,
|
||||
started = serviceStatus.IsStarted,
|
||||
ready = serviceStatus.IsReady,
|
||||
ready = readiness.IsReady,
|
||||
transportReady = serviceStatus.IsReady,
|
||||
requiredMicroservices = readiness.RequiredMicroservices,
|
||||
missingMicroservices = readiness.MissingMicroservices,
|
||||
traceId = context.TraceIdentifier
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Net.WebSockets;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using StellaOps.Gateway.WebService.Configuration;
|
||||
@@ -47,7 +48,7 @@ public sealed class RouteDispatchMiddleware
|
||||
return;
|
||||
}
|
||||
|
||||
var route = _resolver.Resolve(context.Request.Path);
|
||||
var (route, regexMatch) = _resolver.Resolve(context.Request.Path);
|
||||
if (route is null)
|
||||
{
|
||||
await _next(context);
|
||||
@@ -83,13 +84,13 @@ public sealed class RouteDispatchMiddleware
|
||||
await HandleStaticFile(context, route);
|
||||
break;
|
||||
case StellaOpsRouteType.ReverseProxy:
|
||||
await HandleReverseProxy(context, route);
|
||||
await HandleReverseProxy(context, route, regexMatch);
|
||||
break;
|
||||
case StellaOpsRouteType.WebSocket:
|
||||
await HandleWebSocket(context, route);
|
||||
break;
|
||||
case StellaOpsRouteType.Microservice:
|
||||
PrepareMicroserviceRoute(context, route);
|
||||
PrepareMicroserviceRoute(context, route, regexMatch);
|
||||
await _next(context);
|
||||
break;
|
||||
default:
|
||||
@@ -178,17 +179,24 @@ public sealed class RouteDispatchMiddleware
|
||||
await stream.CopyToAsync(context.Response.Body, context.RequestAborted);
|
||||
}
|
||||
|
||||
private async Task HandleReverseProxy(HttpContext context, StellaOpsRoute route)
|
||||
private async Task HandleReverseProxy(HttpContext context, StellaOpsRoute route, Match? regexMatch)
|
||||
{
|
||||
var requestPath = context.Request.Path.Value ?? string.Empty;
|
||||
var resolvedTranslatesTo = ResolveCaptureGroups(route.TranslatesTo, regexMatch);
|
||||
var captureGroupsResolved = !string.Equals(resolvedTranslatesTo, route.TranslatesTo, StringComparison.Ordinal);
|
||||
var remainingPath = requestPath;
|
||||
|
||||
if (!route.IsRegex && requestPath.StartsWith(route.Path, StringComparison.OrdinalIgnoreCase))
|
||||
if (captureGroupsResolved)
|
||||
{
|
||||
// Capture groups resolved: TranslatesTo already contains the full target path.
|
||||
remainingPath = string.Empty;
|
||||
}
|
||||
else if (!route.IsRegex && requestPath.StartsWith(route.Path, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
remainingPath = requestPath[route.Path.Length..];
|
||||
}
|
||||
|
||||
var upstreamBase = route.TranslatesTo!.TrimEnd('/');
|
||||
var upstreamBase = resolvedTranslatesTo!.TrimEnd('/');
|
||||
var upstreamUri = new Uri($"{upstreamBase}{remainingPath}{context.Request.QueryString}");
|
||||
|
||||
var client = _httpClientFactory.CreateClient("RouteDispatch");
|
||||
@@ -279,15 +287,34 @@ public sealed class RouteDispatchMiddleware
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrepareMicroserviceRoute(HttpContext context, StellaOpsRoute route)
|
||||
private static void PrepareMicroserviceRoute(HttpContext context, StellaOpsRoute route, Match? regexMatch)
|
||||
{
|
||||
var translatedPath = ResolveTranslatedMicroservicePath(context.Request.Path.Value, route);
|
||||
// If regex route with capture groups, resolve $1/$2/etc. in TranslatesTo
|
||||
var effectiveRoute = route;
|
||||
if (regexMatch is not null && !string.IsNullOrWhiteSpace(route.TranslatesTo))
|
||||
{
|
||||
var resolvedTranslatesTo = ResolveCaptureGroups(route.TranslatesTo, regexMatch);
|
||||
if (!string.Equals(resolvedTranslatesTo, route.TranslatesTo, StringComparison.Ordinal))
|
||||
{
|
||||
effectiveRoute = new StellaOpsRoute
|
||||
{
|
||||
Type = route.Type,
|
||||
Path = route.Path,
|
||||
IsRegex = route.IsRegex,
|
||||
TranslatesTo = resolvedTranslatesTo,
|
||||
DefaultTimeout = route.DefaultTimeout,
|
||||
PreserveAuthHeaders = route.PreserveAuthHeaders
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var translatedPath = ResolveTranslatedMicroservicePath(context.Request.Path.Value, effectiveRoute);
|
||||
if (!string.Equals(translatedPath, context.Request.Path.Value, StringComparison.Ordinal))
|
||||
{
|
||||
context.Items[RouterHttpContextKeys.TranslatedRequestPath] = translatedPath;
|
||||
}
|
||||
|
||||
var targetMicroservice = ResolveRouteTargetMicroservice(route);
|
||||
var targetMicroservice = ResolveRouteTargetMicroservice(effectiveRoute);
|
||||
if (!string.IsNullOrWhiteSpace(targetMicroservice))
|
||||
{
|
||||
context.Items[RouterHttpContextKeys.RouteTargetMicroservice] = targetMicroservice;
|
||||
@@ -300,6 +327,22 @@ public sealed class RouteDispatchMiddleware
|
||||
}
|
||||
}
|
||||
|
||||
private static string? ResolveCaptureGroups(string? translatesTo, Match? regexMatch)
|
||||
{
|
||||
if (regexMatch is null || string.IsNullOrWhiteSpace(translatesTo))
|
||||
{
|
||||
return translatesTo;
|
||||
}
|
||||
|
||||
var resolved = translatesTo;
|
||||
for (var i = regexMatch.Groups.Count - 1; i >= 1; i--)
|
||||
{
|
||||
resolved = resolved.Replace($"${i}", regexMatch.Groups[i].Value);
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
private static string ResolveTranslatedMicroservicePath(string? requestPathValue, StellaOpsRoute route)
|
||||
{
|
||||
var requestPath = string.IsNullOrWhiteSpace(requestPathValue) ? "/" : requestPathValue!;
|
||||
@@ -314,12 +357,18 @@ public sealed class RouteDispatchMiddleware
|
||||
return requestPath;
|
||||
}
|
||||
|
||||
// For regex routes, the TranslatesTo (after capture group substitution)
|
||||
// already contains the full target path. Use it directly.
|
||||
if (route.IsRegex)
|
||||
{
|
||||
return NormalizePath(targetPrefix);
|
||||
}
|
||||
|
||||
var normalizedRoutePath = NormalizePath(route.Path);
|
||||
var normalizedRequestPath = NormalizePath(requestPath);
|
||||
var remainingPath = normalizedRequestPath;
|
||||
|
||||
if (!route.IsRegex &&
|
||||
normalizedRequestPath.StartsWith(normalizedRoutePath, StringComparison.OrdinalIgnoreCase))
|
||||
if (normalizedRequestPath.StartsWith(normalizedRoutePath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
remainingPath = normalizedRequestPath[normalizedRoutePath.Length..];
|
||||
if (!remainingPath.StartsWith('/'))
|
||||
|
||||
@@ -74,6 +74,7 @@ builder.Services.Replace(ServiceDescriptor.Singleton<StellaOps.Router.Gateway.Au
|
||||
|
||||
builder.Services.AddSingleton<GatewayServiceStatus>();
|
||||
builder.Services.AddSingleton<GatewayMetrics>();
|
||||
builder.Services.AddSingleton<GatewayReadinessEvaluator>();
|
||||
|
||||
// Load router transport plugins
|
||||
var transportPluginLoader = new RouterTransportPluginLoader(
|
||||
@@ -128,7 +129,7 @@ builder.Services.AddSingleton(new IdentityHeaderPolicyOptions
|
||||
IdentityEnvelopeIssuer = bootstrapOptions.Auth.IdentityEnvelopeIssuer,
|
||||
IdentityEnvelopeTtl = TimeSpan.FromSeconds(Math.Max(1, bootstrapOptions.Auth.IdentityEnvelopeTtlSeconds)),
|
||||
JwtPassthroughPrefixes = bootstrapOptions.Routes
|
||||
.Where(r => r.PreserveAuthHeaders)
|
||||
.Where(r => r.PreserveAuthHeaders && !r.IsRegex)
|
||||
.Select(r => r.Path)
|
||||
.ToList(),
|
||||
ApprovedAuthPassthroughPrefixes = [.. bootstrapOptions.Auth.ApprovedAuthPassthroughPrefixes],
|
||||
|
||||
@@ -27,7 +27,7 @@ public sealed class StellaOpsRouteResolver
|
||||
}
|
||||
}
|
||||
|
||||
public StellaOpsRoute? Resolve(PathString path)
|
||||
public (StellaOpsRoute? Route, Match? RegexMatch) Resolve(PathString path)
|
||||
{
|
||||
var pathValue = path.Value ?? string.Empty;
|
||||
|
||||
@@ -35,9 +35,10 @@ public sealed class StellaOpsRouteResolver
|
||||
{
|
||||
if (pattern is not null)
|
||||
{
|
||||
if (pattern.IsMatch(pathValue))
|
||||
var match = pattern.Match(pathValue);
|
||||
if (match.Success)
|
||||
{
|
||||
return route;
|
||||
return (route, match);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -47,12 +48,12 @@ public sealed class StellaOpsRouteResolver
|
||||
pathValue.StartsWith(route.Path, StringComparison.OrdinalIgnoreCase) &&
|
||||
route.Path.EndsWith('/'))
|
||||
{
|
||||
return route;
|
||||
return (route, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Gateway.WebService.Configuration;
|
||||
using StellaOps.Router.Common.Abstractions;
|
||||
using StellaOps.Router.Common.Enums;
|
||||
|
||||
namespace StellaOps.Gateway.WebService.Services;
|
||||
|
||||
public sealed record GatewayReadinessReport
|
||||
{
|
||||
public required bool IsReady { get; init; }
|
||||
|
||||
public required bool Started { get; init; }
|
||||
|
||||
public required bool TransportReady { get; init; }
|
||||
|
||||
public IReadOnlyList<string> RequiredMicroservices { get; init; } = [];
|
||||
|
||||
public IReadOnlyList<string> MissingMicroservices { get; init; } = [];
|
||||
}
|
||||
|
||||
public sealed class GatewayReadinessEvaluator
|
||||
{
|
||||
private readonly IGlobalRoutingState _routingState;
|
||||
private readonly IOptions<GatewayOptions> _options;
|
||||
|
||||
public GatewayReadinessEvaluator(IGlobalRoutingState routingState, IOptions<GatewayOptions> options)
|
||||
{
|
||||
_routingState = routingState;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public GatewayReadinessReport Evaluate(GatewayServiceStatus status)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(status);
|
||||
|
||||
var requiredMicroservices = NormalizeRequiredMicroservices(_options.Value.Health.RequiredMicroservices);
|
||||
if (!status.IsStarted || !status.IsReady)
|
||||
{
|
||||
return new GatewayReadinessReport
|
||||
{
|
||||
IsReady = false,
|
||||
Started = status.IsStarted,
|
||||
TransportReady = status.IsReady,
|
||||
RequiredMicroservices = requiredMicroservices,
|
||||
MissingMicroservices = requiredMicroservices
|
||||
};
|
||||
}
|
||||
|
||||
if (requiredMicroservices.Length == 0)
|
||||
{
|
||||
return new GatewayReadinessReport
|
||||
{
|
||||
IsReady = true,
|
||||
Started = true,
|
||||
TransportReady = true,
|
||||
RequiredMicroservices = requiredMicroservices,
|
||||
MissingMicroservices = []
|
||||
};
|
||||
}
|
||||
|
||||
var registeredServices = _routingState.GetAllConnections()
|
||||
.Where(connection => connection.Status is InstanceHealthStatus.Healthy or InstanceHealthStatus.Degraded)
|
||||
.Select(connection => NormalizeServiceKey(connection.Instance.ServiceName))
|
||||
.Where(serviceName => !string.IsNullOrWhiteSpace(serviceName))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray();
|
||||
|
||||
var missing = requiredMicroservices
|
||||
.Where(required => !registeredServices.Any(registered => IsServiceMatch(registered, required)))
|
||||
.ToArray();
|
||||
|
||||
return new GatewayReadinessReport
|
||||
{
|
||||
IsReady = missing.Length == 0,
|
||||
Started = true,
|
||||
TransportReady = true,
|
||||
RequiredMicroservices = requiredMicroservices,
|
||||
MissingMicroservices = missing
|
||||
};
|
||||
}
|
||||
|
||||
private static string[] NormalizeRequiredMicroservices(IEnumerable<string>? services)
|
||||
{
|
||||
return (services ?? [])
|
||||
.Select(NormalizeServiceKey)
|
||||
.Where(serviceName => !string.IsNullOrWhiteSpace(serviceName))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray()!;
|
||||
}
|
||||
|
||||
private static bool IsServiceMatch(string? registeredServiceName, string requiredServiceName)
|
||||
{
|
||||
var normalizedRegistered = NormalizeServiceKey(registeredServiceName);
|
||||
if (string.IsNullOrWhiteSpace(normalizedRegistered))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return string.Equals(normalizedRegistered, requiredServiceName, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static string? NormalizeServiceKey(string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var normalized = value.Trim().ToLowerInvariant();
|
||||
|
||||
var portSeparator = normalized.IndexOf(':');
|
||||
if (portSeparator >= 0)
|
||||
{
|
||||
normalized = normalized[..portSeparator];
|
||||
}
|
||||
|
||||
const string localDomain = ".stella-ops.local";
|
||||
if (normalized.EndsWith(localDomain, StringComparison.Ordinal))
|
||||
{
|
||||
normalized = normalized[..^localDomain.Length];
|
||||
}
|
||||
|
||||
normalized = StripSuffix(normalized, "-web");
|
||||
normalized = StripSuffix(normalized, "-api");
|
||||
normalized = StripSuffix(normalized, "-service");
|
||||
normalized = StripSuffix(normalized, "-gateway");
|
||||
|
||||
return string.IsNullOrWhiteSpace(normalized)
|
||||
? null
|
||||
: normalized;
|
||||
}
|
||||
|
||||
private static string StripSuffix(string value, string suffix)
|
||||
{
|
||||
return value.EndsWith(suffix, StringComparison.Ordinal)
|
||||
? value[..^suffix.Length]
|
||||
: value;
|
||||
}
|
||||
}
|
||||
@@ -71,125 +71,91 @@
|
||||
"Health": {
|
||||
"StaleThreshold": "30s",
|
||||
"DegradedThreshold": "20s",
|
||||
"CheckInterval": "5s"
|
||||
"CheckInterval": "5s",
|
||||
"RequiredMicroservices": []
|
||||
},
|
||||
"Routes": [
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/release-orchestrator", "TranslatesTo": "http://jobengine.stella-ops.local/api/v1/release-orchestrator" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/approvals", "TranslatesTo": "http://jobengine.stella-ops.local/api/v1/approvals" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/vex", "TranslatesTo": "http://vexhub.stella-ops.local/api/v1/vex" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/vexlens", "TranslatesTo": "http://vexlens.stella-ops.local/api/v1/vexlens" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/notify", "TranslatesTo": "http://notify.stella-ops.local/api/v1/notify" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/notifier", "TranslatesTo": "http://notifier.stella-ops.local/api/v1/notifier" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/concelier", "TranslatesTo": "http://concelier.stella-ops.local/api/v1/concelier" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/cvss", "TranslatesTo": "http://policy-gateway.stella-ops.local/api/cvss", "PreserveAuthHeaders": true },
|
||||
{ "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 },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/analytics", "TranslatesTo": "http://platform.stella-ops.local/api/analytics" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/release-orchestrator", "TranslatesTo": "http://jobengine.stella-ops.local/api/release-orchestrator" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/releases", "TranslatesTo": "http://jobengine.stella-ops.local/api/releases" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/approvals", "TranslatesTo": "http://jobengine.stella-ops.local/api/approvals" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/platform", "TranslatesTo": "http://platform.stella-ops.local/api/v1/platform" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/scanner", "TranslatesTo": "http://scanner.stella-ops.local/api/v1/scanner" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/jobengine", "TranslatesTo": "http://jobengine.stella-ops.local/api/v1/jobengine", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/findings", "TranslatesTo": "http://findings.stella-ops.local/api/v1/findings", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/integrations", "TranslatesTo": "http://integrations.stella-ops.local/api/v1/integrations", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/policy", "TranslatesTo": "http://policy-gateway.stella-ops.local/api/v1/policy" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/reachability", "TranslatesTo": "http://reachgraph.stella-ops.local/api/v1/reachability" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/attestor", "TranslatesTo": "http://attestor.stella-ops.local/api/v1/attestor" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/attestations", "TranslatesTo": "http://attestor.stella-ops.local/api/v1/attestations" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/sbom", "TranslatesTo": "http://sbomservice.stella-ops.local/api/v1/sbom" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/signals", "TranslatesTo": "http://signals.stella-ops.local/api/v1/signals" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/orchestrator", "TranslatesTo": "http://orchestrator.stella-ops.local/api/v1/orchestrator" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/authority/quotas", "TranslatesTo": "http://platform.stella-ops.local/api/v1/authority/quotas", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/authority", "TranslatesTo": "http://authority.stella-ops.local/api/v1/authority", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/trust", "TranslatesTo": "http://authority.stella-ops.local/api/v1/trust", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/evidence", "TranslatesTo": "http://evidencelocker.stella-ops.local/api/v1/evidence" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/proofs", "TranslatesTo": "http://evidencelocker.stella-ops.local/api/v1/proofs" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/timeline", "TranslatesTo": "http://timelineindexer.stella-ops.local/api/v1/timeline" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/search", "TranslatesTo": "http://advisoryai.stella-ops.local/v1/search" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/advisory-ai", "TranslatesTo": "http://advisoryai.stella-ops.local/v1/advisory-ai" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/advisory", "TranslatesTo": "http://advisoryai.stella-ops.local/api/v1/advisory" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/vulnerabilities", "TranslatesTo": "http://scanner.stella-ops.local/api/v1/vulnerabilities" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/watchlist", "TranslatesTo": "http://scanner.stella-ops.local/api/v1/watchlist" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/resolve", "TranslatesTo": "http://binaryindex.stella-ops.local/api/v1/resolve" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/ops/binaryindex", "TranslatesTo": "http://binaryindex.stella-ops.local/api/v1/ops/binaryindex" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/verdicts", "TranslatesTo": "http://evidencelocker.stella-ops.local/api/v1/verdicts" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/lineage", "TranslatesTo": "http://sbomservice.stella-ops.local/api/v1/lineage" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/export", "TranslatesTo": "http://exportcenter.stella-ops.local/api/v1/export" },
|
||||
{ "Type": "ReverseProxy", "Path": "/v1/audit-bundles", "TranslatesTo": "http://exportcenter.stella-ops.local/v1/audit-bundles" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/triage", "TranslatesTo": "http://scanner.stella-ops.local/api/v1/triage" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/governance", "TranslatesTo": "http://policy-gateway.stella-ops.local/api/v1/governance" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/determinization", "TranslatesTo": "http://policy-engine.stella-ops.local/api/v1/determinization" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/opsmemory", "TranslatesTo": "http://opsmemory.stella-ops.local/api/v1/opsmemory" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/secrets", "TranslatesTo": "http://scanner.stella-ops.local/api/v1/secrets" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/sources", "TranslatesTo": "http://scanner.stella-ops.local/api/v1/sources" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/workflows", "TranslatesTo": "http://orchestrator.stella-ops.local/api/v1/workflows" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/witnesses", "TranslatesTo": "http://scanner.stella-ops.local/api/v1/witnesses" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/gate", "TranslatesTo": "http://policy-gateway.stella-ops.local/api/gate", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/risk-budget", "TranslatesTo": "http://policy-engine.stella-ops.local/api/risk-budget" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/fix-verification", "TranslatesTo": "http://scanner.stella-ops.local/api/fix-verification" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/compare", "TranslatesTo": "http://sbomservice.stella-ops.local/api/compare" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/change-traces", "TranslatesTo": "http://sbomservice.stella-ops.local/api/change-traces" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/exceptions", "TranslatesTo": "http://policy-gateway.stella-ops.local/api/exceptions", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/verdicts", "TranslatesTo": "http://evidencelocker.stella-ops.local/api/verdicts" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/orchestrator", "TranslatesTo": "http://orchestrator.stella-ops.local/api/orchestrator" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/gateway/rate-limits", "TranslatesTo": "http://platform.stella-ops.local/api/v1/gateway/rate-limits", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/sbomservice", "TranslatesTo": "http://sbomservice.stella-ops.local/api/sbomservice" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/vuln-explorer", "TranslatesTo": "http://vulnexplorer.stella-ops.local/api/vuln-explorer" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/vex", "TranslatesTo": "http://vexhub.stella-ops.local/api/vex" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/admin/plans", "TranslatesTo": "http://registry-token.stella-ops.local/api/admin/plans", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/admin", "TranslatesTo": "http://platform.stella-ops.local/api/admin" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api", "TranslatesTo": "http://platform.stella-ops.local/api" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/vulnerabilities(.*)", "IsRegex": true, "TranslatesTo": "http://scanner.stella-ops.local/api/v1/vulnerabilities$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/watchlist(.*)", "IsRegex": true, "TranslatesTo": "http://attestor.stella-ops.local/api/v1/watchlist$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/triage(.*)", "IsRegex": true, "TranslatesTo": "http://scanner.stella-ops.local/api/v1/triage$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/secrets(.*)", "IsRegex": true, "TranslatesTo": "http://scanner.stella-ops.local/api/v1/secrets$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/sources(.*)", "IsRegex": true, "TranslatesTo": "http://scanner.stella-ops.local/api/v1/sources$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/witnesses(.*)", "IsRegex": true, "TranslatesTo": "http://scanner.stella-ops.local/api/v1/witnesses$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/trust(.*)", "IsRegex": true, "TranslatesTo": "http://authority.stella-ops.local/api/v1/trust$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/evidence(.*)", "IsRegex": true, "TranslatesTo": "http://evidencelocker.stella-ops.local/api/v1/evidence$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/proofs(.*)", "IsRegex": true, "TranslatesTo": "http://evidencelocker.stella-ops.local/api/v1/proofs$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/verdicts(.*)", "IsRegex": true, "TranslatesTo": "http://evidencelocker.stella-ops.local/api/v1/verdicts$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/release-orchestrator(.*)", "IsRegex": true, "TranslatesTo": "http://jobengine.stella-ops.local/api/v1/release-orchestrator$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/approvals(.*)", "IsRegex": true, "TranslatesTo": "http://jobengine.stella-ops.local/api/v1/approvals$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/attestations(.*)", "IsRegex": true, "TranslatesTo": "http://attestor.stella-ops.local/api/v1/attestations$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/sbom(.*)", "IsRegex": true, "TranslatesTo": "http://sbomservice.stella-ops.local/api/v1/sbom$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/lineage(.*)", "IsRegex": true, "TranslatesTo": "http://sbomservice.stella-ops.local/api/v1/lineage$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/resolve(.*)", "IsRegex": true, "TranslatesTo": "http://binaryindex.stella-ops.local/api/v1/resolve$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/ops/binaryindex(.*)", "IsRegex": true, "TranslatesTo": "http://binaryindex.stella-ops.local/api/v1/ops/binaryindex$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/policy(.*)", "IsRegex": true, "TranslatesTo": "http://policy-gateway.stella-ops.local/api/v1/policy$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/governance(.*)", "IsRegex": true, "TranslatesTo": "http://policy-gateway.stella-ops.local/api/v1/governance$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/determinization(.*)", "IsRegex": true, "TranslatesTo": "http://policy-engine.stella-ops.local/api/v1/determinization$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/workflows(.*)", "IsRegex": true, "TranslatesTo": "http://orchestrator.stella-ops.local/api/v1/workflows$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/authority/quotas(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v1/authority/quotas$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/release-control(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v1/release-control$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/gateway/rate-limits(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v1/gateway/rate-limits$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/reachability(.*)", "IsRegex": true, "TranslatesTo": "http://reachgraph.stella-ops.local/api/v1/reachability$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/timeline(.*)", "IsRegex": true, "TranslatesTo": "http://timelineindexer.stella-ops.local/api/v1/timeline$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/audit(.*)", "IsRegex": true, "TranslatesTo": "http://timeline.stella-ops.local/api/v1/audit$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/export(.*)", "IsRegex": true, "TranslatesTo": "http://exportcenter.stella-ops.local/api/v1/export$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/advisory-sources(.*)", "IsRegex": true, "TranslatesTo": "http://concelier.stella-ops.local/api/v1/advisory-sources$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/notifier/delivery(.*)", "IsRegex": true, "TranslatesTo": "http://notifier.stella-ops.local/api/v2/notify/deliveries$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/search(.*)", "IsRegex": true, "TranslatesTo": "http://advisoryai.stella-ops.local/v1/search$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/advisory-ai(.*)", "IsRegex": true, "TranslatesTo": "http://advisoryai.stella-ops.local/v1/advisory-ai$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/advisory(.*)", "IsRegex": true, "TranslatesTo": "http://advisoryai.stella-ops.local/api/v1/advisory$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/vex(.*)", "IsRegex": true, "TranslatesTo": "http://vexhub.stella-ops.local/api/v1/vex$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/doctor/scheduler(.*)", "IsRegex": true, "TranslatesTo": "http://doctor-scheduler.stella-ops.local/api/v1/doctor/scheduler$1" },
|
||||
|
||||
{ "Type": "Microservice", "Path": "^/api/v2/context(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v2/context$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v2/releases(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v2/releases$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v2/security(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v2/security$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v2/topology(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v2/topology$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v2/integrations(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/v2/integrations$1" },
|
||||
|
||||
{ "Type": "Microservice", "Path": "^/api/v1/([^/]+)(.*)", "IsRegex": true, "TranslatesTo": "http://$1.stella-ops.local/api/v1/$1$2" },
|
||||
{ "Type": "Microservice", "Path": "^/api/v2/([^/]+)(.*)", "IsRegex": true, "TranslatesTo": "http://$1.stella-ops.local/api/v2/$1$2" },
|
||||
|
||||
{ "Type": "Microservice", "Path": "^/api/(cvss|gate|exceptions|policy)(.*)", "IsRegex": true, "TranslatesTo": "http://policy-gateway.stella-ops.local/api/$1$2" },
|
||||
{ "Type": "Microservice", "Path": "^/api/(risk|risk-budget)(.*)", "IsRegex": true, "TranslatesTo": "http://policy-engine.stella-ops.local/api/$1$2" },
|
||||
{ "Type": "Microservice", "Path": "^/api/(release-orchestrator|releases|approvals)(.*)", "IsRegex": true, "TranslatesTo": "http://jobengine.stella-ops.local/api/$1$2" },
|
||||
{ "Type": "Microservice", "Path": "^/api/(compare|change-traces|sbomservice)(.*)", "IsRegex": true, "TranslatesTo": "http://sbomservice.stella-ops.local/api/$1$2" },
|
||||
{ "Type": "Microservice", "Path": "^/api/fix-verification(.*)", "IsRegex": true, "TranslatesTo": "http://scanner.stella-ops.local/api/fix-verification$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/verdicts(.*)", "IsRegex": true, "TranslatesTo": "http://evidencelocker.stella-ops.local/api/verdicts$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/vuln-explorer(.*)", "IsRegex": true, "TranslatesTo": "http://vulnexplorer.stella-ops.local/api/vuln-explorer$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/vex(.*)", "IsRegex": true, "TranslatesTo": "http://vexhub.stella-ops.local/api/vex$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/admin/plans(.*)", "IsRegex": true, "TranslatesTo": "http://registry-token.stella-ops.local/api/admin/plans$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/admin(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/admin$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/analytics(.*)", "IsRegex": true, "TranslatesTo": "http://platform.stella-ops.local/api/analytics$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/orchestrator(.*)", "IsRegex": true, "TranslatesTo": "http://orchestrator.stella-ops.local/api/orchestrator$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/jobengine(.*)", "IsRegex": true, "TranslatesTo": "http://orchestrator.stella-ops.local/api/jobengine$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/scheduler(.*)", "IsRegex": true, "TranslatesTo": "http://scheduler.stella-ops.local/api/scheduler$1" },
|
||||
{ "Type": "Microservice", "Path": "^/api/doctor(.*)", "IsRegex": true, "TranslatesTo": "http://doctor.stella-ops.local/api/doctor$1" },
|
||||
|
||||
{ "Type": "Microservice", "Path": "^/policy(.*)", "IsRegex": true, "TranslatesTo": "http://policy-gateway.stella-ops.local/policy$1" },
|
||||
|
||||
{ "Type": "Microservice", "Path": "^/v1/evidence-packs(.*)", "IsRegex": true, "TranslatesTo": "http://advisoryai.stella-ops.local/v1/evidence-packs$1" },
|
||||
{ "Type": "Microservice", "Path": "^/v1/runs(.*)", "IsRegex": true, "TranslatesTo": "http://jobengine.stella-ops.local/v1/runs$1" },
|
||||
{ "Type": "Microservice", "Path": "^/v1/advisory-ai(.*)", "IsRegex": true, "TranslatesTo": "http://advisoryai.stella-ops.local/v1/advisory-ai$1" },
|
||||
{ "Type": "Microservice", "Path": "^/v1/audit-bundles(.*)", "IsRegex": true, "TranslatesTo": "http://exportcenter.stella-ops.local/v1/audit-bundles$1" },
|
||||
|
||||
{ "Type": "ReverseProxy", "Path": "/connect", "TranslatesTo": "http://authority.stella-ops.local/connect" },
|
||||
{ "Type": "ReverseProxy", "Path": "/.well-known", "TranslatesTo": "http://authority.stella-ops.local/.well-known" },
|
||||
{ "Type": "ReverseProxy", "Path": "/jwks", "TranslatesTo": "http://authority.stella-ops.local/jwks" },
|
||||
{ "Type": "ReverseProxy", "Path": "/authority/console", "TranslatesTo": "http://authority.stella-ops.local/console" },
|
||||
{ "Type": "ReverseProxy", "Path": "/authority", "TranslatesTo": "http://authority.stella-ops.local/authority" },
|
||||
{ "Type": "ReverseProxy", "Path": "/console", "TranslatesTo": "http://authority.stella-ops.local/console" },
|
||||
{ "Type": "ReverseProxy", "Path": "/rekor", "TranslatesTo": "http://rekor.stella-ops.local:3322" },
|
||||
{ "Type": "ReverseProxy", "Path": "/platform/envsettings.json", "TranslatesTo": "http://platform.stella-ops.local/platform/envsettings.json" },
|
||||
{ "Type": "ReverseProxy", "Path": "/envsettings.json", "TranslatesTo": "http://platform.stella-ops.local/platform/envsettings.json" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api/v1/setup", "TranslatesTo": "http://platform.stella-ops.local/api/v1/setup" },
|
||||
{ "Type": "ReverseProxy", "Path": "/platform", "TranslatesTo": "http://platform.stella-ops.local/platform" },
|
||||
{ "Type": "ReverseProxy", "Path": "/connect", "TranslatesTo": "http://authority.stella-ops.local", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/.well-known", "TranslatesTo": "http://authority.stella-ops.local/.well-known", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/jwks", "TranslatesTo": "http://authority.stella-ops.local/jwks", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/authority", "TranslatesTo": "http://authority.stella-ops.local/authority", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/console", "TranslatesTo": "http://authority.stella-ops.local/console", "PreserveAuthHeaders": true },
|
||||
{ "Type": "ReverseProxy", "Path": "/scanner", "TranslatesTo": "http://scanner.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/policyGateway", "TranslatesTo": "http://policy-gateway.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/policyEngine", "TranslatesTo": "http://policy-engine.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/concelier", "TranslatesTo": "http://concelier.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/attestor", "TranslatesTo": "http://attestor.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/notify", "TranslatesTo": "http://notify.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/notifier", "TranslatesTo": "http://notifier.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/scheduler", "TranslatesTo": "http://scheduler.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/signals", "TranslatesTo": "http://signals.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/excititor", "TranslatesTo": "http://excititor.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/findingsLedger", "TranslatesTo": "http://findings.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/vexhub", "TranslatesTo": "http://vexhub.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/vexlens", "TranslatesTo": "http://vexlens.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/orchestrator", "TranslatesTo": "http://orchestrator.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/taskrunner", "TranslatesTo": "http://taskrunner.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/cartographer", "TranslatesTo": "http://cartographer.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/reachgraph", "TranslatesTo": "http://reachgraph.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/doctor", "TranslatesTo": "http://doctor.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/integrations", "TranslatesTo": "http://integrations.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/replay", "TranslatesTo": "http://replay.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/exportcenter", "TranslatesTo": "http://exportcenter.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/evidencelocker", "TranslatesTo": "http://evidencelocker.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/signer", "TranslatesTo": "http://signer.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/binaryindex", "TranslatesTo": "http://binaryindex.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/riskengine", "TranslatesTo": "http://riskengine.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/vulnexplorer", "TranslatesTo": "http://vulnexplorer.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/sbomservice", "TranslatesTo": "http://sbomservice.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/advisoryai", "TranslatesTo": "http://advisoryai.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/unknowns", "TranslatesTo": "http://unknowns.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/timelineindexer", "TranslatesTo": "http://timelineindexer.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/opsmemory", "TranslatesTo": "http://opsmemory.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/issuerdirectory", "TranslatesTo": "http://issuerdirectory.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/symbols", "TranslatesTo": "http://symbols.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/packsregistry", "TranslatesTo": "http://packsregistry.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/registryTokenservice", "TranslatesTo": "http://registry-token.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/airgapController", "TranslatesTo": "http://airgap-controller.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/airgapTime", "TranslatesTo": "http://airgap-time.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/smremote", "TranslatesTo": "http://smremote.stella-ops.local" },
|
||||
{ "Type": "ReverseProxy", "Path": "/api", "TranslatesTo": "http://platform.stella-ops.local/api" },
|
||||
|
||||
{ "Type": "StaticFiles", "Path": "/", "TranslatesTo": "/app/wwwroot", "Headers": { "x-spa-fallback": "true" } },
|
||||
{ "Type": "NotFoundPage", "Path": "/_error/404", "TranslatesTo": "/app/wwwroot/index.html" },
|
||||
{ "Type": "ServerErrorPage", "Path": "/_error/500", "TranslatesTo": "/app/wwwroot/index.html" }
|
||||
|
||||
Reference in New Issue
Block a user