1
// SPDX-License-Identifier: Apache-2.0
2
// Copyright Authors of Tetragon
12
"google.golang.org/protobuf/encoding/protojson"
13
"google.golang.org/protobuf/proto"
14
"google.golang.org/protobuf/types/known/timestamppb"
16
"github.com/cilium/tetragon/api/v1/tetragon"
17
"github.com/sryoya/protorand"
18
"github.com/stretchr/testify/assert"
19
"github.com/stretchr/testify/require"
22
func TestCompactEncoder_InvalidEventToString(t *testing.T) {
23
p := NewCompactEncoder(os.Stdout, Never, false, false)
25
// should fail if the event field is nil.
26
_, err := p.EventToString(&tetragon.GetEventsResponse{})
30
func TestCompactEncoder_ExecEventToString(t *testing.T) {
31
p := NewCompactEncoder(os.Stdout, Never, false, false)
33
// should fail if the process field is nil.
34
_, err := p.EventToString(&tetragon.GetEventsResponse{
35
Event: &tetragon.GetEventsResponse_ProcessExec{
36
ProcessExec: &tetragon.ProcessExec{},
42
result, err := p.EventToString(&tetragon.GetEventsResponse{
43
Event: &tetragon.GetEventsResponse_ProcessExec{
44
ProcessExec: &tetragon.ProcessExec{
45
Process: &tetragon.Process{
46
Binary: "/usr/bin/curl",
47
Arguments: "cilium.io",
53
assert.NoError(t, err)
54
assert.Equal(t, "🚀 process my-node /usr/bin/curl cilium.io", result)
57
result, err = p.EventToString(&tetragon.GetEventsResponse{
58
Event: &tetragon.GetEventsResponse_ProcessExec{
59
ProcessExec: &tetragon.ProcessExec{
60
Process: &tetragon.Process{
61
Binary: "/usr/bin/curl",
62
Arguments: "cilium.io",
64
Namespace: "kube-system",
71
assert.NoError(t, err)
72
assert.Equal(t, "🚀 process kube-system/tetragon /usr/bin/curl cilium.io", result)
75
func TestCompactEncoder_ExitEventToString(t *testing.T) {
76
p := NewCompactEncoder(os.Stdout, Never, false, false)
78
// should fail if the process field is nil.
79
_, err := p.EventToString(&tetragon.GetEventsResponse{
80
Event: &tetragon.GetEventsResponse_ProcessExit{
81
ProcessExit: &tetragon.ProcessExit{},
87
result, err := p.EventToString(&tetragon.GetEventsResponse{
88
Event: &tetragon.GetEventsResponse_ProcessExit{
89
ProcessExit: &tetragon.ProcessExit{
90
Process: &tetragon.Process{
91
Binary: "/usr/bin/curl",
92
Arguments: "cilium.io",
94
Namespace: "kube-system",
102
assert.NoError(t, err)
103
assert.Equal(t, "💥 exit kube-system/tetragon /usr/bin/curl cilium.io 1", result)
106
result, err = p.EventToString(&tetragon.GetEventsResponse{
107
Event: &tetragon.GetEventsResponse_ProcessExit{
108
ProcessExit: &tetragon.ProcessExit{
109
Process: &tetragon.Process{
110
Binary: "/usr/bin/curl",
111
Arguments: "cilium.io",
113
Namespace: "kube-system",
121
assert.NoError(t, err)
122
assert.Equal(t, "💥 exit kube-system/tetragon /usr/bin/curl cilium.io SIGKILL", result)
125
func TestCompactEncoder_KprobeEventToString(t *testing.T) {
126
p := NewCompactEncoder(os.Stdout, Never, false, false)
128
// should fail without process field
129
_, err := p.EventToString(&tetragon.GetEventsResponse{
130
Event: &tetragon.GetEventsResponse_ProcessKprobe{
131
ProcessKprobe: &tetragon.ProcessKprobe{
132
FunctionName: "unhandled_function",
139
result, err := p.EventToString(&tetragon.GetEventsResponse{
140
Event: &tetragon.GetEventsResponse_ProcessKprobe{
141
ProcessKprobe: &tetragon.ProcessKprobe{
142
Process: &tetragon.Process{
143
Binary: "/usr/bin/curl",
145
Namespace: "kube-system",
149
FunctionName: "unhandled_function",
153
assert.NoError(t, err)
154
assert.Equal(t, "❓ syscall kube-system/tetragon /usr/bin/curl unhandled_function", result)
158
func TestCompactEncoder_KprobeOpenEventToString(t *testing.T) {
159
p := NewCompactEncoder(os.Stdout, Never, false, false)
162
result, err := p.EventToString(&tetragon.GetEventsResponse{
163
Event: &tetragon.GetEventsResponse_ProcessKprobe{
164
ProcessKprobe: &tetragon.ProcessKprobe{
165
Process: &tetragon.Process{
166
Binary: "/usr/bin/curl",
168
Namespace: "kube-system",
172
FunctionName: "fd_install",
176
assert.NoError(t, err)
177
assert.Equal(t, "📬 open kube-system/tetragon /usr/bin/curl ", result)
180
result, err = p.EventToString(&tetragon.GetEventsResponse{
181
Event: &tetragon.GetEventsResponse_ProcessKprobe{
182
ProcessKprobe: &tetragon.ProcessKprobe{
183
Process: &tetragon.Process{
184
Binary: "/usr/bin/curl",
186
Namespace: "kube-system",
190
FunctionName: "fd_install",
191
Args: []*tetragon.KprobeArgument{
193
{Arg: &tetragon.KprobeArgument_FileArg{FileArg: &tetragon.KprobeFile{Path: "/etc/password"}}},
198
assert.NoError(t, err)
199
assert.Equal(t, "📬 open kube-system/tetragon /usr/bin/curl /etc/password", result)
202
func TestCompactEncoder_KprobeWriteEventToString(t *testing.T) {
203
p := NewCompactEncoder(os.Stdout, Never, false, false)
205
// write without args
206
result, err := p.EventToString(&tetragon.GetEventsResponse{
207
Event: &tetragon.GetEventsResponse_ProcessKprobe{
208
ProcessKprobe: &tetragon.ProcessKprobe{
209
Process: &tetragon.Process{
210
Binary: "/usr/bin/curl",
212
Namespace: "kube-system",
216
FunctionName: "__x64_sys_write",
220
assert.NoError(t, err)
221
assert.Equal(t, "📝 write kube-system/tetragon /usr/bin/curl ", result)
224
result, err = p.EventToString(&tetragon.GetEventsResponse{
225
Event: &tetragon.GetEventsResponse_ProcessKprobe{
226
ProcessKprobe: &tetragon.ProcessKprobe{
227
Process: &tetragon.Process{
228
Binary: "/usr/bin/curl",
230
Namespace: "kube-system",
234
FunctionName: "__x64_sys_write",
235
Args: []*tetragon.KprobeArgument{
236
{Arg: &tetragon.KprobeArgument_FileArg{FileArg: &tetragon.KprobeFile{Path: "/etc/password"}}},
238
{Arg: &tetragon.KprobeArgument_SizeArg{SizeArg: 1234}},
243
assert.NoError(t, err)
244
assert.Equal(t, "📝 write kube-system/tetragon /usr/bin/curl /etc/password 1234 bytes", result)
247
func TestCompactEncoder_KprobeCloseEventToString(t *testing.T) {
248
p := NewCompactEncoder(os.Stdout, Never, false, false)
251
result, err := p.EventToString(&tetragon.GetEventsResponse{
252
Event: &tetragon.GetEventsResponse_ProcessKprobe{
253
ProcessKprobe: &tetragon.ProcessKprobe{
254
Process: &tetragon.Process{
255
Binary: "/usr/bin/curl",
257
Namespace: "kube-system",
261
FunctionName: "__x64_sys_close",
265
assert.NoError(t, err)
266
assert.Equal(t, "📪 close kube-system/tetragon /usr/bin/curl ", result)
269
result, err = p.EventToString(&tetragon.GetEventsResponse{
270
Event: &tetragon.GetEventsResponse_ProcessKprobe{
271
ProcessKprobe: &tetragon.ProcessKprobe{
272
Process: &tetragon.Process{
273
Binary: "/usr/bin/curl",
275
Namespace: "kube-system",
279
FunctionName: "__x64_sys_close",
280
Args: []*tetragon.KprobeArgument{
281
{Arg: &tetragon.KprobeArgument_FileArg{FileArg: &tetragon.KprobeFile{Path: "/etc/password"}}},
286
assert.NoError(t, err)
287
assert.Equal(t, "📪 close kube-system/tetragon /usr/bin/curl /etc/password", result)
290
func TestCompactEncoder_KprobeBPFEventToString(t *testing.T) {
291
p := NewCompactEncoder(os.Stdout, Never, false, false)
294
result, err := p.EventToString(&tetragon.GetEventsResponse{
295
Event: &tetragon.GetEventsResponse_ProcessKprobe{
296
ProcessKprobe: &tetragon.ProcessKprobe{
297
Process: &tetragon.Process{
298
Binary: "/usr/bin/bpftool",
300
Namespace: "kube-system",
304
FunctionName: "bpf_check",
307
assert.NoError(t, err)
308
assert.Equal(t, "🐝 bpf_load kube-system/tetragon /usr/bin/bpftool ", result)
311
result, err = p.EventToString(&tetragon.GetEventsResponse{
312
Event: &tetragon.GetEventsResponse_ProcessKprobe{
313
ProcessKprobe: &tetragon.ProcessKprobe{
314
Process: &tetragon.Process{
315
Binary: "/usr/bin/bpftool",
317
Namespace: "kube-system",
321
FunctionName: "bpf_check",
322
Args: []*tetragon.KprobeArgument{
323
{Arg: &tetragon.KprobeArgument_BpfAttrArg{
324
BpfAttrArg: &tetragon.KprobeBpfAttr{
325
ProgType: "BPF_PROG_TYPE_KPROBE",
327
ProgName: "amazing-program",
334
assert.NoError(t, err)
335
assert.Equal(t, "🐝 bpf_load kube-system/tetragon /usr/bin/bpftool BPF_PROG_TYPE_KPROBE amazing-program instruction count 2048", result)
338
func TestCompactEncoder_KprobePerfEventAllocEventToString(t *testing.T) {
339
p := NewCompactEncoder(os.Stdout, Never, false, false)
341
// perf event alloc with no args
342
result, err := p.EventToString(&tetragon.GetEventsResponse{
343
Event: &tetragon.GetEventsResponse_ProcessKprobe{
344
ProcessKprobe: &tetragon.ProcessKprobe{
345
Process: &tetragon.Process{
346
Binary: "/usr/bin/bpftool",
348
Namespace: "kube-system",
352
FunctionName: "security_perf_event_alloc",
355
assert.NoError(t, err)
356
assert.Equal(t, "🐝 perf_event_alloc kube-system/tetragon /usr/bin/bpftool ", result)
358
// perf event alloc with args
359
result, err = p.EventToString(&tetragon.GetEventsResponse{
360
Event: &tetragon.GetEventsResponse_ProcessKprobe{
361
ProcessKprobe: &tetragon.ProcessKprobe{
362
Process: &tetragon.Process{
363
Binary: "/usr/bin/bpftool",
365
Namespace: "kube-system",
369
FunctionName: "security_perf_event_alloc",
370
Args: []*tetragon.KprobeArgument{
371
{Arg: &tetragon.KprobeArgument_PerfEventArg{
372
PerfEventArg: &tetragon.KprobePerfEvent{
373
KprobeFunc: "commit_creds",
374
Type: "PERF_TYPE_TRACEPOINT",
381
assert.NoError(t, err)
382
assert.Equal(t, "🐝 perf_event_alloc kube-system/tetragon /usr/bin/bpftool PERF_TYPE_TRACEPOINT commit_creds", result)
385
func TestCompactEncoder_KprobeBPFMapAllocEventToString(t *testing.T) {
386
p := NewCompactEncoder(os.Stdout, Never, false, false)
388
// bpf map with no args
389
result, err := p.EventToString(&tetragon.GetEventsResponse{
390
Event: &tetragon.GetEventsResponse_ProcessKprobe{
391
ProcessKprobe: &tetragon.ProcessKprobe{
392
Process: &tetragon.Process{
393
Binary: "/usr/bin/bpftool",
395
Namespace: "kube-system",
399
FunctionName: "security_bpf_map_alloc",
402
assert.NoError(t, err)
403
assert.Equal(t, "🗺 bpf_map_create kube-system/tetragon /usr/bin/bpftool ", result)
406
result, err = p.EventToString(&tetragon.GetEventsResponse{
407
Event: &tetragon.GetEventsResponse_ProcessKprobe{
408
ProcessKprobe: &tetragon.ProcessKprobe{
409
Process: &tetragon.Process{
410
Binary: "/usr/bin/bpftool",
412
Namespace: "kube-system",
416
FunctionName: "security_bpf_map_alloc",
417
Args: []*tetragon.KprobeArgument{
418
{Arg: &tetragon.KprobeArgument_BpfMapArg{
419
BpfMapArg: &tetragon.KprobeBpfMap{
420
MapType: "BPF_MAP_TYPE_HASH",
424
MapName: "amazing-map",
431
assert.NoError(t, err)
432
assert.Equal(t, "🗺 bpf_map_create kube-system/tetragon /usr/bin/bpftool BPF_MAP_TYPE_HASH amazing-map key size 8 value size 8 max entries 1024", result)
435
func TestCompactEncoder_Encode(t *testing.T) {
437
p := NewCompactEncoder(&b, Never, false, false)
443
// more invalid event
444
err = p.Encode(&tetragon.GetEventsResponse{})
448
err = p.Encode(&tetragon.GetEventsResponse{
449
Event: &tetragon.GetEventsResponse_ProcessExec{
450
ProcessExec: &tetragon.ProcessExec{
451
Process: &tetragon.Process{
452
Binary: "/usr/bin/curl",
453
Arguments: "cilium.io",
455
Namespace: "kube-system",
462
assert.NoError(t, err)
463
assert.Equal(t, "🚀 process kube-system/tetragon /usr/bin/curl cilium.io\n", b.String())
466
func TestCompactEncoder_EncodeWithTimestamp(t *testing.T) {
468
p := NewCompactEncoder(&b, Never, true, false)
474
// more invalid event
475
err = p.Encode(&tetragon.GetEventsResponse{})
479
err = p.Encode(&tetragon.GetEventsResponse{
480
Event: &tetragon.GetEventsResponse_ProcessExec{
481
ProcessExec: &tetragon.ProcessExec{
482
Process: &tetragon.Process{
483
Binary: "/usr/bin/curl",
484
Arguments: "cilium.io",
486
Namespace: "kube-system",
492
Time: ×tamppb.Timestamp{},
494
assert.NoError(t, err)
495
assert.Equal(t, "1970-01-01T00:00:00.000000000Z 🚀 process kube-system/tetragon /usr/bin/curl cilium.io\n", b.String())
498
func FuzzProtojsonCompatibility(f *testing.F) {
499
for _, n := range []int64{
510
f.Fuzz(func(t *testing.T, seed int64) {
511
pr := protorand.New()
513
ev := &tetragon.GetEventsResponse{}
514
msg, err := pr.Gen(ev)
515
require.NoError(t, err)
517
var buf1 bytes.Buffer
518
protojsonEncoder := NewProtojsonEncoder(&buf1)
519
err = protojsonEncoder.Encode(msg)
520
require.NoError(t, err)
522
var buf2 bytes.Buffer
523
jsonEncoder := json.NewEncoder(&buf2)
524
err = jsonEncoder.Encode(msg)
525
require.NoError(t, err)
527
msgProtojson := &tetragon.GetEventsResponse{}
528
err = protojson.Unmarshal(buf2.Bytes(), msgProtojson)
529
require.NoError(t, err)
530
msgJson := &tetragon.GetEventsResponse{}
531
err = json.Unmarshal(buf2.Bytes(), msgJson)
532
require.NoError(t, err)
534
assert.True(t, proto.Equal(msgJson, msgProtojson))
535
assert.True(t, proto.Equal(msg, msgProtojson))