Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/v1/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

373 changes: 193 additions & 180 deletions api/v1/tetragon/events.pb.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions api/v1/tetragon/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ message Filter {
// Filter by the container name in the process.pod.container field using RE2 regular expression syntax:
// https://github.com/google/re2/wiki/Syntax
repeated string container_name_regex = 18;
// Filter by the namespace in the process.pod.namespace field using RE2 regular expression syntax:
// https://github.com/google/re2/wiki/Syntax
repeated string namespace_regex = 19;
}

// Filter over a set of Linux process capabilities. See `message Capabilities`
Expand Down
47 changes: 26 additions & 21 deletions cmd/tetra/getevents/getevents.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,28 @@ import (
)

type Opts struct {
Output string
Color string
IncludeFields []string
EventTypes []string
ExcludeFields []string
Namespaces []string
Namespace []string // deprecated: use Namespaces
Processes []string
Process []string // deprecated: use Processes
Pods []string
Pod []string // deprecated: use Pods
Containers []string
Host bool
Timestamps bool
TTYEncode string
StackTraces bool
ImaHash bool
PolicyNames []string
CelExpression []string
Reconnect bool
ReconnectWait time.Duration
Output string
Color string
IncludeFields []string
EventTypes []string
ExcludeFields []string
Namespaces []string
Namespace []string // deprecated: use Namespaces
Processes []string
Process []string // deprecated: use Processes
Pods []string
Pod []string // deprecated: use Pods
Containers []string
Host bool
Timestamps bool
TTYEncode string
StackTraces bool
ImaHash bool
PolicyNames []string
NamespaceRegex []string
CelExpression []string
Reconnect bool
ReconnectWait time.Duration
}

