Skip to content

Commit d22aafc

Browse files
authored
[processor/redaction] Introduce blocked_key_patterns parameter (#37664)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description - added `blocked_key_patterns` parameter to mask values of attributes, which keys match at least one of the defined patterns - refactored tests to make them easier to extend <!-- Issue number (e.g. #1234) or full URL to issue, if applicable. --> #### Link to tracking issue Fixes #35830 #### Follow-up #38161 --------- Signed-off-by: odubajDT <[email protected]>
1 parent b072b17 commit d22aafc

File tree

8 files changed

+355
-262
lines changed

8 files changed

+355
-262
lines changed
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: processor/redaction
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: "Introduce 'blocked_key_patterns' parameter"
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [35830]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: []

processor/redactionprocessor/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ processors:
7373
# Any keys in this list are allowed so they don't need to be in both lists.
7474
ignored_keys:
7575
- safe_attribute
76+
# blocked_key_patterns is a list of blocked span attribute key patterns. Span attributes
77+
# matching the regexes on the list are masked.
78+
blocked_key_patterns:
79+
- ".*token.*"
80+
- ".*api_key.*"
7681
# blocked_values is a list of regular expressions for blocking values of
7782
# allowed span attributes. Values that match are masked
7883
blocked_values:
@@ -111,6 +116,9 @@ part of the value is not masked even if it matches the regular expression for a
111116
If the value matches the regular expression for a blocked value only, the matching
112117
part of the value is masked with a fixed length of asterisks.
113118

119+
`blocked_key_patterns` applies to the values of the keys matching one of the patterns.
120+
The value is then masked according to the configuration.
121+
114122
For example, if `notes` is on the list of allowed keys, then the `notes`
115123
attribute is retained. However, if there is a value such as a credit card
116124
number in the `notes` field that matched a regular expression on the list of

processor/redactionprocessor/config.go

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ type Config struct {
1414
// allow all keys, you should explicitly set AllowAllKeys
1515
AllowedKeys []string `mapstructure:"allowed_keys"`
1616

17+
// BlockedKeyPatterns is a list of blocked span attribute key patterns. Span attributes
18+
// matching the regexes on the list are masked.
19+
BlockedKeyPatterns []string `mapstructure:"blocked_key_patterns"`
20+
1721
// IgnoredKeys is a list of span attribute keys that are not redacted.
1822
// Span attributes in this list are allowed to pass through the filter
1923
// without being changed or removed.

processor/redactionprocessor/config_test.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@ func TestLoadConfig(t *testing.T) {
2626
{
2727
id: component.NewIDWithName(metadata.Type, ""),
2828
expected: &Config{
29-
AllowAllKeys: false,
30-
AllowedKeys: []string{"description", "group", "id", "name"},
31-
IgnoredKeys: []string{"safe_attribute"},
32-
BlockedValues: []string{"4[0-9]{12}(?:[0-9]{3})?", "(5[1-5][0-9]{14})"},
33-
AllowedValues: []string{"[email protected]"},
34-
Summary: debug,
29+
AllowAllKeys: false,
30+
AllowedKeys: []string{"description", "group", "id", "name"},
31+
IgnoredKeys: []string{"safe_attribute"},
32+
BlockedValues: []string{"4[0-9]{12}(?:[0-9]{3})?", "(5[1-5][0-9]{14})"},
33+
BlockedKeyPatterns: []string{".*token.*", ".*api_key.*"},
34+
AllowedValues: []string{"[email protected]"},
35+
Summary: debug,
3536
},
3637
},
3738
{

processor/redactionprocessor/factory_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ func TestDefaultConfiguration(t *testing.T) {
1919
assert.Empty(t, c.AllowedKeys)
2020
assert.Empty(t, c.BlockedValues)
2121
assert.Empty(t, c.AllowedValues)
22+
assert.Empty(t, c.BlockedKeyPatterns)
2223
}
2324

2425
func TestCreateTestProcessor(t *testing.T) {

processor/redactionprocessor/processor.go

+25-9
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ type redaction struct {
2828
blockRegexList map[string]*regexp.Regexp
2929
// Attribute values allowed in a span
3030
allowRegexList map[string]*regexp.Regexp
31+
// Attribute keys blocked in a span
32+
blockKeyRegexList map[string]*regexp.Regexp
3133
// Redaction processor configuration
3234
config *Config
3335
// Logger
@@ -43,6 +45,11 @@ func newRedaction(ctx context.Context, config *Config, logger *zap.Logger) (*red
4345
// TODO: Placeholder for an error metric in the next PR
4446
return nil, fmt.Errorf("failed to process block list: %w", err)
4547
}
48+
blockKeysRegexList, err := makeRegexList(ctx, config.BlockedKeyPatterns)
49+
if err != nil {
50+
// TODO: Placeholder for an error metric in the next PR
51+
return nil, fmt.Errorf("failed to process block keys list: %w", err)
52+
}
4653

4754
allowRegexList, err := makeRegexList(ctx, config.AllowedValues)
4855
if err != nil {
@@ -51,12 +58,13 @@ func newRedaction(ctx context.Context, config *Config, logger *zap.Logger) (*red
5158
}
5259

5360
return &redaction{
54-
allowList: allowList,
55-
ignoreList: ignoreList,
56-
blockRegexList: blockRegexList,
57-
allowRegexList: allowRegexList,
58-
config: config,
59-
logger: logger,
61+
allowList: allowList,
62+
ignoreList: ignoreList,
63+
blockRegexList: blockRegexList,
64+
allowRegexList: allowRegexList,
65+
blockKeyRegexList: blockKeysRegexList,
66+
config: config,
67+
logger: logger,
6068
}, nil
6169
}
6270

@@ -197,7 +205,6 @@ func (s *redaction) processAttrs(_ context.Context, attributes pcommon.Map) {
197205
}
198206

199207
strVal := value.Str()
200-
201208
// Allow any values matching the allowed list regex
202209
for _, compiledRE := range s.allowRegexList {
203210
if match := compiledRE.MatchString(strVal); match {
@@ -206,11 +213,20 @@ func (s *redaction) processAttrs(_ context.Context, attributes pcommon.Map) {
206213
}
207214
}
208215

216+
// Mask any blocked keys for the other attributes
217+
for _, compiledRE := range s.blockKeyRegexList {
218+
if match := compiledRE.MatchString(k); match {
219+
toBlock = append(toBlock, k)
220+
maskedValue := compiledRE.ReplaceAllString(strVal, "****")
221+
value.SetStr(maskedValue)
222+
return true
223+
}
224+
}
225+
209226
// Mask any blocked values for the other attributes
210227
var matched bool
211228
for _, compiledRE := range s.blockRegexList {
212-
match := compiledRE.MatchString(strVal)
213-
if match {
229+
if match := compiledRE.MatchString(strVal); match {
214230
if !matched {
215231
matched = true
216232
toBlock = append(toBlock, k)

0 commit comments

Comments
 (0)