using Shouldly; using Xunit; namespace ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests; /// /// Scripting:Worker:Identity (lmxopcua#780 design §6, §14 #5): the virtual account's SID is computed exactly as /// Windows computes it, so the host's restricted token, the installer's ACLs (which compute the same SID in /// PowerShell, scripts/install/tests/Test-ScriptWorkerIsolation.ps1 pins the same value) and the pipe ACL agree. /// [Trait("Category", "Unit")] public sealed class ScriptWorkerIdentityTests { /// The installer's default identity; the PowerShell harness pins the same string. private const string OtOpcUaScriptWorkerSid = "S-1-5-80-1846135827-3903057317-1998105452-3938448374-3023753135"; [Fact] public void The_service_sid_algorithm_reproduces_a_well_known_virtual_account() => ScriptWorkerIdentity.ServiceSid("TrustedInstaller") .ShouldBe("S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464"); [Fact] public void The_default_identity_resolves_to_the_pinned_sid_case_insensitively() { ScriptWorkerIdentity.TryResolveSid(ScriptWorkerIdentity.DefaultIdentity, out var sid, out var error).ShouldBeTrue(error); sid.ShouldBe(OtOpcUaScriptWorkerSid); ScriptWorkerIdentity.TryResolveSid(@"nt service\otopcuascriptworker", out var lower, out _).ShouldBeTrue(); lower.ShouldBe(OtOpcUaScriptWorkerSid); } [Fact] public void A_sid_string_passes_through() { ScriptWorkerIdentity.TryResolveSid("S-1-5-21-1-2-3-1001", out var sid, out _).ShouldBeTrue(); sid.ShouldBe("S-1-5-21-1-2-3-1001"); } [Theory] [InlineData("", "no identity")] [InlineData(@"OTOPCUA\svc-worker", "expected 'NT SERVICE")] [InlineData(@"NT SERVICE\bad name", "virtual account name")] [InlineData("S-1-1-0", "well-known group")] [InlineData("S-1-5-32-545", "well-known group")] [InlineData("S-1-5-18", "well-known group")] [InlineData("S-1-5-11", "well-known group")] public void A_domain_account_a_well_known_group_or_garbage_is_refused(string identity, string why) { ScriptWorkerIdentity.TryResolveSid(identity, out _, out var error).ShouldBeFalse(); error!.ShouldContain(why); } [Fact] public void The_restricting_set_is_the_identity_then_everyone_users_and_restricted_and_never_authenticated_users() { var set = ScriptWorkerIdentity.RestrictingSids(OtOpcUaScriptWorkerSid); set.ShouldBe([OtOpcUaScriptWorkerSid, "S-1-1-0", "S-1-5-32-545", "S-1-5-12"]); set.ShouldNotContain("S-1-5-11"); } [Fact] public void Validation_refuses_an_identity_off_windows_and_a_malformed_one_on_windows() { new ScriptWorkerOptions().ValidateIdentity(isWindows: false).ShouldBeNull("unset is always fine"); new ScriptWorkerOptions { Identity = ScriptWorkerIdentity.DefaultIdentity }.ValidateIdentity(isWindows: true) .ShouldBeNull("positive control"); new ScriptWorkerOptions { Identity = ScriptWorkerIdentity.DefaultIdentity }.ValidateIdentity(isWindows: false) .ShouldNotBeNull().ShouldContain("only supported on Windows"); new ScriptWorkerOptions { Identity = @"OTOPCUA\svc" }.ValidateIdentity(isWindows: true) .ShouldNotBeNull().ShouldContain("Scripting:Worker:Identity"); } [Fact] public void Sanitized_keeps_the_identity() => new ScriptWorkerOptions { Identity = ScriptWorkerIdentity.DefaultIdentity }.Sanitized(out _).Identity .ShouldBe(ScriptWorkerIdentity.DefaultIdentity); }