Skip to content

Commit ad2aca3

Browse files
Allow access to match when preprocessing mask
1 parent 1514169 commit ad2aca3

File tree

5 files changed

+71
-10
lines changed

5 files changed

+71
-10
lines changed

Changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog for Serilog.Enrichers.Sensitive
22

3+
## 1.6.0
4+
5+
- Pass match to `PreprocessMask` to allow for further customisation of mask value
6+
37
## 1.5.1
48

59
- Add support for dictionaries in destructured objects

Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<Project>
22
<PropertyGroup>
3-
<Version>1.5.1.0</Version>
3+
<Version>1.6.0.0</Version>
44
<Authors>Sander van Vliet, Huibert Jan Nieuwkamer, Scott Toberman</Authors>
55
<Company>Codenizer BV</Company>
6-
<Copyright>2022 Sander van Vliet</Copyright>
6+
<Copyright>2023 Sander van Vliet</Copyright>
77
</PropertyGroup>
88
</Project>

README.md

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ new LoggerConfiguration()
118118
// etc etc
119119
};
120120
});
121-
```csharp
121+
```
122122

123123
It is also possible to not use any masking operators but instead mask based on property names. In that case you can configure the enricher to not use any masking operators at all:
124124

@@ -130,7 +130,7 @@ new LoggerConfiguration()
130130
{
131131
options.MaskingOperators.Clear();
132132
});
133-
```csharp
133+
```
134134

135135
### Using a custom mask value
136136

@@ -149,6 +149,28 @@ A example rendered message would then look like:
149149

150150
You can specify any mask string as long as it's non-null or an empty string.
151151

152+
#### Customising the mask value based on the matched value
153+
154+
In situations where you want to change the mask and have it include parts of the matched value you can override the `PreprocessMask` method that takes both `mask` and `match` parameters. This allows you to perform more masks that are more dynamic.
155+
156+
For example: mask only the "user" part of an e-mail address.
157+
158+
```csharp
159+
public class CustomizedEmailAddressMaskingOperator : EmailAddressMaskingOperator
160+
{
161+
protected override PreprocessMask(string mask, Match match)
162+
{
163+
var parts = match.Value.Split('@');
164+
165+
return mask + "@" + parts[1];
166+
}
167+
}
168+
```
169+
170+
When the mask is `***MASKED***` and we pass in `[email protected]` the result will be `***MASKED***@universalexports.co.uk`.
171+
172+
Note that this example uses `EmailAddressMaskingOperator` which has a fairly complex regular expression. If possible change your regular expression to have match groups so you can more easily access them through the `match` parameter.
173+
152174
### Always mask a property
153175

154176
It may be that you always want to mask the value of a property regardless of whether it matches a pattern for any of the masking operators. In that case you can specify that the property is always masked:

src/Serilog.Enrichers.Sensitive/RegexMaskingOperator.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public MaskingResult Mask(string input, string mask)
3838
{
3939
if (ShouldMaskMatch(match))
4040
{
41-
return match.Result(PreprocessMask(mask));
41+
return match.Result(PreprocessMask(PreprocessMask(mask), match));
4242
}
4343

4444
return match.Value;
@@ -76,6 +76,14 @@ public MaskingResult Mask(string input, string mask)
7676
/// <returns>The processed mask, defaults to no pre-processing and returns the input</returns>
7777
protected virtual string PreprocessMask(string mask) => mask;
7878

79+
/// <summary>
80+
/// Perform any operations on the mask before masking the matched value
81+
/// </summary>
82+
/// <param name="mask">The mask value as specified on the <see cref="SensitiveDataEnricherOptions"/></param>
83+
/// <param name="match">The regex match</param>
84+
/// <returns>The processed mask, defaults to no pre-processing and returns the input</returns>
85+
protected virtual string PreprocessMask(string mask, Match match) => mask;
86+
7987
/// <summary>
8088
/// Indicate whether the operator should continue with masking the matched value from the input
8189
/// </summary>

test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingWithRegexOperator.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Text.RegularExpressions;
23
using FluentAssertions;
34
using Xunit;
45

@@ -7,11 +8,20 @@ namespace Serilog.Enrichers.Sensitive.Tests.Unit
78
public class WhenMaskingWithRegexOperator
89
{
910
private class RegexExtenderWithOptions : RegexMaskingOperator
10-
{
11-
public RegexExtenderWithOptions(string regexPattern) : base(regexPattern)
12-
{
13-
}
14-
}
11+
{
12+
private Func<string, Match, string> _preprocessMask;
13+
14+
public RegexExtenderWithOptions(string regexPattern, Func<string, Match, string>? preprocessMask = null)
15+
: base(regexPattern)
16+
{
17+
_preprocessMask = preprocessMask ?? new Func<string,Match,string>((mask, _) => mask);
18+
}
19+
20+
protected override string PreprocessMask(string mask, Match match)
21+
{
22+
return _preprocessMask(mask, match);
23+
}
24+
}
1525

1626

1727
[Fact]
@@ -43,5 +53,22 @@ public void GivenConstructor_EmptyOrWhitespacePatternThrowsException(string rege
4353
.Should()
4454
.Be("regexString");
4555
}
56+
57+
[Fact]
58+
public void GivenPreprocessMaskWithMatchIsUsed_MaskedValueIsModified()
59+
{
60+
// Regex matches any character and has a match group for the last character.
61+
// The mask provided to Mask() is ignored and instead it's set to mask all
62+
// characters with '*' except the last one.
63+
var result = new RegexExtenderWithOptions(
64+
".*([a-z])",
65+
(mask, match) => match.Groups[1].Value.PadLeft(match.Value.Length, '*'))
66+
.Mask("abc", "**MASK**");
67+
68+
result
69+
.Result
70+
.Should()
71+
.Be("**c");
72+
}
4673
}
4774
}

0 commit comments

Comments
 (0)