namespace MxGateway.Server.Diagnostics; /// /// Redacts sensitive information from log entries. /// public static class GatewayLogRedactor { /// Placeholder for redacted values. public const string RedactedValue = "[redacted]"; private static readonly HashSet SensitiveCommandMethods = new(StringComparer.OrdinalIgnoreCase) { "AuthenticateUser", "WriteSecured", "WriteSecured2" }; /// /// Determines whether a command method bears credentials. /// /// The command method name to check. public static bool IsCredentialBearingCommand(string? commandMethod) { return commandMethod is not null && SensitiveCommandMethods.Contains(commandMethod); } /// /// Redacts the API key secret portion of a Bearer authorization header. /// /// The authorization header value to redact. public static string? RedactApiKey(string? authorizationHeader) { if (string.IsNullOrWhiteSpace(authorizationHeader)) { return authorizationHeader; } const string bearerPrefix = "Bearer "; if (!authorizationHeader.StartsWith(bearerPrefix, StringComparison.OrdinalIgnoreCase)) { return RedactedValue; } string token = authorizationHeader[bearerPrefix.Length..].Trim(); if (!token.StartsWith("mxgw_", StringComparison.OrdinalIgnoreCase)) { return $"{bearerPrefix}{RedactedValue}"; } string[] tokenParts = token.Split('_', 3, StringSplitOptions.RemoveEmptyEntries); if (tokenParts.Length < 2) { return $"{bearerPrefix}mxgw_{RedactedValue}"; } return $"{bearerPrefix}mxgw_{tokenParts[1]}_{RedactedValue}"; } /// /// Redacts the client identity if it contains an API key. /// /// The client identity string to redact. public static string? RedactClientIdentity(string? clientIdentity) { if (string.IsNullOrWhiteSpace(clientIdentity)) { return clientIdentity; } return clientIdentity.Contains("mxgw_", StringComparison.OrdinalIgnoreCase) ? RedactApiKey(clientIdentity) : clientIdentity; } /// /// Redacts a command value if it contains credentials or value logging is disabled. /// /// The command method name to check for credentials. /// The command value to redact. /// Whether value logging is enabled. public static object? RedactCommandValue( string? commandMethod, object? value, bool valueLoggingEnabled = false) { if (value is null) { return null; } if (!valueLoggingEnabled || IsCredentialBearingCommand(commandMethod)) { return RedactedValue; } return value; } }