From 4847b595fba52bc201dcbe335a9982d423e85737 Mon Sep 17 00:00:00 2001 From: Dmytro Khmelnytskyi Date: Wed, 8 May 2024 15:00:46 +0200 Subject: [PATCH 1/2] add updated code --- .../EmailAddressMaskingOperator.cs | 4 +- .../IMaskingOperator.cs | 3 +- .../RegexMaskingOperator.cs | 83 +++++++++----- .../SensitiveDataEnricher.cs | 71 ++++++------ ...ilog.Enrichers.Sensitive.Tests.Unit.csproj | 4 +- .../WhenConfiguringFromJson.cs | 11 ++ .../WhenMaskingCreditCards.cs | 41 ++++--- .../WhenMaskingEmailAddresses.cs | 83 ++++++++++---- ...MaskingLogEventWithNonStringScalarValue.cs | 2 +- .../WhenMaskingWithRegexOperator.cs | 101 ++++++++++-------- 10 files changed, 262 insertions(+), 141 deletions(-) diff --git a/src/Serilog.Enrichers.Sensitive/EmailAddressMaskingOperator.cs b/src/Serilog.Enrichers.Sensitive/EmailAddressMaskingOperator.cs index a60e59f..3269712 100644 --- a/src/Serilog.Enrichers.Sensitive/EmailAddressMaskingOperator.cs +++ b/src/Serilog.Enrichers.Sensitive/EmailAddressMaskingOperator.cs @@ -11,7 +11,7 @@ public EmailAddressMaskingOperator() : base(EmailPattern, RegexOptions.IgnoreCas { } - protected override string PreprocessInput(string input) + protected override string PreprocessInput(string input, string? propertyName = null) { if (input.Contains("%40")) { @@ -20,7 +20,7 @@ protected override string PreprocessInput(string input) return input; } - protected override bool ShouldMaskInput(string input) + protected override bool ShouldMaskInput(string input, string? propertyName = null) { return input.Contains("@"); } diff --git a/src/Serilog.Enrichers.Sensitive/IMaskingOperator.cs b/src/Serilog.Enrichers.Sensitive/IMaskingOperator.cs index 51c051b..94e5bf1 100644 --- a/src/Serilog.Enrichers.Sensitive/IMaskingOperator.cs +++ b/src/Serilog.Enrichers.Sensitive/IMaskingOperator.cs @@ -3,6 +3,7 @@ public interface IMaskingOperator { - MaskingResult Mask(string input, string mask); + MaskingResult MaskProperty(string propertyName, string input, string mask); + MaskingResult MaskMessage(string input, string mask); } } \ No newline at end of file diff --git a/src/Serilog.Enrichers.Sensitive/RegexMaskingOperator.cs b/src/Serilog.Enrichers.Sensitive/RegexMaskingOperator.cs index ca55738..403a5a0 100644 --- a/src/Serilog.Enrichers.Sensitive/RegexMaskingOperator.cs +++ b/src/Serilog.Enrichers.Sensitive/RegexMaskingOperator.cs @@ -10,8 +10,8 @@ public abstract class RegexMaskingOperator : IMaskingOperator { private readonly Regex _regex; - protected RegexMaskingOperator(string regexString) - : this(regexString, RegexOptions.Compiled) + protected RegexMaskingOperator(string regexString) + : this(regexString, RegexOptions.Compiled) { } @@ -25,7 +25,36 @@ protected RegexMaskingOperator(string regexString, RegexOptions options) } } - public MaskingResult Mask(string input, string mask) + public MaskingResult MaskProperty(string propertyName, string input, string mask) + { + var preprocessedInput = PreprocessInput(input, propertyName); + + if (!ShouldMaskInput(preprocessedInput, propertyName)) + { + return MaskingResult.NoMatch; + } + + var maskedResult = _regex.Replace(preprocessedInput, match => + { + if (ShouldMaskMatch(match)) + { + return match.Result(PreprocessMask(PreprocessMask(mask), match)); + } + + return match.Value; + }); + + var result = new MaskingResult + { + Result = maskedResult, + Match = maskedResult != input + }; + + return result; + } + + public MaskingResult MaskMessage(string input, string mask) + { var preprocessedInput = PreprocessInput(input); @@ -34,16 +63,16 @@ public MaskingResult Mask(string input, string mask) return MaskingResult.NoMatch; } - var maskedResult = _regex.Replace(preprocessedInput, match => - { - if (ShouldMaskMatch(match)) - { - return match.Result(PreprocessMask(PreprocessMask(mask), match)); - } + var maskedResult = _regex.Replace(preprocessedInput, match => + { + if (ShouldMaskMatch(match)) + { + return match.Result(PreprocessMask(PreprocessMask(mask), match)); + } + + return match.Value; + }); - return match.Value; - }); - var result = new MaskingResult { Result = maskedResult, @@ -59,37 +88,37 @@ public MaskingResult Mask(string input, string mask) /// The message template or the value of a property on the log event /// true when the input should be masked, otherwise false. Defaults to true /// This method provides an extension point to short-circuit the masking operation before the regular expression matching is performed - protected virtual bool ShouldMaskInput(string input) => true; + protected virtual bool ShouldMaskInput(string input, string? propertyName = null) => true; /// /// Perform any operations on the input value before masking the input /// - /// The message template or the value of a property on the log event + /// The message template or the value of a property on the log event /// The processed input, defaults to no pre-processing and returns the input /// Use this method if the input is encoded using URL encoding for example - protected virtual string PreprocessInput(string input) => input; + protected virtual string PreprocessInput(string input, string? propertyName = null) => input; /// /// Perform any operations on the mask before masking the matched value /// /// The mask value as specified on the - /// The processed mask, defaults to no pre-processing and returns the input + /// The processed mask, defaults to no pre-processing and returns the input protected virtual string PreprocessMask(string mask) => mask; - /// - /// Perform any operations on the mask before masking the matched value - /// - /// The mask value as specified on the - /// The regex match - /// The processed mask, defaults to no pre-processing and returns the input - protected virtual string PreprocessMask(string mask, Match match) => mask; + /// + /// Perform any operations on the mask before masking the matched value + /// + /// The mask value as specified on the + /// The regex match + /// The processed mask, defaults to no pre-processing and returns the input + protected virtual string PreprocessMask(string mask, Match match) => mask; /// /// Indicate whether the operator should continue with masking the matched value from the input /// /// The match found by the regular expression of this operator - /// true when the match should be masked, otherwise false. Defaults to true - /// This method provides an extension point to short-circuit the masking operation if the value matches the regular expression but does not satisfy some additional criteria - protected virtual bool ShouldMaskMatch(Match match) => true; - } + /// true when the match should be masked, otherwise false. Defaults to true + /// This method provides an extension point to short-circuit the masking operation if the value matches the regular expression but does not satisfy some additional criteria + protected virtual bool ShouldMaskMatch(Match match) => true; + } } diff --git a/src/Serilog.Enrichers.Sensitive/SensitiveDataEnricher.cs b/src/Serilog.Enrichers.Sensitive/SensitiveDataEnricher.cs index 75176f3..bde96a9 100644 --- a/src/Serilog.Enrichers.Sensitive/SensitiveDataEnricher.cs +++ b/src/Serilog.Enrichers.Sensitive/SensitiveDataEnricher.cs @@ -21,7 +21,7 @@ internal class SensitiveDataEnricher : ILogEventEnricher private readonly MaskPropertyCollection _maskProperties; private readonly List _excludeProperties; - public SensitiveDataEnricher(SensitiveDataEnricherOptions options) + public SensitiveDataEnricher(SensitiveDataEnricherOptions options) : this(options.Apply) { } @@ -30,8 +30,8 @@ public SensitiveDataEnricher( Action? options) { var enricherOptions = new SensitiveDataEnricherOptions( - MaskingMode.Globally, - DefaultMaskValue, + MaskingMode.Globally, + DefaultMaskValue, DefaultOperators.Select(o => o.GetType().AssemblyQualifiedName), new List(), new List()); @@ -55,7 +55,7 @@ public SensitiveDataEnricher( var fields = typeof(LogEvent).GetFields(BindingFlags.Instance | BindingFlags.NonPublic); var backingField = fields.SingleOrDefault(f => f.Name.Contains("")); - + if (backingField == null) { throw new InvalidOperationException( @@ -114,7 +114,7 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) return (false, null); } - if(_maskProperties.TryGetProperty(property.Key, out var options)) + if (_maskProperties.TryGetProperty(property.Key, out var options)) { if (options == MaskOptions.Default) { @@ -136,7 +136,7 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) { case ScalarValue { Value: string stringValue }: { - var (wasMasked, maskedValue) = ReplaceSensitiveDataFromString(stringValue); + var (wasMasked, maskedValue) = ReplaceSensitiveDataFromString(stringValue, property.Key); if (wasMasked) { @@ -150,23 +150,23 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) // which is why this needs special handling and isn't // caught by the string value above. case ScalarValue { Value: Uri uriValue }: - { - var (wasMasked, maskedValue) = ReplaceSensitiveDataFromString(uriValue.ToString()); - - if (wasMasked) { - return (true, new ScalarValue(new Uri(maskedValue))); - } + var (wasMasked, maskedValue) = ReplaceSensitiveDataFromString(uriValue.ToString(), property.Key); - return (false, null); - } + if (wasMasked) + { + return (true, new ScalarValue(new Uri(maskedValue))); + } + + return (false, null); + } case SequenceValue sequenceValue: var resultElements = new List(); var anyElementMasked = false; foreach (var element in sequenceValue.Elements) { var (wasElementMasked, elementResult) = MaskProperty(new KeyValuePair(property.Key, element)); - + if (wasElementMasked) { resultElements.Add(elementResult!); @@ -201,27 +201,27 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) return (anyMasked, new StructureValue(propList)); } case DictionaryValue dictionaryValue: - { - var resultDictionary = new List>(); - var anyKeyMasked = false; - - foreach (var pair in dictionaryValue.Elements) { - var (wasPairMasked, pairResult) = MaskProperty(new KeyValuePair(pair.Key.Value as string, pair.Value)); + var resultDictionary = new List>(); + var anyKeyMasked = false; - if (wasPairMasked) - { - resultDictionary.Add(new KeyValuePair(pair.Key, pairResult)); - anyKeyMasked = true; - } - else + foreach (var pair in dictionaryValue.Elements) { - resultDictionary.Add(new KeyValuePair(pair.Key, pair.Value)); + var (wasPairMasked, pairResult) = MaskProperty(new KeyValuePair(pair.Key.Value as string, pair.Value)); + + if (wasPairMasked) + { + resultDictionary.Add(new KeyValuePair(pair.Key, pairResult)); + anyKeyMasked = true; + } + else + { + resultDictionary.Add(new KeyValuePair(pair.Key, pair.Value)); + } } - } - return (anyKeyMasked, new DictionaryValue(resultDictionary)); - } + return (anyKeyMasked, new DictionaryValue(resultDictionary)); + } default: return (false, null); } @@ -315,20 +315,23 @@ private string MaskWithOptions(string maskValue, MaskOptions options, string inp { return input.Substring(0, start).PadRight(pad, '*') + input.Substring(end); } - + return input.Substring(0, start) + DefaultMaskPad + input.Substring(end); } return maskValue; } - private (bool, string) ReplaceSensitiveDataFromString(string input) + private (bool, string) ReplaceSensitiveDataFromString(string input, string? propertyName = null) { var isMasked = false; foreach (var maskingOperator in _maskingOperators) { - var maskResult = maskingOperator.Mask(input, _maskValue); + + var maskResult = string.IsNullOrWhiteSpace(propertyName) + ? maskingOperator.MaskMessage(input, _maskValue) + : maskingOperator.MaskProperty(propertyName!, input, _maskValue); if (maskResult.Match) { diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/Serilog.Enrichers.Sensitive.Tests.Unit.csproj b/test/Serilog.Enrichers.Sensitive.Tests.Unit/Serilog.Enrichers.Sensitive.Tests.Unit.csproj index 1ceb44f..815b5e5 100644 --- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/Serilog.Enrichers.Sensitive.Tests.Unit.csproj +++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/Serilog.Enrichers.Sensitive.Tests.Unit.csproj @@ -36,10 +36,10 @@ - PreserveNewest + Always - PreserveNewest + Always diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs index 65e2327..f4c8a78 100644 --- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs +++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Configuration; +using Serilog.Events; using Serilog.Sinks.InMemory; using Serilog.Sinks.InMemory.Assertions; using Xunit; @@ -72,4 +73,14 @@ public MaskingResult Mask(string input, string mask) Result = mask }; } + + public MaskingResult MaskProperty(string propertyName, string input, string mask) + { + return Mask(input, mask); + } + + public MaskingResult MaskMessage(string input, string mask) + { + return Mask(input, mask); + } } \ No newline at end of file diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingCreditCards.cs b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingCreditCards.cs index 37e4201..12d4229 100644 --- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingCreditCards.cs +++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingCreditCards.cs @@ -5,31 +5,46 @@ namespace Serilog.Enrichers.Sensitive.Tests.Unit { public class WhenMaskingCreditCards { - private const string Mask = "***MASK***"; + private const string Mask = "***MASK***"; - [Theory] + [Theory] [InlineData("4111 1111 1111 1111", "***MASK***", true, false)] [InlineData("4111-1111-1111-1111", "***MASK***", true, false)] [InlineData("4111111111111111", "***MASK***", true, true)] - [InlineData("4111 1111 1111 1111", "4111 ***MASK***11 1111", false, false)] - [InlineData("4111-1111-1111-1111", "4111-***MASK***11-1111", false, false)] - [InlineData("4111111111111111", "4111***MASK***111111", false, false)] - [InlineData("4111 1111 1111 1111", "***MASK***", false, true)] - [InlineData("4111-1111-1111-1111", "***MASK***", false, true)] - [InlineData("4111111111111111", "***MASK***", false, true)] + [InlineData("4111 1111 1111 1111", "4111 ***MASK***11 1111", false, false)] + [InlineData("4111-1111-1111-1111", "4111-***MASK***11-1111", false, false)] + [InlineData("4111111111111111", "4111***MASK***111111", false, false)] + [InlineData("4111 1111 1111 1111", "***MASK***", false, true)] + [InlineData("4111-1111-1111-1111", "***MASK***", false, true)] + [InlineData("4111111111111111", "***MASK***", false, true)] public void GivenCreditCard_ValuesAreMaskedFully(string cc, string result, bool fullMask, bool useDefaultConstructor) { - TheMaskedResultOf(cc, fullMask, useDefaultConstructor) + ThePropertyMaskedResultOf("anyPropertyName", cc, fullMask, useDefaultConstructor) .Should() .Be(result); + + TheMessageMaskedResultOf(cc, fullMask, useDefaultConstructor) + .Should() + .Be(result); + } + + private static string ThePropertyMaskedResultOf(string propertyName, string input, bool fullMask, bool useDefaultConstructor) + { + var maskingResult = (useDefaultConstructor ? new CreditCardMaskingOperator() : new CreditCardMaskingOperator(fullMask)).MaskProperty(propertyName, input, Mask); + + return maskingResult.Match + ? maskingResult.Result + : input; } - private static string TheMaskedResultOf(string input, bool fullMask, bool useDefaultConstructor) + + + private static string TheMessageMaskedResultOf(string input, bool fullMask, bool useDefaultConstructor) { - var maskingResult = (useDefaultConstructor ? new CreditCardMaskingOperator() : new CreditCardMaskingOperator(fullMask)).Mask(input, Mask); + var maskingResult = (useDefaultConstructor ? new CreditCardMaskingOperator() : new CreditCardMaskingOperator(fullMask)).MaskMessage(input, Mask); - return maskingResult.Match - ? maskingResult.Result + return maskingResult.Match + ? maskingResult.Result : input; } } diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingEmailAddresses.cs b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingEmailAddresses.cs index bb01f85..1110ca9 100644 --- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingEmailAddresses.cs +++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingEmailAddresses.cs @@ -8,7 +8,11 @@ public class WhenMaskingEmailAddresses [Fact] public void GivenSimpleMailAddress_AddressIsMasked() { - TheMaskedResultOf("simple@email.com") + ThePropertyMaskedResultOf("anyPropertyName", "simple@email.com") + .Should() + .Be(Mask); + + TheMessageMaskedResultOf("simple@email.com") .Should() .Be(Mask); } @@ -16,7 +20,11 @@ public void GivenSimpleMailAddress_AddressIsMasked() [Fact] public void GivenSimpleMailAddressButUppercase_AddressIsMasked() { - TheMaskedResultOf("SIMPLE@email.com") + ThePropertyMaskedResultOf("anyPropertyName", "SIMPLE@email.com") + .Should() + .Be(Mask); + + TheMessageMaskedResultOf("SIMPLE@email.com") .Should() .Be(Mask); } @@ -24,7 +32,11 @@ public void GivenSimpleMailAddressButUppercase_AddressIsMasked() [Fact] public void GivenEmailAddressWithBoxQualifier_AddressIsMasked() { - TheMaskedResultOf("test+spamfolder@email.com") + ThePropertyMaskedResultOf("anyPropertyName", "test+spamfolder@email.com") + .Should() + .Be(Mask); + + TheMessageMaskedResultOf("test+spamfolder@email.com") .Should() .Be(Mask); } @@ -32,7 +44,11 @@ public void GivenEmailAddressWithBoxQualifier_AddressIsMasked() [Fact] public void GivenEmailAddressWithSubdomains_AddressIsMasked() { - TheMaskedResultOf("test@sub.sub.sub.email.com") + ThePropertyMaskedResultOf("anyPropertyName", "test@sub.sub.sub.email.com") + .Should() + .Be(Mask); + + TheMessageMaskedResultOf("test@sub.sub.sub.email.com") .Should() .Be(Mask); } @@ -40,7 +56,11 @@ public void GivenEmailAddressWithSubdomains_AddressIsMasked() [Fact] public void GivenEmailAddressInUrl_EntireStringIsMasked() { - TheMaskedResultOf("https://foo.com/api/1/some/endpoint?email=test@sub.sub.sub.email.com") + ThePropertyMaskedResultOf("anyPropertyName", "https://foo.com/api/1/some/endpoint?email=test@sub.sub.sub.email.com") + .Should() + .Be("https:" + Mask); // I don't even regex + + TheMessageMaskedResultOf("https://foo.com/api/1/some/endpoint?email=test@sub.sub.sub.email.com") .Should() .Be("https:" + Mask); // I don't even regex } @@ -48,7 +68,11 @@ public void GivenEmailAddressInUrl_EntireStringIsMasked() [Fact] public void GivenEmailAddressUrlEncoded_AddressIsMasked() { - TheMaskedResultOf("test%40email.com") + ThePropertyMaskedResultOf("anyPropertyName", "test%40email.com") + .Should() + .Be(Mask); // I don't even regex + + TheMessageMaskedResultOf("test%40email.com") .Should() .Be(Mask); // I don't even regex } @@ -72,9 +96,13 @@ public void GivenEmailAddressUrlEncoded_AddressIsMasked() [InlineData(@"firstname-lastname@example.com")] public void GivenValidEmailAddress_AddressIsMasked(string email) { - TheMaskedResultOf(email) - .Should() - .Be(Mask); + ThePropertyMaskedResultOf("anyPropertyName", email) + .Should() + .Be(Mask); + + TheMessageMaskedResultOf(email) + .Should() + .Be(Mask); } [Theory] @@ -90,9 +118,13 @@ public void GivenValidEmailAddress_AddressIsMasked(string email) [InlineData("(),:;<>[\\]@example.com")] public void GivenInvalidEmailAddress_StringIsNotMasked(string toTest) { - TheMaskedResultOf(toTest) - .Should() - .Be(toTest); + ThePropertyMaskedResultOf("anyPropertyName", toTest) + .Should() + .Be(toTest); + + TheMessageMaskedResultOf(toTest) + .Should() + .Be(toTest); } [Theory] @@ -106,17 +138,30 @@ public void GivenInvalidEmailAddress_StringIsNotMasked(string toTest) [InlineData("this\\ is\"really\"not\\allowed@example.com", "this\\ is\"really\"not\\{0}")] public void GivenInvalidEmailAddress_StringIsStillMasked(string toTest, string expectedMask) { - TheMaskedResultOf(toTest) - .Should() - .Be(string.Format(expectedMask, Mask)); + ThePropertyMaskedResultOf("anyPropertyName", toTest) + .Should() + .Be(string.Format(expectedMask, Mask)); + + TheMessageMaskedResultOf(toTest) + .Should() + .Be(string.Format(expectedMask, Mask)); + } + + private static string TheMessageMaskedResultOf(string input) + { + var maskingResult = new EmailAddressMaskingOperator().MaskMessage(input, Mask); + + return maskingResult.Match + ? maskingResult.Result + : input; } - private static string TheMaskedResultOf(string input) + private static string ThePropertyMaskedResultOf(string propertyName, string input) { - var maskingResult = new EmailAddressMaskingOperator().Mask(input, Mask); + var maskingResult = new EmailAddressMaskingOperator().MaskProperty(propertyName, input, Mask); - return maskingResult.Match - ? maskingResult.Result + return maskingResult.Match + ? maskingResult.Result : input; } } diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingLogEventWithNonStringScalarValue.cs b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingLogEventWithNonStringScalarValue.cs index 565f917..f17e20f 100644 --- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingLogEventWithNonStringScalarValue.cs +++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingLogEventWithNonStringScalarValue.cs @@ -88,7 +88,7 @@ public UriMaskingOperator() : base(SomePattern, RegexOptions.IgnoreCase | RegexO { } - protected override string PreprocessInput(string input) + protected override string PreprocessInput(string input, string? logPropertyName = null) { return input; } diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingWithRegexOperator.cs b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingWithRegexOperator.cs index 5175e55..6c87601 100644 --- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingWithRegexOperator.cs +++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingWithRegexOperator.cs @@ -1,20 +1,20 @@ -using System; +using FluentAssertions; +using System; using System.Text.RegularExpressions; -using FluentAssertions; using Xunit; namespace Serilog.Enrichers.Sensitive.Tests.Unit { - public class WhenMaskingWithRegexOperator - { - private class RegexExtenderWithOptions : RegexMaskingOperator + public class WhenMaskingWithRegexOperator + { + private class RegexExtenderWithOptions : RegexMaskingOperator { private Func _preprocessMask; - public RegexExtenderWithOptions(string regexPattern, Func? preprocessMask = null) + public RegexExtenderWithOptions(string regexPattern, Func? preprocessMask = null) : base(regexPattern) { - _preprocessMask = preprocessMask ?? new Func((mask, _) => mask); + _preprocessMask = preprocessMask ?? new Func((mask, _) => mask); } protected override string PreprocessMask(string mask, Match match) @@ -24,51 +24,68 @@ protected override string PreprocessMask(string mask, Match match) } - [Fact] - public void GivenConstructor_NullPatternThrowsException() - { - var ex = Record.Exception(() => new RegexExtenderWithOptions(null!)); - ex - .Should() - .NotBeNull() - .And - .BeOfType(); - (ex as ArgumentNullException)?.ParamName - .Should() - .Be("regexString"); - } + [Fact] + public void GivenConstructor_NullPatternThrowsException() + { + var ex = Record.Exception(() => new RegexExtenderWithOptions(null!)); + ex + .Should() + .NotBeNull() + .And + .BeOfType(); + (ex as ArgumentNullException)?.ParamName + .Should() + .Be("regexString"); + } + + [Theory] + [InlineData("")] + [InlineData(" ")] + public void GivenConstructor_EmptyOrWhitespacePatternThrowsException(string regexPattern) + { + var ex = Record.Exception(() => new RegexExtenderWithOptions(regexPattern)); + ex + .Should() + .NotBeNull() + .And + .BeOfType(); + (ex as ArgumentOutOfRangeException)?.ParamName + .Should() + .Be("regexString"); + } - [Theory] - [InlineData("")] - [InlineData(" ")] - public void GivenConstructor_EmptyOrWhitespacePatternThrowsException(string regexPattern) - { - var ex = Record.Exception(() => new RegexExtenderWithOptions(regexPattern)); - ex - .Should() - .NotBeNull() - .And - .BeOfType(); - (ex as ArgumentOutOfRangeException)?.ParamName - .Should() - .Be("regexString"); - } + [Fact] + public void GivenPreprocessMaskWithMatchIsUsed_MaskedValueIsModified_InProperty() + { + // Regex matches any character and has a match group for the last character. + // The mask provided to Mask() is ignored and instead it's set to mask all + // characters with '*' except the last one. + var result = new RegexExtenderWithOptions( + ".*([a-z])", + (mask, match) => match.Groups[1].Value.PadLeft(match.Value.Length, '*')) + .MaskProperty("anyName", "abc", "**MASK**"); + + result + .Result + .Should() + .Be("**c"); + } - [Fact] - public void GivenPreprocessMaskWithMatchIsUsed_MaskedValueIsModified() + [Fact] + public void GivenPreprocessMaskWithMatchIsUsed_MaskedValueIsModified_InMessage() { - // Regex matches any character and has a match group for the last character. - // The mask provided to Mask() is ignored and instead it's set to mask all - // characters with '*' except the last one. + // Regex matches any character and has a match group for the last character. + // The mask provided to Mask() is ignored and instead it's set to mask all + // characters with '*' except the last one. var result = new RegexExtenderWithOptions( ".*([a-z])", (mask, match) => match.Groups[1].Value.PadLeft(match.Value.Length, '*')) - .Mask("abc", "**MASK**"); + .MaskMessage("abc", "**MASK**"); result .Result .Should() .Be("**c"); } - } + } } \ No newline at end of file From 1bb73788774da67ac9d2f6dea930b581f05166c9 Mon Sep 17 00:00:00 2001 From: Dmytro Khmelnytskyi Date: Wed, 8 May 2024 15:39:04 +0200 Subject: [PATCH 2/2] remove unneeded using --- .../WhenConfiguringFromJson.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs index f4c8a78..917dea6 100644 --- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs +++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Configuration; -using Serilog.Events; using Serilog.Sinks.InMemory; using Serilog.Sinks.InMemory.Assertions; using Xunit;