sprints and audit work
This commit is contained in:
@@ -3,6 +3,7 @@ namespace StellaOps.Gateway.WebService.Middleware;
|
||||
public sealed class CorrelationIdMiddleware
|
||||
{
|
||||
public const string HeaderName = "X-Correlation-Id";
|
||||
private const int MaxCorrelationIdLength = 128;
|
||||
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
@@ -16,7 +17,18 @@ public sealed class CorrelationIdMiddleware
|
||||
if (context.Request.Headers.TryGetValue(HeaderName, out var headerValue) &&
|
||||
!string.IsNullOrWhiteSpace(headerValue))
|
||||
{
|
||||
context.TraceIdentifier = headerValue.ToString();
|
||||
var correlationId = headerValue.ToString();
|
||||
|
||||
// Validate correlation ID to prevent header injection and resource exhaustion
|
||||
if (IsValidCorrelationId(correlationId))
|
||||
{
|
||||
context.TraceIdentifier = correlationId;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid correlation ID - generate a new one
|
||||
context.TraceIdentifier = Guid.NewGuid().ToString("N");
|
||||
}
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(context.TraceIdentifier))
|
||||
{
|
||||
@@ -27,4 +39,25 @@ public sealed class CorrelationIdMiddleware
|
||||
|
||||
await _next(context);
|
||||
}
|
||||
|
||||
private static bool IsValidCorrelationId(string value)
|
||||
{
|
||||
// Enforce length limit
|
||||
if (value.Length > MaxCorrelationIdLength)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for valid characters (alphanumeric, dashes, underscores)
|
||||
// Reject control characters, line breaks, and other potentially dangerous chars
|
||||
foreach (var c in value)
|
||||
{
|
||||
if (!char.IsLetterOrDigit(c) && c != '-' && c != '_' && c != '.')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,16 +31,19 @@ internal sealed class DefaultRoutingPlugin : IRoutingPlugin
|
||||
private readonly RoutingOptions _options;
|
||||
private readonly RouterNodeConfig _gatewayConfig;
|
||||
private readonly ConcurrentDictionary<string, int> _roundRobinCounters = new();
|
||||
private readonly Func<int, int> _randomIndexSource;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DefaultRoutingPlugin"/> class.
|
||||
/// </summary>
|
||||
public DefaultRoutingPlugin(
|
||||
IOptions<RoutingOptions> options,
|
||||
IOptions<RouterNodeConfig> gatewayConfig)
|
||||
IOptions<RouterNodeConfig> gatewayConfig,
|
||||
Func<int, int>? randomIndexSource = null)
|
||||
{
|
||||
_options = options.Value;
|
||||
_gatewayConfig = gatewayConfig.Value;
|
||||
_randomIndexSource = randomIndexSource ?? Random.Shared.Next;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -239,7 +242,7 @@ internal sealed class DefaultRoutingPlugin : IRoutingPlugin
|
||||
|
||||
private ConnectionState SelectRandom(List<ConnectionState> candidates)
|
||||
{
|
||||
var index = Random.Shared.Next(candidates.Count);
|
||||
var index = _randomIndexSource(candidates.Count);
|
||||
return candidates[index];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user