using Shouldly; using Xunit; namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests; /// #835/#836 security review: endpoint matching (I-1), credential-reference detection (audit) and L-1. [Trait("Category", "Unit")] public sealed class CredentialPolicyReviewTests { [Theory] [InlineData("""{"AuthType":"Anonymous","UserCertificatePath":"C:\\x.pfx"}""", 0)] [InlineData("""{"AuthType":"username","UserCertificatePath":"/etc/x.pfx"}""", 0)] [InlineData("""{"AuthType":0,"UserCertificatePath":"/etc/x.pfx"}""", 0)] [InlineData("""{"AuthType":"Certificate","UserCertificatePath":"/etc/x.pfx"}""", 1)] [InlineData("""{"authType":2,"UserCertificatePath":"/etc/x.pfx"}""", 1)] [InlineData("""{"UserCertificatePath":"/etc/x.pfx"}""", 1)] // no switch here — the merge may supply it [InlineData("""{"AuthType":null,"UserCertificatePath":"/etc/x.pfx"}""", 1)] public void L1_the_path_rule_applies_unless_the_object_explicitly_switches_certificate_auth_off(string config, int expected) => DriverCredentialPolicy.DescribeProblems(DriverTypeNames.OpcUaClient, config).Count.ShouldBe(expected); [Fact] public void Endpoint_values_are_collected_at_any_depth_and_flattened() { DriverCredentialPolicy.EndpointValues(DriverTypeNames.OpcUaClient, """{"EndpointUrl":" opc.tcp://a:4840 ","EndpointUrls":["opc.tcp://b:4840"],"Devices":[{"discoveryUrl":"opc.tcp://c"}]}""") .ShouldBe(["opc.tcp://a:4840", "opc.tcp://b:4840", "opc.tcp://c"]); DriverCredentialPolicy.EndpointValues(DriverTypeNames.Heidenhain, """{"Devices":[{"Host":"cnc1","Port":19000}]}""") .ShouldBe(["cnc1", "19000"]); DriverCredentialPolicy.EndpointValues(DriverTypeNames.Modbus, """{"Host":"x"}""").ShouldBeEmpty(); } [Theory] [InlineData("""{"Gateway":{"Endpoint":"http://gw:5001"}}""", true)] [InlineData("""{"Gateway":{"Endpoint":"HTTP://GW:5001"}}""", true)] [InlineData("""{"Gateway":{}}""", true)] [InlineData("""{"Gateway":{"Endpoint":"http://attacker:5001"}}""", false)] public void An_unsaved_endpoint_does_not_match_the_stored_driver(string submitted, bool expected) => DriverCredentialPolicy.EndpointsMatchStored(DriverTypeNames.Galaxy, submitted, ["""{"Gateway":{"ApiKeySecretRef":"secret:galaxy/a/k"}}""", """{"Gateway":{"Endpoint":"http://gw:5001"}}"""]) .ShouldBe(expected); [Fact] public void A_type_without_endpoint_fields_never_matches() => DriverCredentialPolicy.EndpointsMatchStored(DriverTypeNames.Modbus, "{}", ["{}"]).ShouldBeFalse(); [Theory] [InlineData("""{"Gateway":{"ApiKeySecretRef":"secret:galaxy/x"}}""", true)] [InlineData("""{"Gateway":{"ApiKeySecretRef":"env:OTOPCUA_GALAXY_X"}}""", true)] [InlineData("""{"Gateway":{"ApiKeySecretRef":"dev:k"}}""", false)] [InlineData("""{"Gateway":{"ApiKeySecretRef":"literal"}}""", false)] [InlineData("""{"Gateway":{"ApiKeySecretRef":"env:ConnectionStrings__ConfigDb"}}""", false)] // out of scope: refused anyway public void HasCredentialReferences_detects_resolvable_references(string config, bool expected) => DriverCredentialPolicy.HasCredentialReferences(DriverTypeNames.Galaxy, config).ShouldBe(expected); }