using ZB.MOM.WW.Telemetry.Serilog; namespace ZB.MOM.WW.MxGateway.Server.Diagnostics; /// /// Adapts the static to the shared seam /// so the telemetry RedactionEnricher masks API-key/credential material on every log event. /// public sealed class GatewayLogRedactorSeam : ILogRedactor { private static readonly string[] IdentityKeys = ["ClientIdentity", "authorization", "Authorization"]; /// Property name carrying the MXAccess command method, which gates value redaction. private const string CommandMethodProperty = "CommandMethod"; /// Property name carrying a command payload value that may bear credentials. private const string CommandValueProperty = "CommandValue"; /// /// Masks API-key/credential material in known identity-bearing log properties, and any /// command payload value. /// /// The log event property dictionary to redact in place. public void Redact(IDictionary properties) { ArgumentNullException.ThrowIfNull(properties); foreach (var key in IdentityKeys) { if (properties.TryGetValue(key, out var value) && value is string s) { properties[key] = GatewayLogRedactor.RedactClientIdentity(s); } } RedactCommandValue(properties); foreach (string key in properties.Keys.ToList()) { if (key.Contains("password", StringComparison.OrdinalIgnoreCase) && properties[key] is not null) { properties[key] = GatewayLogRedactor.RedactedValue; } } } /// /// Masks a command payload value. Value logging is off here — the seam exposes no opt-in — so /// every non-null value is masked, credential-bearing command or not. /// /// The log event property dictionary to redact in place. private static void RedactCommandValue(IDictionary properties) { if (!properties.TryGetValue(CommandValueProperty, out object? value) || value is null) { return; } string? commandMethod = properties.TryGetValue(CommandMethodProperty, out object? method) ? method as string : null; properties[CommandValueProperty] = GatewayLogRedactor.RedactCommandValue(commandMethod, value); } }