feat(server): add observability and operator controls (#16)
quality-gate / quality (push) Failing after 1m1s
quality-gate / quality (push) Failing after 1m1s
This commit is contained in:
@@ -6,6 +6,7 @@ using FinalFactory.Rendezvous.Server.Http;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
@@ -86,6 +87,9 @@ public sealed class AbuseProtectionTests
|
||||
AbuseProtectionService protection = new(Options.Create(options));
|
||||
IPAddress source = IPAddress.Parse("198.51.100.10");
|
||||
|
||||
Assert.True(protection.IsOperatorSourceAllowed(source));
|
||||
Assert.True(protection.IsOperatorSourceAllowed(IPAddress.Parse("::ffff:198.51.100.10")));
|
||||
Assert.False(protection.IsOperatorSourceAllowed(IPAddress.Parse("198.51.100.11")));
|
||||
AssertAccepted(protection, source, "BrowseSessions");
|
||||
AssertAccepted(protection, source, "BrowseSessions");
|
||||
AssertRejected(protection, source, "BrowseSessions");
|
||||
@@ -93,6 +97,57 @@ public sealed class AbuseProtectionTests
|
||||
AssertRejected(protection, source, "RenewSessionLease");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PublicSaturationCannotConsumeTheOperatorPartition()
|
||||
{
|
||||
AbuseProtectionOptions options = PermissiveOptions();
|
||||
options.HttpGlobalRequestsPerWindow = 1;
|
||||
options.HttpOptionalRequestsPerWindow = 1;
|
||||
options.OperatorGlobalRequestsPerWindow = 1;
|
||||
AbuseProtectionService protection = new(Options.Create(options));
|
||||
IPAddress source = IPAddress.Parse("198.51.100.10");
|
||||
|
||||
AssertAccepted(protection, source, "BrowseSessions");
|
||||
AssertRejected(protection, source, "BrowseSessions");
|
||||
Assert.True(protection.TryAcquireOperatorIngress(source, out var lease, out _));
|
||||
lease!.Dispose();
|
||||
Assert.False(protection.TryAcquireOperatorIngress(source, out _, out _));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeniedOperatorSourcesConsumeTheBoundedPublicPartition()
|
||||
{
|
||||
AbuseProtectionOptions options = PermissiveOptions();
|
||||
options.OperatorAllowedAddresses = ["192.0.2.10"];
|
||||
options.HttpGlobalRequestsPerWindow = 1;
|
||||
options.HttpOptionalRequestsPerWindow = 1;
|
||||
options.HttpIpPrefixRequestsPerWindow = 1;
|
||||
options.HttpOptionalIpPrefixRequestsPerWindow = 1;
|
||||
AbuseProtectionService protection = new(Options.Create(options));
|
||||
bool dispatched = false;
|
||||
HttpAbuseProtectionMiddleware middleware = new(
|
||||
_ =>
|
||||
{
|
||||
dispatched = true;
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
protection);
|
||||
|
||||
DefaultHttpContext first = Context("198.51.100.10");
|
||||
first.SetEndpoint(new Endpoint(
|
||||
_ => Task.CompletedTask,
|
||||
new EndpointMetadataCollection(new EndpointNameMetadata("GetOperatorStatus")),
|
||||
"operator-status"));
|
||||
await middleware.InvokeAsync(first);
|
||||
Assert.Equal(StatusCodes.Status404NotFound, first.Response.StatusCode);
|
||||
|
||||
DefaultHttpContext repeated = Context("198.51.100.10");
|
||||
repeated.SetEndpoint(first.GetEndpoint());
|
||||
await middleware.InvokeAsync(repeated);
|
||||
Assert.Equal(StatusCodes.Status429TooManyRequests, repeated.Response.StatusCode);
|
||||
Assert.False(dispatched);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResourceBudgetsRemainIsolatedAcrossTenantAndPrincipalScopes()
|
||||
{
|
||||
@@ -354,7 +409,8 @@ public sealed class AbuseProtectionTests
|
||||
{
|
||||
const string canary = "credential-canary <script> endpoint=203.0.113.8:9000";
|
||||
DefaultHttpContext context = Context("198.51.100.10");
|
||||
RendezvousExceptionHandler handler = new();
|
||||
RendezvousExceptionHandler handler = new(
|
||||
NullLogger<RendezvousExceptionHandler>.Instance);
|
||||
|
||||
Assert.True(await handler.TryHandleAsync(
|
||||
context,
|
||||
@@ -438,6 +494,11 @@ public sealed class AbuseProtectionTests
|
||||
HealthGlobalConcurrency = 10_000,
|
||||
HealthIpPrefixRequestsPerWindow = 10_000,
|
||||
HealthIpPrefixConcurrency = 1_000,
|
||||
OperatorAllowedAddresses = ["198.51.100.10"],
|
||||
OperatorGlobalRequestsPerWindow = 10_000,
|
||||
OperatorGlobalConcurrency = 10_000,
|
||||
OperatorIpPrefixRequestsPerWindow = 10_000,
|
||||
OperatorIpPrefixConcurrency = 1_000,
|
||||
HttpGlobalRequestsPerWindow = 10_000,
|
||||
HttpOptionalRequestsPerWindow = 9_000,
|
||||
HttpIpPrefixRequestsPerWindow = 10_000,
|
||||
|
||||
Reference in New Issue
Block a user