using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.AdminUI.Deployments; using ZB.MOM.WW.OtOpcUa.Configuration.Entities; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; using ZB.MOM.WW.OtOpcUa.Runtime.Drivers; namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Deployments; /// /// The upgrade preflight / /raw banner lists the configs the deploy gate will now refuse for lmxopcua#835 /// (another instance's secret) and #836 (absolute user-certificate path) — Draft and Deployed alike. /// [Trait("Category", "Unit")] public sealed class CredentialReferencePreflightInstanceAndPathTests { private static DriverInstance Drv(string id, string name, string type, string config) => new() { DriverInstanceId = id, ClusterId = "c", Name = name, DriverType = type, DriverConfig = config }; [Fact] public void Draft_and_deployed_cross_instance_references_are_listed() { var drivers = new[] { Drv("DRV-a", "A", DriverTypeNames.Galaxy, """{"Gateway":{"ApiKeySecretRef":"secret:galaxy/DRV-a/apikey"}}"""), Drv("DRV-b", "B", DriverTypeNames.Galaxy, """{"Gateway":{"ApiKeySecretRef":"secret:galaxy/DRV-a/apikey"}}"""), }; var devices = new[] { new Device { DeviceId = "dev-b", DriverInstanceId = "DRV-b", Name = "gw", DeviceConfig = """{"AlarmAck":{"FallbackPasswordSecretRef":"secret:otopcua/galaxy/A/ack"}}""" } }; var deployed = new[] { new DriverInstanceSpec(Guid.NewGuid(), "DRV-a", "A", DriverTypeNames.Galaxy, true, "{}"), new DriverInstanceSpec(Guid.NewGuid(), "DRV-b", "B", DriverTypeNames.Galaxy, true, """{"Gateway":{"ApiKeySecretRef":"secret:galaxy/A/apikey"}}"""), }; var findings = CredentialReferencePreflight.Scan(drivers, devices, deployed); findings.Count.ShouldBe(3); findings.ShouldAllBe(f => f.DriverInstanceId == "DRV-b" && f.Problem.Contains("lmxopcua#835")); findings.Count(f => f.Source == CredentialFindingSource.Draft).ShouldBe(2); findings.Single(f => f.Source == CredentialFindingSource.Deployed).DriverName.ShouldBe("B"); } [Fact] public void An_absolute_user_certificate_path_is_listed_without_the_path() { var findings = CredentialReferencePreflight.Scan( [Drv("o", "Upstream", DriverTypeNames.OpcUaClient, """{"AuthType":"Certificate","UserCertificatePath":"C:\\certs\\plant.pfx"}""")], [], []); var f = findings.ShouldHaveSingleItem(); f.Problem.ShouldContain("lmxopcua#836"); f.Problem.ShouldNotContain("plant.pfx"); } /// /// lmxopcua#850: the AuthType switch in one config and the path in the other — each config passes alone, the /// runtime-merged config does not. The deploy gate catches it; the banner must show it before a deploy does. /// [Fact] public void A_path_split_from_its_certificate_switch_is_listed_from_the_merged_config() { var findings = CredentialReferencePreflight.Scan( [Drv("o", "Upstream", DriverTypeNames.OpcUaClient, """{"AuthType":"Anonymous","UserCertificatePath":"C:\\stolen\\host.pfx"}""")], [new Device { DeviceId = "dev-o", DriverInstanceId = "o", Name = "d", DeviceConfig = """{"AuthType":"Certificate"}""" }], []); var f = findings.ShouldHaveSingleItem(); f.Source.ShouldBe(CredentialFindingSource.Draft); f.DriverInstanceId.ShouldBe("o"); f.DeviceName.ShouldBeNull(); f.Problem.ShouldContain("merged with its devices"); f.Problem.ShouldContain("lmxopcua#836"); f.Problem.ShouldNotContain("host.pfx"); } /// Control: a problem already reported on one config is not listed a second time from the merge. [Fact] public void A_path_already_reported_on_its_own_config_is_not_duplicated_by_the_merge() => CredentialReferencePreflight.Scan( [Drv("o", "Upstream", DriverTypeNames.OpcUaClient, """{"AuthType":"Certificate","UserCertificatePath":"C:\\certs\\plant.pfx"}""")], [new Device { DeviceId = "dev-o", DriverInstanceId = "o", Name = "d", DeviceConfig = "{}" }], []) .ShouldHaveSingleItem().Problem.ShouldNotContain("merged"); /// lmxopcua#849: an env: reference naming another instance is listed like a secret: one. [Fact] public void A_cross_instance_env_reference_is_listed() => CredentialReferencePreflight.Scan( [ Drv("DRV-a", "A", DriverTypeNames.Galaxy, "{}"), Drv("DRV-b", "B", DriverTypeNames.Galaxy, """{"Gateway":{"ApiKeySecretRef":"env:OTOPCUA_GALAXY_DRV_A_KEY"}}"""), ], [], []) .ShouldHaveSingleItem().Problem.ShouldContain("lmxopcua#849"); }