using OCSentinelCli; using Xunit; namespace OCSentinelCli.Tests; public sealed class ExchangeIisAccountCorrelatorTests { [Fact] public void EnrichesAnIisFailureFromOneMatchingSecurityFailure() { DateTimeOffset timestamp = new(2026, 8, 5, 4, 0, 0, TimeSpan.Zero); List events = [ IisFailure(timestamp), SecurityFailure(timestamp.AddSeconds(20), "user@example.test") ]; AttackEvent enriched = Assert.Single(ExchangeIisAccountCorrelator.Enrich(events), attack => attack.Source == "IIS W3C"); Assert.Equal("user@example.test", enriched.Username); } [Fact] public void KeepsIisAccountUnresolvedWhenMultipleAccountsMatch() { DateTimeOffset timestamp = new(2026, 8, 5, 4, 0, 0, TimeSpan.Zero); List events = [ IisFailure(timestamp), SecurityFailure(timestamp.AddSeconds(20), "first@example.test"), SecurityFailure(timestamp.AddSeconds(30), "second@example.test") ]; AttackEvent unresolved = Assert.Single(ExchangeIisAccountCorrelator.Enrich(events), attack => attack.Source == "IIS W3C"); Assert.Equal("[not logged]", unresolved.Username); } private static AttackEvent IisFailure(DateTimeOffset timestamp) => new() { Timestamp = timestamp, SourceIp = "198.51.100.8", Username = "[not logged]", Source = "IIS W3C", Target = "Exchange ActiveSync login" }; private static AttackEvent SecurityFailure(DateTimeOffset timestamp, string username) => new() { Timestamp = timestamp, SourceIp = "198.51.100.8", Username = username, Source = "Security", Service = "Network", Target = "Windows login", InstanceId = 4625 }; }