Resolve all high-severity architecture review findings
This commit is contained in:
@@ -47,6 +47,7 @@ public class CentralControlEndToEndTests : IAsyncLifetime
|
||||
// bridge can be asserted without extracting ids out of a decoded AuditEvent.
|
||||
private static readonly Guid AcceptedId = Guid.Parse("11111111-1111-1111-1111-111111111111");
|
||||
|
||||
private int _dispatches;
|
||||
private IHost _host = null!;
|
||||
private TestServer _server = null!;
|
||||
private ActorSystem _actorSystem = null!;
|
||||
@@ -56,7 +57,7 @@ public class CentralControlEndToEndTests : IAsyncLifetime
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
_actorSystem = ActorSystem.Create("centralcontrol-e2e-test");
|
||||
var stub = _actorSystem.ActorOf(Props.Create(() => new StubCentralActor(AcceptedId)), "central-stub");
|
||||
var stub = _actorSystem.ActorOf(Props.Create(() => new StubCentralActor(AcceptedId, () => Interlocked.Increment(ref _dispatches))), "central-stub");
|
||||
|
||||
_service = new CentralControlGrpcService(
|
||||
NullLogger<CentralControlGrpcService>.Instance,
|
||||
@@ -117,6 +118,35 @@ public class CentralControlEndToEndTests : IAsyncLifetime
|
||||
|
||||
// ---- Auth positives / negatives, all through the real pipeline ----
|
||||
|
||||
[Theory]
|
||||
[InlineData("reconcile")]
|
||||
[InlineData("notification")]
|
||||
[InlineData("audit")]
|
||||
[InlineData("cached")]
|
||||
[InlineData("health")]
|
||||
[InlineData("heartbeat")]
|
||||
public async Task SiteAKey_WithForeignOwner_IsDeniedBeforeAnyActorDispatch(string rpc)
|
||||
{
|
||||
using var channel = Channel(SiteAKey, SiteA);
|
||||
var client = new CentralControlService.CentralControlServiceClient(channel);
|
||||
var deadline = DateTime.UtcNow.AddSeconds(2);
|
||||
var error = await Assert.ThrowsAsync<RpcException>(async () =>
|
||||
{
|
||||
switch (rpc)
|
||||
{
|
||||
case "reconcile": await client.ReconcileSiteAsync(new ReconcileSiteRequestDto { SiteIdentifier = SiteB }, deadline: deadline); break;
|
||||
case "notification": await client.SubmitNotificationAsync(new NotificationSubmitDto { SourceSiteId = SiteB }, deadline: deadline); break;
|
||||
case "audit": await client.IngestAuditEventsAsync(new AuditEventBatch { Events = { new AuditEventDto { SourceSiteId = SiteA }, new AuditEventDto { SourceSiteId = SiteB } } }, deadline: deadline); break;
|
||||
case "cached": await client.IngestCachedTelemetryAsync(new CachedTelemetryBatch { Packets = { new CachedTelemetryPacket {
|
||||
AuditEvent = new AuditEventDto { SourceSiteId = SiteA }, Operational = new SiteCallOperationalDto { SourceSite = SiteB } } } }, deadline: deadline); break;
|
||||
case "health": await client.ReportSiteHealthAsync(new SiteHealthReportDto { SiteId = SiteB }, deadline: deadline); break;
|
||||
default: await client.HeartbeatAsync(new HeartbeatDto { SiteId = SiteB }, deadline: deadline); break;
|
||||
}
|
||||
});
|
||||
Assert.Equal(StatusCode.PermissionDenied, error.StatusCode);
|
||||
Assert.Equal(0, Volatile.Read(ref _dispatches));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CorrectSiteAndKey_ReachesTheService_OnAUnaryCall()
|
||||
{
|
||||
@@ -211,6 +241,7 @@ public class CentralControlEndToEndTests : IAsyncLifetime
|
||||
{
|
||||
NotificationId = Guid.NewGuid().ToString(),
|
||||
ListName = "ops",
|
||||
SourceSiteId = SiteA,
|
||||
SiteEnqueuedAt = Timestamp.FromDateTime(
|
||||
DateTime.SpecifyKind(new DateTime(2026, 5, 20, 10, 0, 0), DateTimeKind.Utc)),
|
||||
};
|
||||
@@ -249,13 +280,14 @@ public class CentralControlEndToEndTests : IAsyncLifetime
|
||||
/// </summary>
|
||||
private sealed class StubCentralActor : ReceiveActor
|
||||
{
|
||||
public StubCentralActor(Guid acceptedId)
|
||||
public StubCentralActor(Guid acceptedId, Action dispatched)
|
||||
{
|
||||
Receive<NotificationSubmit>(msg =>
|
||||
Sender.Tell(new NotificationSubmitAck(msg.NotificationId, Accepted: true, Error: null)));
|
||||
Receive<NotificationSubmit>(msg => { dispatched();
|
||||
Sender.Tell(new NotificationSubmitAck(msg.NotificationId, Accepted: true, Error: null)); });
|
||||
|
||||
Receive<IngestAuditEventsCommand>(_ =>
|
||||
Sender.Tell(new IngestAuditEventsReply(new[] { acceptedId })));
|
||||
Receive<IngestAuditEventsCommand>(_ => { dispatched();
|
||||
Sender.Tell(new IngestAuditEventsReply(new[] { acceptedId })); });
|
||||
ReceiveAny(_ => dispatched());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user