Skip to content

Commit

Permalink
fieldfilters: fix regression with missing top-level info and add test
Browse files Browse the repository at this point in the history
[upstream commit 651fcf1]

We had a regression after some fieldfilter bug fixes and performance optimizations that
caused top-level information to be missing from events when field filters are applied. The
fix here is to make sure that we are setting non-event fields in the destination struct.
Apply the fix and add a unit test to check for future regressions.

Signed-off-by: William Findlay <[email protected]>
  • Loading branch information
willfindlay committed Dec 14, 2023
1 parent 85c2171 commit c3bc9a0
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
24 changes: 18 additions & 6 deletions pkg/fieldfilters/fields.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package fieldfilters

import (
"encoding/json"
"errors"
"fmt"
"io"
"strings"
Expand Down Expand Up @@ -206,20 +207,31 @@ func (f *FieldFilter) Filter(event *tetragon.GetEventsResponse) (*tetragon.GetEv

src := event.ProtoReflect()
dst := src.New()
var filterErr error
var filterErrs []error
src.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
if fd.ContainingOneof() == nil || !src.Has(fd) {
if !src.Has(fd) {
return true
}
event := src.Get(fd).Message().Interface()
dstEvent := dst.Mutable(fd).Message().Interface()
filterErr = fieldmask_utils.StructToStruct(f.fields, event, dstEvent)

if fd.ContainingOneof() != nil && fd.ContainingOneof().Name() == "event" {
event := src.Get(fd).Message().Interface()
dstEvent := dst.Mutable(fd).Message().Interface()
err := fieldmask_utils.StructToStruct(f.fields, event, dstEvent)
if err != nil {
filterErrs = append(filterErrs, err)
}
return true
}

// Preserve all information that is not in the Event field
dst.Set(fd, v)

return true
})

if !src.IsValid() {
return nil, fmt.Errorf("invalid event after field filter")
}

return dst.Interface().(*tetragon.GetEventsResponse), filterErr
return dst.Interface().(*tetragon.GetEventsResponse), errors.Join(filterErrs...)
}
26 changes: 26 additions & 0 deletions pkg/fieldfilters/fields_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,32 @@ func TestEmptyFieldFilter(t *testing.T) {
assert.True(t, proto.Equal(ev, expected), "events are equal after filter")
}

func TestEmptyFieldFilterTopLevelInformation(t *testing.T) {
ev := &tetragon.GetEventsResponse{
NodeName: "foobarqux",
AggregationInfo: &tetragon.AggregationInfo{
Count: 1000,
},
Time: &timestamppb.Timestamp{
Seconds: 1000,
Nanos: 1000,
},
Event: &tetragon.GetEventsResponse_ProcessExec{
ProcessExec: &tetragon.ProcessExec{
Process: &tetragon.Process{},
Parent: &tetragon.Process{},
},
},
}

filter, err := NewExcludeFieldFilter(nil, nil, false)
require.NoError(t, err)
ev, _ = filter.Filter(ev)
assert.NotEmpty(t, ev.NodeName, "node name must not be empty")
assert.NotEmpty(t, ev.Time, "timestamp must not be empty")
assert.NotEmpty(t, ev.AggregationInfo, "aggregation info must not be empty")
}

func TestFieldFilterInvertedEventSet(t *testing.T) {
ev := &tetragon.GetEventsResponse{
Event: &tetragon.GetEventsResponse_ProcessExec{
Expand Down

0 comments on commit c3bc9a0

Please sign in to comment.