using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;
using ZB.MOM.WW.OtOpcUa.Configuration.Validation;
namespace ZB.MOM.WW.OtOpcUa.Configuration.Tests;
/// lmxopcua#815: the credential-reference namespace deploy gate (Galaxy, OpcUaClient).
[Trait("Category", "Unit")]
public sealed class DraftValidatorCredentialReferenceTests
{
private static IReadOnlyList Validate(string type, string driverConfig, string deviceConfig = "{}") =>
DraftValidator.Validate(new DraftSnapshot
{
GenerationId = 1,
ClusterId = "c",
DriverInstances = [new DriverInstance { DriverInstanceId = "drv", ClusterId = "c", Name = "drv", DriverType = type, DriverConfig = driverConfig }],
Devices = [new Device { DeviceId = "dev", DriverInstanceId = "drv", Name = "dev1", DeviceConfig = deviceConfig }],
Tags = [],
}).Where(e => e.Code == CredentialReferenceDeployChecks.Code).ToList();
[Theory]
[InlineData("GalaxyMxGateway", """{"Gateway":{"Endpoint":"http://evil:5001","ApiKeySecretRef":"env:ConnectionStrings__ConfigDb"}}""")]
[InlineData("GalaxyMxGateway", """{"Gateway":{"ApiKeySecretRef":"env:ServerHistorian__ApiKey"}}""")]
[InlineData("GalaxyMxGateway", """{"Gateway":{"ApiKeySecretRef":"file:C:\\otopcua\\appsettings.json"}}""")]
[InlineData("GalaxyMxGateway", """{"AlarmAck":{"FallbackPasswordSecretRef":"secret:otopcua/apikeys/ab/galaxy-ack-password"}}""")]
[InlineData("OpcUaClient", """{"EndpointUrl":"opc.tcp://evil:4840","Password":"secret:otopcua/historian/api-key"}""")]
[InlineData("OpcUaClient", """{"UserCertificatePassword":"env:ConnectionStrings__ConfigDb"}""")]
public void An_out_of_namespace_reference_is_refused_naming_the_allowed_form(string type, string config)
{
var e = Validate(type, config).ShouldHaveSingleItem();
e.Context.ShouldBe("drv");
e.Message.ShouldContain("secret:");
e.Message.ShouldContain("lmxopcua#815");
e.Message.ShouldContain("Migrate it before deploying");
e.Message.ShouldNotContain("ConnectionStrings__ConfigDb");
}
[Fact]
public void A_reference_in_a_device_config_is_checked_too()
=> Validate("GalaxyMxGateway", "{}", """{"Gateway":{"ApiKeySecretRef":"env:ConnectionStrings__ConfigDb"}}""")
.ShouldHaveSingleItem().Context.ShouldBe("dev");
[Theory]
[InlineData("GalaxyMxGateway", """{"Gateway":{"ApiKeySecretRef":"secret:galaxy/main/apikey"},"AlarmAck":{"FallbackPasswordSecretRef":"secret:otopcua/galaxy/ack-fallback"}}""")]
[InlineData("GalaxyMxGateway", """{"Gateway":{"ApiKeySecretRef":"env:GALAXY_MXGW_API_KEY"}}""")]
[InlineData("GalaxyMxGateway", """{"Gateway":{"ApiKeySecretRef":"dev:k"}}""")]
[InlineData("OpcUaClient", """{"Password":"literal","UserCertificatePassword":"env:OTOPCUA_OPCUACLIENT_CERT_PW"}""")]
[InlineData("Modbus", """{"Password":"env:ConnectionStrings__ConfigDb"}""")]
public void Namespaced_literal_and_unrelated_configs_pass(string type, string config)
=> Validate(type, config).ShouldBeEmpty();
[Fact]
public void Heidenhain_is_reported_once_by_its_own_gate_not_twice()
=> DraftValidator.Validate(new DraftSnapshot
{
GenerationId = 1, ClusterId = "c",
DriverInstances = [new DriverInstance { DriverInstanceId = "hh", ClusterId = "c", Name = "hh", DriverType = "Heidenhain", DriverConfig = """{"Access":{"InspectPassword":"env:ConnectionStrings__ConfigDb"}}""" }],
Devices = [], Tags = [],
})
.Count(e => e.Code is CredentialReferenceDeployChecks.Code or HeidenhainDeployChecks.CredentialCode).ShouldBe(1);
}