var Options Opts
Expand Down Expand Up @@ -95,6 +96,9 @@ var GetFilter = func() *tetragon.Filter {
if len(Options.PolicyNames) > 0 {
filter.PolicyNames = Options.PolicyNames
}
if len(Options.NamespaceRegex) > 0 {
filter.NamespaceRegex = Options.NamespaceRegex
}
if len(Options.CelExpression) > 0 {
filter.CelExpression = Options.CelExpression
}
Expand Down Expand Up @@ -257,6 +261,7 @@ redirection of events to the stdin. Examples:
flags.BoolVar(&Options.StackTraces, "stack-traces", true, "Include stack traces in compact output")
flags.BoolVar(&Options.ImaHash, "ima-hash", true, "Include ima hashes in compact output")
flags.StringSliceVar(&Options.PolicyNames, "policy-names", nil, "Get events by tracing policy names")
flags.StringSliceVar(&Options.NamespaceRegex, "namespace-regex", nil, "Get events by namespace name regex")
flags.StringSliceVar(&Options.CelExpression, "cel-expression", nil, "Get events satisfying the CEL expression")
flags.BoolVar(&Options.Reconnect, "reconnect", false, "Keep trying to connect even if an error occurred")
flags.DurationVar(&Options.ReconnectWait, "reconnect-wait", 2*time.Second, "wait time before attempting to reconnect")
Expand Down

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions docs/content/en/docs/reference/grpc-api.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/filters/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ var Filters = []OnBuildFilter{
&AncestorBinaryRegexFilter{},
&HealthCheckFilter{},
&NamespaceFilter{},
&NamespaceRegexFilter{},
&PidFilter{},
&PidSetFilter{},
&EventTypeFilter{},
Expand Down
53 changes: 53 additions & 0 deletions pkg/filters/namespace_regex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Tetragon

package filters

import (
"context"
"fmt"
"regexp"

"github.com/cilium/tetragon/api/v1/tetragon"
"github.com/cilium/tetragon/pkg/event"
)

func filterByNamespaceRegex(namespacePatterns []string) (FilterFunc, error) {
var namespaces []*regexp.Regexp
for _, pattern := range namespacePatterns {
query, err := regexp.Compile(pattern)
if err != nil {
return nil, fmt.Errorf("failed to compile regexp: %w", err)
}
namespaces = append(namespaces, query)
}
return func(ev *event.Event) bool {
process := GetProcess(ev)
if process == nil {
return false
}
if process.Pod == nil {
return false
}
for _, ns := range namespaces {
if ns.MatchString(process.Pod.Namespace) {
return true
}
}
return false
}, nil
}

type NamespaceRegexFilter struct{}

func (f *NamespaceRegexFilter) OnBuildFilter(_ context.Context, ff *tetragon.Filter) ([]FilterFunc, error) {
var fs []FilterFunc
if ff.NamespaceRegex != nil {
filters, err := filterByNamespaceRegex(ff.NamespaceRegex)
if err != nil {
return nil, err
}
fs = append(fs, filters)
}
return fs, nil
}
99 changes: 99 additions & 0 deletions pkg/filters/namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,102 @@ func TestNamespace(t *testing.T) {
ev = event.Event{Event: &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExec{ProcessExec: &tetragon.ProcessExec{Process: &tetragon.Process{}}}}}
assert.True(t, fl.MatchOne(&ev))
}

func TestNamespaceRegex(t *testing.T) {
f := []*tetragon.Filter{{NamespaceRegex: []string{"test-.*"}}}
fl, err := BuildFilterList(context.Background(), f, []OnBuildFilter{&NamespaceRegexFilter{}})
require.NoError(t, err)

ev := event.Event{
Event: &tetragon.GetEventsResponse{
Event: &tetragon.GetEventsResponse_ProcessExec{
ProcessExec: &tetragon.ProcessExec{Process: &tetragon.Process{Pod: &tetragon.Pod{Namespace: "test-app"}}},
},
},
}
assert.True(t, fl.MatchOne(&ev), "should match test-app namespace")

ev = event.Event{
Event: &tetragon.GetEventsResponse{
Event: &tetragon.GetEventsResponse_ProcessExec{
ProcessExec: &tetragon.ProcessExec{Process: &tetragon.Process{Pod: &tetragon.Pod{Namespace: "test-system"}}},
},
},
}
assert.True(t, fl.MatchOne(&ev), "should match test-system namespace")

ev = event.Event{
Event: &tetragon.GetEventsResponse{
Event: &tetragon.GetEventsResponse_ProcessExec{
ProcessExec: &tetragon.ProcessExec{Process: &tetragon.Process{Pod: &tetragon.Pod{Namespace: "kube-system"}}},
},
},
}
assert.False(t, fl.MatchOne(&ev), "should not match kube-system namespace")

ev = event.Event{
Event: &tetragon.GetEventsResponse{
Event: &tetragon.GetEventsResponse_ProcessExec{
ProcessExec: &tetragon.ProcessExec{Process: &tetragon.Process{Pod: &tetragon.Pod{Namespace: "default"}}},
},
},
}
assert.False(t, fl.MatchOne(&ev), "should not match default namespace")

ev = event.Event{
Event: &tetragon.GetEventsResponse{
Event: &tetragon.GetEventsResponse_ProcessExec{
ProcessExec: &tetragon.ProcessExec{Process: &tetragon.Process{}},
},
},
}
assert.False(t, fl.MatchOne(&ev), "should not match process without pod info")

ev = event.Event{
Event: &tetragon.GetEventsResponse{
Event: &tetragon.GetEventsResponse_ProcessExec{
ProcessExec: &tetragon.ProcessExec{},
},
},
}
assert.False(t, fl.MatchOne(&ev), "should not match nil process")
}

func TestNamespaceRegexMultiplePatterns(t *testing.T) {
f := []*tetragon.Filter{{NamespaceRegex: []string{"prod-.*", "staging-.*"}}}
fl, err := BuildFilterList(context.Background(), f, []OnBuildFilter{&NamespaceRegexFilter{}})
require.NoError(t, err)

ev := event.Event{
Event: &tetragon.GetEventsResponse{
Event: &tetragon.GetEventsResponse_ProcessExec{
ProcessExec: &tetragon.ProcessExec{Process: &tetragon.Process{Pod: &tetragon.Pod{Namespace: "prod-app"}}},
},
},
}
assert.True(t, fl.MatchOne(&ev), "should match prod-app namespace")

ev = event.Event{
Event: &tetragon.GetEventsResponse{
Event: &tetragon.GetEventsResponse_ProcessExec{
ProcessExec: &tetragon.ProcessExec{Process: &tetragon.Process{Pod: &tetragon.Pod{Namespace: "staging-app"}}},
},
},
}
assert.True(t, fl.MatchOne(&ev), "should match staging-app namespace")

ev = event.Event{
Event: &tetragon.GetEventsResponse{
Event: &tetragon.GetEventsResponse_ProcessExec{
ProcessExec: &tetragon.ProcessExec{Process: &tetragon.Process{Pod: &tetragon.Pod{Namespace: "dev-app"}}},
},
},
}
assert.False(t, fl.MatchOne(&ev), "should not match dev-app namespace")
}

func TestNamespaceRegexInvalidPattern(t *testing.T) {
f := []*tetragon.Filter{{NamespaceRegex: []string{"[invalid"}}}
_, err := BuildFilterList(context.Background(), f, []OnBuildFilter{&NamespaceRegexFilter{}})
require.Error(t, err, "should return error for invalid regex")
}
Loading
Loading