Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement redaction filters #2243

Merged
merged 1 commit into from
Mar 28, 2024
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
17 changes: 17 additions & 0 deletions api/v1/README.md

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

434 changes: 255 additions & 179 deletions api/v1/tetragon/events.pb.go

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions api/v1/tetragon/events.pb.json.go

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

7 changes: 7 additions & 0 deletions api/v1/tetragon/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ message CapFilterSet {
repeated CapabilitiesType none = 4;
}

message RedactionFilter {
// Match events that the redaction filter will apply to.
repeated Filter match = 1;
// Regular expressions to use for redaction. Strings inside capture groups are redacted.
repeated string redact = 2;
}

// Determines the behavior of a field filter
enum FieldFilterAction {
INCLUDE = 0;
Expand Down
16 changes: 14 additions & 2 deletions cmd/tetragon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ func getFieldFilters() ([]*tetragon.FieldFilter, error) {
return filters, nil
}

func getRedactionFilters() (fieldfilters.RedactionFilterList, error) {
redactionFilters := viper.GetString(option.KeyRedactionFilters)
return fieldfilters.ParseRedactionFilterList(redactionFilters)
}

// Save daemon information so it is used by client cli but
// also by bugtool
func saveInitInfo() error {
Expand Down Expand Up @@ -401,11 +406,18 @@ func tetragonExecute() error {

hookRunner := rthooks.GlobalRunner().WithWatcher(k8sWatcher)

redactionFilters, err := getRedactionFilters()
if err != nil {
return err
}
log.WithFields(logrus.Fields{"redactionFilters": redactionFilters}).Info("Configured redaction filters")

pm, err := tetragonGrpc.NewProcessManager(
ctx,
&cleanupWg,
observer.GetSensorManager(),
hookRunner)
hookRunner,
redactionFilters)
if err != nil {
return err
}
Expand Down Expand Up @@ -705,7 +717,7 @@ func startExporter(ctx context.Context, server *server.Server) error {
}
}
req := tetragon.GetEventsRequest{AllowList: allowList, DenyList: denyList, AggregationOptions: aggregationOptions, FieldFilters: fieldFilters}
log.WithFields(logrus.Fields{"fieldFilters": fieldFilters}).Debug("Configured field filters")
log.WithFields(logrus.Fields{"fieldFilters": fieldFilters}).Info("Configured field filters")
log.WithFields(logrus.Fields{"logger": writer, "request": &req}).Info("Starting JSON exporter")
exporter := exporter.NewExporter(ctx, &req, server, encoder, writer, rateLimiter)
return exporter.Start()
Expand Down
45 changes: 44 additions & 1 deletion docs/content/en/docs/concepts/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,49 @@ only `exec_id` and `parent_exec_id` in all event types except for
{"fields":"process.exec_id,process.parent_exec_id", "event_set": ["PROCESS_EXEC"], "invert_event_set": true, "action": "INCLUDE"}
```

#### Redacting Sensitive Information

Since Tetragon traces the entire system, event exports might sometimes contain
sensitive information (for example, a secret passed via a command line argument
to a process). To prevent this information from being exfiltrated via Tetragon
JSON export, Tetragon provides a mechanism called Redaction Filters which can be
used to select events and string patterns to redact. These filters are written
in JSON and passed to the Tetragon agent via the `--redaction-filters` command
line flag or the `redactionFilters` Helm value.

To perform redactions, redaction filters define regular expressions in the
`redact` field. Any capture groups in these regular expressions are redacted and
replaced with `"*****"`.

{{< warning >}}
When writing regular expressions in JSON, it is important to escape backslash
characters. For instance `\Wpasswd\W?` would be written as `{"redact": "\\Wpasswd\\W?"}`.
{{< /warning >}}

Redaction filters select events using the `match` field, which contains one or
more filters (these filters are defined the same way as export filters). If no
match filter is defined, all events are selected.

As a concrete example, the following will redact all passwords passed to
processes with the `"--password"` argument:

```json
{"redact": ["--password(?:\\s+|=)(\\S*)"]}
```

Now, an event that contains the string `"--password=foo"` would have that string
replaced with `"--password=*****"`.

Suppose we also see some passwords passed via the -p shorthand for a specific binary, foo.
We can also redact these as follows:

```json
{"match": [{"binary_regex": "(?:^|/)foo$"}], "redact": ["-p(?:\\s+|=)(\\S*)"]}
```

With both of the above redaction filters in place, we are now redacting all
password arguments.

### `tetra` CLI

A second way is to use the [`tetra`](https://github.com/cilium/tetragon/tree/main/cmd/tetra) CLI. This
Expand Down Expand Up @@ -245,4 +288,4 @@ An example gRPC endpoint is the Tetra CLI when its not piped JSON output directl

```shell
kubectl exec -ti -n kube-system ds/tetragon -c tetragon -- tetra getevents -o compact
```
```
9 changes: 9 additions & 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.

3 changes: 2 additions & 1 deletion docs/content/en/docs/reference/helm-chart.md

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

2 changes: 2 additions & 0 deletions docs/data/tetragon_flags.yaml

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

3 changes: 2 additions & 1 deletion install/kubernetes/tetragon/README.md

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

Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ data:
{{- .Values.tetragon.exportDenyList | trim | nindent 4 }}
field-filters: |-
{{- .Values.tetragon.fieldFilters | trim | nindent 4 }}
redaction-filters: |-
{{- .Values.tetragon.redactionFilters | trim | nindent 4 }}
export-rate-limit: {{ .Values.tetragon.exportRateLimit | quote }}
{{- end }}
{{- if .Values.tetragon.enableK8sAPI }}
Expand Down
34 changes: 32 additions & 2 deletions install/kubernetes/tetragon/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,37 @@ tetragon:
# {"event_set": ["PROCESS_KPROBE"], "fields": "process", "action": "INCLUDE"}
#
fieldFilters: |-
{}

# Filters to redact secrets from string fields in Tetragon events. To perform
# redactions, redaction filters define regular expressions in the `redact`
# field. Any capture groups in these regular expressions are redacted and
# replaced with "*****".
#
# Redaction filters select events using the `match` field, which contains one
# or more filters (these filters are defined the same way as export filters).
# If no match filter is defined, all events are selected.
#
# NOTE: When writing regular expressions in JSON, it is important to escape
# backslash characters. For instance `\Wpasswd\W?` would be written as
# `{"redact": "\\Wpasswd\\W?"}`.
#
# As a concrete example, the following will redact all passwords passed to
# processes with the "--password" argument:
#
# {"redact": ["--password(?:\\s+|=)(\\S*)"]}
#
# Now, an event which contains the string "--password=foo" would have that
# string replaced with "--password=*****".
#
# Suppose we also see some passwords passed via the -p shorthand for a specific binary, foo.
# We can also redact these as follows:
#
# {"match": [{"binary_regex": "(?:^|/)foo$"}], "redact": ["-p(?:\\s+|=)(\\S*)"]}
#
# With both of the above redaction filters in place, we are now redacting all
# password arguments.
kkourt marked this conversation as resolved.
Show resolved Hide resolved
redactionFilters: |-

# Access Kubernetes API to associate Tetragon events with Kubernetes pods.
enableK8sAPI: true
# enableProcessCred enables Capabilities visibility in exec and kprobe events.
Expand Down Expand Up @@ -171,7 +201,7 @@ tetragon:
installDir: "/opt/tetragon"
# -- Security context for oci-hook-setup init container
securityContext:
privileged: true
privileged: true
# -- Extra volume mounts to add to the oci-hook-setup init container
extraVolumeMounts: []
# -- resources for the the oci-hook-setup init container
Expand Down
4 changes: 3 additions & 1 deletion pkg/bench/bench.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/cilium/tetragon/pkg/cilium"
"github.com/cilium/tetragon/pkg/defaults"
"github.com/cilium/tetragon/pkg/exporter"
"github.com/cilium/tetragon/pkg/fieldfilters"
"github.com/cilium/tetragon/pkg/grpc"
"github.com/cilium/tetragon/pkg/logger"
"github.com/cilium/tetragon/pkg/observer"
Expand Down Expand Up @@ -227,7 +228,8 @@ func startBenchmarkExporter(ctx context.Context, obs *observer.Observer, summary
ctx,
&wg,
observer.GetSensorManager(),
hookRunner)
hookRunner,
fieldfilters.RedactionFilterList{})
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/exporter/exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"github.com/cilium/tetragon/api/v1/tetragon"
"github.com/cilium/tetragon/pkg/encoder"
"github.com/cilium/tetragon/pkg/fieldfilters"
"github.com/cilium/tetragon/pkg/ratelimit"
"github.com/cilium/tetragon/pkg/rthooks"
"github.com/cilium/tetragon/pkg/server"
Expand Down Expand Up @@ -85,7 +86,7 @@ func TestExporter_Send(t *testing.T) {
eventNotifier := newFakeNotifier()
ctx, cancel := context.WithCancel(context.Background())
dr := rthooks.DummyHookRunner{}
grpcServer := server.NewServer(ctx, &wg, eventNotifier, &server.FakeObserver{}, dr)
grpcServer := server.NewServer(ctx, &wg, eventNotifier, &server.FakeObserver{}, dr, fieldfilters.RedactionFilterList{})
numRecords := 2
results := newArrayWriter(numRecords)
encoder := encoder.NewProtojsonEncoder(results)
Expand Down Expand Up @@ -190,7 +191,7 @@ func Test_rateLimitExport(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
eventNotifier := newFakeNotifier()
dr := rthooks.DummyHookRunner{}
grpcServer := server.NewServer(ctx, &wg, eventNotifier, &server.FakeObserver{}, dr)
grpcServer := server.NewServer(ctx, &wg, eventNotifier, &server.FakeObserver{}, dr, fieldfilters.RedactionFilterList{})
results := newArrayWriter(tt.totalEvents)
encoder := encoder.NewProtojsonEncoder(results)
request := &tetragon.GetEventsRequest{}
Expand Down
Loading
Loading