From a45ee282e30e18e43a8f7d5a144c0ce09e97f973 Mon Sep 17 00:00:00 2001 From: Andrei Fedotov Date: Thu, 29 Aug 2024 14:38:33 +0300 Subject: [PATCH] tetra: Add IMA hashes in compact printing Signed-off-by: Andrei Fedotov --- cmd/tetra/getevents/getevents.go | 8 +++++--- pkg/encoder/encoder.go | 31 ++++++++++++++++++++++++++++++- pkg/encoder/encoder_test.go | 26 +++++++++++++------------- 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/cmd/tetra/getevents/getevents.go b/cmd/tetra/getevents/getevents.go index 589ad62f859..ed40d071106 100644 --- a/cmd/tetra/getevents/getevents.go +++ b/cmd/tetra/getevents/getevents.go @@ -36,18 +36,19 @@ type Opts struct { Timestamps bool TTYEncode string StackTraces bool + ImaHash bool PolicyNames []string } var Options Opts // GetEncoder returns an encoder for an event stream based on configuration options. -var GetEncoder = func(w io.Writer, colorMode encoder.ColorMode, timestamps bool, compact bool, tty string, stackTraces bool) encoder.EventEncoder { +var GetEncoder = func(w io.Writer, colorMode encoder.ColorMode, timestamps bool, compact bool, tty string, stackTraces bool, imaHash bool) encoder.EventEncoder { if tty != "" { return encoder.NewTtyEncoder(w, tty) } if compact { - return encoder.NewCompactEncoder(w, colorMode, timestamps, stackTraces) + return encoder.NewCompactEncoder(w, colorMode, timestamps, stackTraces, imaHash) } return encoder.NewProtojsonEncoder(w) } @@ -121,7 +122,7 @@ func getEvents(ctx context.Context, client tetragon.FineGuidanceSensorsClient) e if err != nil { return fmt.Errorf("failed to call GetEvents: %w", err) } - eventEncoder := GetEncoder(os.Stdout, encoder.ColorMode(Options.Color), Options.Timestamps, Options.Output == "compact", Options.TTYEncode, Options.StackTraces) + eventEncoder := GetEncoder(os.Stdout, encoder.ColorMode(Options.Color), Options.Timestamps, Options.Output == "compact", Options.TTYEncode, Options.StackTraces, Options.ImaHash) for { res, err := stream.Recv() if err != nil { @@ -219,6 +220,7 @@ redirection of events to the stdin. Examples: flags.BoolVar(&Options.Timestamps, "timestamps", false, "Include timestamps in compact output") flags.StringVarP(&Options.TTYEncode, "tty-encode", "t", "", "Encode terminal data by file path (all other events will be ignored)") 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") return &cmd } diff --git a/pkg/encoder/encoder.go b/pkg/encoder/encoder.go index f040395001c..ea62321ea16 100644 --- a/pkg/encoder/encoder.go +++ b/pkg/encoder/encoder.go @@ -88,15 +88,17 @@ type CompactEncoder struct { Colorer *Colorer Timestamps bool StackTraces bool + ImaHash bool } // NewCompactEncoder initializes and returns a pointer to CompactEncoder. -func NewCompactEncoder(w io.Writer, colorMode ColorMode, timestamps bool, stackTraces bool) *CompactEncoder { +func NewCompactEncoder(w io.Writer, colorMode ColorMode, timestamps bool, stackTraces bool, imaHash bool) *CompactEncoder { return &CompactEncoder{ Writer: w, Colorer: NewColorer(colorMode), Timestamps: timestamps, StackTraces: stackTraces, + ImaHash: imaHash, } } @@ -123,6 +125,12 @@ func (p *CompactEncoder) Encode(v interface{}) error { fmt.Fprint(p.Writer, st) } + // print ima hash if available + if p.ImaHash { + st := HumanIMAHash(event, p.Colorer) + fmt.Fprint(p.Writer, st) + } + return nil } @@ -223,6 +231,27 @@ func HumanStackTrace(response *tetragon.GetEventsResponse, colorer *Colorer) str } return out.String() } +func HumanIMAHash(response *tetragon.GetEventsResponse, colorer *Colorer) string { + out := new(strings.Builder) + if ev, ok := response.Event.(*tetragon.GetEventsResponse_ProcessLsm); ok { + if ev.ProcessLsm.ImaHash != "" { + var path string + switch ev.ProcessLsm.FunctionName { + case "file_open": + case "mmap_file": + path = ev.ProcessLsm.Args[0].GetFileArg().Path + case "bprm_check_security": + path = ev.ProcessLsm.Args[0].GetLinuxBinprmArg().Path + default: + } + if path != "" { + colorer.Green.Fprintf(out, " %s", path) + colorer.Blue.Fprintf(out, " %s\n", ev.ProcessLsm.ImaHash) + } + } + } + return out.String() +} func (p *CompactEncoder) EventToString(response *tetragon.GetEventsResponse) (string, error) { switch response.Event.(type) { diff --git a/pkg/encoder/encoder_test.go b/pkg/encoder/encoder_test.go index a724f0f8c05..902b1b46525 100644 --- a/pkg/encoder/encoder_test.go +++ b/pkg/encoder/encoder_test.go @@ -21,7 +21,7 @@ import ( ) func TestCompactEncoder_InvalidEventToString(t *testing.T) { - p := NewCompactEncoder(os.Stdout, Never, false, false) + p := NewCompactEncoder(os.Stdout, Never, false, false, false) // should fail if the event field is nil. _, err := p.EventToString(&tetragon.GetEventsResponse{}) @@ -29,7 +29,7 @@ func TestCompactEncoder_InvalidEventToString(t *testing.T) { } func TestCompactEncoder_ExecEventToString(t *testing.T) { - p := NewCompactEncoder(os.Stdout, Never, false, false) + p := NewCompactEncoder(os.Stdout, Never, false, false, false) // should fail if the process field is nil. _, err := p.EventToString(&tetragon.GetEventsResponse{ @@ -74,7 +74,7 @@ func TestCompactEncoder_ExecEventToString(t *testing.T) { } func TestCompactEncoder_ExitEventToString(t *testing.T) { - p := NewCompactEncoder(os.Stdout, Never, false, false) + p := NewCompactEncoder(os.Stdout, Never, false, false, false) // should fail if the process field is nil. _, err := p.EventToString(&tetragon.GetEventsResponse{ @@ -124,7 +124,7 @@ func TestCompactEncoder_ExitEventToString(t *testing.T) { } func TestCompactEncoder_KprobeEventToString(t *testing.T) { - p := NewCompactEncoder(os.Stdout, Never, false, false) + p := NewCompactEncoder(os.Stdout, Never, false, false, false) // should fail without process field _, err := p.EventToString(&tetragon.GetEventsResponse{ @@ -157,7 +157,7 @@ func TestCompactEncoder_KprobeEventToString(t *testing.T) { } func TestCompactEncoder_KprobeOpenEventToString(t *testing.T) { - p := NewCompactEncoder(os.Stdout, Never, false, false) + p := NewCompactEncoder(os.Stdout, Never, false, false, false) // open without args result, err := p.EventToString(&tetragon.GetEventsResponse{ @@ -201,7 +201,7 @@ func TestCompactEncoder_KprobeOpenEventToString(t *testing.T) { } func TestCompactEncoder_KprobeWriteEventToString(t *testing.T) { - p := NewCompactEncoder(os.Stdout, Never, false, false) + p := NewCompactEncoder(os.Stdout, Never, false, false, false) // write without args result, err := p.EventToString(&tetragon.GetEventsResponse{ @@ -246,7 +246,7 @@ func TestCompactEncoder_KprobeWriteEventToString(t *testing.T) { } func TestCompactEncoder_KprobeCloseEventToString(t *testing.T) { - p := NewCompactEncoder(os.Stdout, Never, false, false) + p := NewCompactEncoder(os.Stdout, Never, false, false, false) // open without args result, err := p.EventToString(&tetragon.GetEventsResponse{ @@ -289,7 +289,7 @@ func TestCompactEncoder_KprobeCloseEventToString(t *testing.T) { } func TestCompactEncoder_KprobeBPFEventToString(t *testing.T) { - p := NewCompactEncoder(os.Stdout, Never, false, false) + p := NewCompactEncoder(os.Stdout, Never, false, false, false) // bpf with no args result, err := p.EventToString(&tetragon.GetEventsResponse{ @@ -337,7 +337,7 @@ func TestCompactEncoder_KprobeBPFEventToString(t *testing.T) { } func TestCompactEncoder_KprobePerfEventAllocEventToString(t *testing.T) { - p := NewCompactEncoder(os.Stdout, Never, false, false) + p := NewCompactEncoder(os.Stdout, Never, false, false, false) // perf event alloc with no args result, err := p.EventToString(&tetragon.GetEventsResponse{ @@ -384,7 +384,7 @@ func TestCompactEncoder_KprobePerfEventAllocEventToString(t *testing.T) { } func TestCompactEncoder_KprobeBPFMapAllocEventToString(t *testing.T) { - p := NewCompactEncoder(os.Stdout, Never, false, false) + p := NewCompactEncoder(os.Stdout, Never, false, false, false) // bpf map with no args result, err := p.EventToString(&tetragon.GetEventsResponse{ @@ -435,7 +435,7 @@ func TestCompactEncoder_KprobeBPFMapAllocEventToString(t *testing.T) { func TestCompactEncoder_Encode(t *testing.T) { var b bytes.Buffer - p := NewCompactEncoder(&b, Never, false, false) + p := NewCompactEncoder(&b, Never, false, false, false) // invalid event err := p.Encode(nil) @@ -466,7 +466,7 @@ func TestCompactEncoder_Encode(t *testing.T) { func TestCompactEncoder_EncodeWithTimestamp(t *testing.T) { var b bytes.Buffer - p := NewCompactEncoder(&b, Never, true, false) + p := NewCompactEncoder(&b, Never, true, false, false) // invalid event err := p.Encode(nil) @@ -579,7 +579,7 @@ func FuzzCompactEncoder(f *testing.F) { } var buf1 bytes.Buffer - compactEncoder := NewCompactEncoder(&buf1, cm, timestamps, stackTraces) + compactEncoder := NewCompactEncoder(&buf1, cm, timestamps, stackTraces, false) err = compactEncoder.Encode(msg) require.NoError(t, err) })