fix(management): validate site gRPC addresses on create/update (review 2026-10-21 03/R-1)

This commit is contained in:
Joseph Doherty
2026-10-22 09:17:27 -04:00
parent a9f9ea1c9d
commit 36d57f11b3
3 changed files with 98 additions and 1 deletions
@@ -29,6 +29,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Deployment;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
using ZB.MOM.WW.ScadaBridge.Commons.Types.InboundApi;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Transport;
using ZB.MOM.WW.ScadaBridge.Commons.Validation;
using ZB.MOM.WW.ScadaBridge.DeploymentManager;
using ZB.MOM.WW.ScadaBridge.HealthMonitoring;
using ZB.MOM.WW.ScadaBridge.Communication;
@@ -1885,8 +1886,23 @@ public class ManagementActor : ReceiveActor
return site;
}
/// <summary>
/// Rejects a malformed site gRPC address at the write boundary (review 2026-10-21
/// 03/R-1). Both addresses are optional, but a non-empty value must be an absolute
/// http(s) URL — anything else makes the central channel build throw inside
/// <c>SitePairChannelProvider.UpdateSite</c> on the next address refresh.
/// </summary>
private static void ValidateSiteGrpcAddresses(string? grpcNodeAAddress, string? grpcNodeBAddress)
{
if (!GrpcEndpointRules.TryValidate(grpcNodeAAddress, allowEmpty: true, out var errorA))
throw new ManagementCommandException($"GrpcNodeAAddress: {errorA}");
if (!GrpcEndpointRules.TryValidate(grpcNodeBAddress, allowEmpty: true, out var errorB))
throw new ManagementCommandException($"GrpcNodeBAddress: {errorB}");
}
private static async Task<object?> HandleCreateSite(IServiceProvider sp, CreateSiteCommand cmd, string user)
{
ValidateSiteGrpcAddresses(cmd.GrpcNodeAAddress, cmd.GrpcNodeBAddress);
var repo = sp.GetRequiredService<ISiteRepository>();
var site = new Site(cmd.Name, cmd.SiteIdentifier)
{
@@ -1906,6 +1922,7 @@ public class ManagementActor : ReceiveActor
private static async Task<object?> HandleUpdateSite(IServiceProvider sp, UpdateSiteCommand cmd, string user)
{
ValidateSiteGrpcAddresses(cmd.GrpcNodeAAddress, cmd.GrpcNodeBAddress);
var repo = sp.GetRequiredService<ISiteRepository>();
var site = await repo.GetSiteByIdAsync(cmd.SiteId)
?? throw new ManagementCommandException($"Site with ID {cmd.SiteId} not found.");