Skip to content

Commit

Permalink
x-pack/filebeat/input/cel: don't panic when redact option is not spec…
Browse files Browse the repository at this point in the history
…ified (elastic#36388)
  • Loading branch information
efd6 authored Aug 22, 2023
1 parent 818c72d commit ecc82aa
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff]
- Fix handling of Juniper SRX structured data when there is no leading junos element. {issue}36270[36270] {pull}36308[36308]
- Remove erroneous error log in GCPPubSub input. {pull}36296[36296]
- Fix Filebeat Cisco module with missing escape character {issue}36325[36325] {pull}36326[36326]
- Fix panic when redact option is not provided to CEL input. {issue}36387[36387] {pull}36388[36388]

*Heartbeat*

Expand Down
15 changes: 7 additions & 8 deletions x-pack/filebeat/input/cel/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,11 @@ func (i input) run(env v2.Context, src *source, cursor map[string]interface{}, p
}

// Process a set of event requests.
log.Debugw("request state", logp.Namespace("cel"), "state", redactor{state: state, mask: cfg.Redact.Fields, delete: cfg.Redact.Delete})
log.Debugw("request state", logp.Namespace("cel"), "state", redactor{state: state, cfg: cfg.Redact})
metrics.executions.Add(1)
start := i.now()
state, err = evalWith(ctx, prg, state, start)
log.Debugw("response state", logp.Namespace("cel"), "state", redactor{state: state, mask: cfg.Redact.Fields, delete: cfg.Redact.Delete})
log.Debugw("response state", logp.Namespace("cel"), "state", redactor{state: state, cfg: cfg.Redact})
if err != nil {
switch {
case errors.Is(err, context.Canceled), errors.Is(err, context.DeadlineExceeded):
Expand Down Expand Up @@ -1021,21 +1021,20 @@ func (m *inputMetrics) Close() {

// redactor implements lazy field redaction of sets of a mapstr.M.
type redactor struct {
state mapstr.M
mask []string // mask is the set of dotted paths to redact from state.
delete bool // if delete is true, delete redacted fields instead of showing a redaction.
state mapstr.M
cfg *redact
}

// String renders the JSON corresponding to r.state after applying redaction
// operations.
func (r redactor) String() string {
if len(r.mask) == 0 {
if r.cfg == nil || len(r.cfg.Fields) == 0 {
return r.state.String()
}
c := make(mapstr.M, len(r.state))
cloneMap(c, r.state)
for _, mask := range r.mask {
if r.delete {
for _, mask := range r.cfg.Fields {
if r.cfg.Delete {
walkMap(c, mask, func(parent mapstr.M, key string) {
delete(parent, key)
})
Expand Down
58 changes: 41 additions & 17 deletions x-pack/filebeat/input/cel/input_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1571,14 +1571,26 @@ func paginationArrayHandler() http.HandlerFunc {
}

var redactorTests = []struct {
name string
state mapstr.M
mask []string
delete bool
name string
state mapstr.M
cfg *redact

wantOrig string
wantRedact string
}{
{
name: "nil_redact",
state: mapstr.M{
"auth": mapstr.M{
"user": "fred",
"pass": "top_secret",
},
"other": "data",
},
cfg: nil,
wantOrig: `{"auth":{"pass":"top_secret","user":"fred"},"other":"data"}`,
wantRedact: `{"auth":{"pass":"top_secret","user":"fred"},"other":"data"}`,
},
{
name: "auth_no_delete",
state: mapstr.M{
Expand All @@ -1588,8 +1600,10 @@ var redactorTests = []struct {
},
"other": "data",
},
mask: []string{"auth"},
delete: false,
cfg: &redact{
Fields: []string{"auth"},
Delete: false,
},
wantOrig: `{"auth":{"pass":"top_secret","user":"fred"},"other":"data"}`,
wantRedact: `{"auth":"*","other":"data"}`,
},
Expand All @@ -1602,8 +1616,10 @@ var redactorTests = []struct {
},
"other": "data",
},
mask: []string{"auth"},
delete: true,
cfg: &redact{
Fields: []string{"auth"},
Delete: true,
},
wantOrig: `{"auth":{"pass":"top_secret","user":"fred"},"other":"data"}`,
wantRedact: `{"other":"data"}`,
},
Expand All @@ -1616,8 +1632,10 @@ var redactorTests = []struct {
},
"other": "data",
},
mask: []string{"auth.pass"},
delete: false,
cfg: &redact{
Fields: []string{"auth.pass"},
Delete: false,
},
wantOrig: `{"auth":{"pass":"top_secret","user":"fred"},"other":"data"}`,
wantRedact: `{"auth":{"pass":"*","user":"fred"},"other":"data"}`,
},
Expand All @@ -1630,8 +1648,10 @@ var redactorTests = []struct {
},
"other": "data",
},
mask: []string{"auth.pass"},
delete: true,
cfg: &redact{
Fields: []string{"auth.pass"},
Delete: true,
},
wantOrig: `{"auth":{"pass":"top_secret","user":"fred"},"other":"data"}`,
wantRedact: `{"auth":{"user":"fred"},"other":"data"}`,
},
Expand All @@ -1644,8 +1664,10 @@ var redactorTests = []struct {
},
"other": "data",
},
mask: []string{"cursor.key"},
delete: false,
cfg: &redact{
Fields: []string{"cursor.key"},
Delete: false,
},
wantOrig: `{"cursor":[{"key":"val_one","other":"data"},{"key":"val_two","other":"data"}],"other":"data"}`,
wantRedact: `{"cursor":[{"key":"*","other":"data"},{"key":"*","other":"data"}],"other":"data"}`,
},
Expand All @@ -1658,8 +1680,10 @@ var redactorTests = []struct {
},
"other": "data",
},
mask: []string{"cursor.key"},
delete: true,
cfg: &redact{
Fields: []string{"cursor.key"},
Delete: true,
},
wantOrig: `{"cursor":[{"key":"val_one","other":"data"},{"key":"val_two","other":"data"}],"other":"data"}`,
wantRedact: `{"cursor":[{"other":"data"},{"other":"data"}],"other":"data"}`,
},
Expand All @@ -1668,7 +1692,7 @@ var redactorTests = []struct {
func TestRedactor(t *testing.T) {
for _, test := range redactorTests {
t.Run(test.name, func(t *testing.T) {
got := fmt.Sprint(redactor{state: test.state, mask: test.mask, delete: test.delete})
got := fmt.Sprint(redactor{state: test.state, cfg: test.cfg})
orig := fmt.Sprint(test.state)
if orig != test.wantOrig {
t.Errorf("unexpected original state after redaction:\n--- got\n--- want\n%s", cmp.Diff(orig, test.wantOrig))
Expand Down

0 comments on commit ecc82aa

Please sign in to comment.