1
// SPDX-License-Identifier: Apache-2.0
2
// Copyright Authors of Tetragon
14
"github.com/cilium/tetragon/api/v1/tetragon"
15
"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
16
"github.com/cilium/tetragon/pkg/policyfilter"
17
"github.com/cilium/tetragon/pkg/sensors/program"
18
"github.com/cilium/tetragon/pkg/tracingpolicy"
20
slimv1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1"
21
"github.com/stretchr/testify/assert"
22
"github.com/stretchr/testify/require"
25
type dummyHandler struct {
30
func (d *dummyHandler) PolicyHandler(_ tracingpolicy.TracingPolicy, _ policyfilter.PolicyID) (SensorIface, error) {
34
// TestAddPolicy tests the addition of a policy with a dummy sensor
35
func TestAddPolicy(t *testing.T) {
36
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
39
RegisterPolicyHandlerAtInit("dummy", &dummyHandler{s: &Sensor{Name: "dummy-sensor"}})
41
delete(registeredPolicyHandlers, "dummy")
44
policy := v1alpha1.TracingPolicy{}
45
mgr, err := StartSensorManager("", nil)
46
assert.NoError(t, err)
48
if err := mgr.StopSensorManager(ctx); err != nil {
49
panic("failed to stop sensor manager")
52
policy.ObjectMeta.Name = "test-policy"
53
err = mgr.AddTracingPolicy(ctx, &policy)
54
assert.NoError(t, err)
55
l, err := mgr.ListSensors(ctx)
56
assert.NoError(t, err)
57
assert.Equal(t, []SensorStatus{{Name: "dummy-sensor", Enabled: true, Collection: "test-policy (object:0/) (type:/)"}}, *l)
60
// TestAddPolicies tests the addition of a policy with two dummy sensors
61
func TestAddPolicies(t *testing.T) {
62
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
65
RegisterPolicyHandlerAtInit("dummy1", &dummyHandler{s: &Sensor{Name: "dummy-sensor1"}})
66
RegisterPolicyHandlerAtInit("dummy2", &dummyHandler{s: &Sensor{Name: "dummy-sensor2"}})
68
delete(registeredPolicyHandlers, "dummy1")
69
delete(registeredPolicyHandlers, "dummy2")
72
policy := v1alpha1.TracingPolicy{}
73
mgr, err := StartSensorManager("", nil)
74
assert.NoError(t, err)
76
if err := mgr.StopSensorManager(ctx); err != nil {
77
panic("failed to stop sensor manager")
80
policy.ObjectMeta.Name = "test-policy"
81
err = mgr.AddTracingPolicy(ctx, &policy)
82
assert.NoError(t, err)
83
l, err := mgr.ListSensors(ctx)
84
assert.NoError(t, err)
85
assert.ElementsMatch(t, []SensorStatus{
86
{Name: "dummy-sensor1", Enabled: true, Collection: "test-policy (object:0/) (type:/)"},
87
{Name: "dummy-sensor2", Enabled: true, Collection: "test-policy (object:0/) (type:/)"},
91
// TestAddPolicySpecError tests the addition of a policy where a spec fails to load
92
func TestAddPolicySpecError(t *testing.T) {
93
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
96
RegisterPolicyHandlerAtInit("dummy", &dummyHandler{s: &Sensor{Name: "dummy-sensor"}})
97
RegisterPolicyHandlerAtInit("spec-fail", &dummyHandler{e: errors.New("spec load is expected to fail: failed")})
99
delete(registeredPolicyHandlers, "dummy")
100
delete(registeredPolicyHandlers, "spec-fail")
103
policy := v1alpha1.TracingPolicy{}
104
mgr, err := StartSensorManager("", nil)
105
assert.NoError(t, err)
107
if err := mgr.StopSensorManager(ctx); err != nil {
108
panic("failed to stop sensor manager")
111
policy.ObjectMeta.Name = "test-policy"
112
err = mgr.AddTracingPolicy(ctx, &policy)
113
assert.NotNil(t, err)
114
t.Logf("got error (as expected): %s", err)
115
l, err := mgr.ListSensors(ctx)
116
assert.NoError(t, err)
117
assert.Equal(t, []SensorStatus{}, *l)
120
// TestAddPolicyLoadError tests the addition of a policy where the sensor is expected to fail
121
func TestAddPolicyLoadError(t *testing.T) {
122
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
125
RegisterPolicyHandlerAtInit("dummy", &dummyHandler{s: &Sensor{Name: "dummy-sensor"}})
126
RegisterPolicyHandlerAtInit("load-fail", &dummyHandler{s: &Sensor{
127
Name: "dummy-sensor",
128
Progs: []*program.Program{{Name: "bpf-program-that-does-not-exist"}},
131
delete(registeredPolicyHandlers, "dummy")
132
delete(registeredPolicyHandlers, "load-fail")
135
policy := v1alpha1.TracingPolicy{}
136
mgr, err := StartSensorManager("", nil)
137
assert.NoError(t, err)
139
if err := mgr.StopSensorManager(ctx); err != nil {
140
panic("failed to stop sensor manager")
143
policy.ObjectMeta.Name = "test-policy"
144
addError := mgr.AddTracingPolicy(ctx, &policy)
145
assert.NotNil(t, addError)
146
t.Logf("got error (as expected): %s", addError)
148
l, err := mgr.ListTracingPolicies(ctx)
149
assert.NoError(t, err)
150
assert.Len(t, l.Policies, 1)
151
assert.Equal(t, LoadErrorState.ToTetragonState(), l.Policies[0].State)
152
assert.Equal(t, addError.Error(), l.Policies[0].Error)
155
func TestPolicyFilterDisabled(t *testing.T) {
156
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
159
handler, err := newHandler(policyfilter.DisabledState(), newCollectionMap(), "")
160
assert.NoError(t, err)
161
mgr, err := startSensorManager(handler, handler.collections, nil)
162
assert.NoError(t, err)
163
defer mgr.StopSensorManager(ctx)
165
policy := v1alpha1.TracingPolicy{}
167
// normal policy should succeed
168
policyName := "test-policy"
169
policyNamespace := ""
170
policy.ObjectMeta.Name = policyName
171
err = mgr.AddTracingPolicy(ctx, &policy)
172
require.NoError(t, err, fmt.Sprintf("Add tracing policy failed with error: %v", err))
173
err = mgr.DeleteTracingPolicy(ctx, policyName, policyNamespace)
174
require.NoError(t, err)
175
err = mgr.AddTracingPolicy(ctx, &policy)
176
require.NoError(t, err)
177
err = mgr.DeleteTracingPolicy(ctx, policyName, policyNamespace)
178
require.NoError(t, err)
180
// namespaced policy with disabled state should fail
181
namespacedPolicy := v1alpha1.TracingPolicyNamespaced{}
182
policy.ObjectMeta.Name = policyName
183
namespacedPolicy.ObjectMeta.Name = policyName
184
namespacedPolicy.ObjectMeta.Namespace = "namespace"
185
err = mgr.AddTracingPolicy(ctx, &namespacedPolicy)
186
require.Error(t, err)
188
// policy with pod selector should fail
189
policy.Spec.PodSelector = &slimv1.LabelSelector{
190
MatchExpressions: []slimv1.LabelSelectorRequirement{{
192
Operator: slimv1.LabelSelectorOpExists,
195
err = mgr.AddTracingPolicy(ctx, &policy)
196
require.Error(t, err)
199
func TestPolicyStates(t *testing.T) {
200
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
203
t.Run("LoadError", func(t *testing.T) {
204
RegisterPolicyHandlerAtInit("load-fail", &dummyHandler{s: &Sensor{
205
Name: "dummy-sensor",
206
Progs: []*program.Program{{Name: "bpf-program-that-does-not-exist"}},
209
delete(registeredPolicyHandlers, "load-fail")
212
policy := v1alpha1.TracingPolicy{}
213
mgr, err := StartSensorManager("", nil)
214
require.NoError(t, err)
216
if err := mgr.StopSensorManager(ctx); err != nil {
217
panic("failed to stop sensor manager")
220
policy.ObjectMeta.Name = "test-policy"
221
addError := mgr.AddTracingPolicy(ctx, &policy)
222
assert.NotNil(t, addError)
224
l, err := mgr.ListTracingPolicies(ctx)
225
assert.NoError(t, err)
226
assert.Len(t, l.Policies, 1)
227
assert.Equal(t, LoadErrorState.ToTetragonState(), l.Policies[0].State)
228
assert.Equal(t, addError.Error(), l.Policies[0].Error)
231
t.Run("EnabledDisabled", func(t *testing.T) {
232
RegisterPolicyHandlerAtInit("dummy", &dummyHandler{s: &Sensor{Name: "dummy-sensor"}})
234
delete(registeredPolicyHandlers, "dummy")
237
policy := v1alpha1.TracingPolicy{}
238
mgr, err := StartSensorManager("", nil)
239
require.NoError(t, err)
241
if err := mgr.StopSensorManager(ctx); err != nil {
242
panic("failed to stop sensor manager")
245
policy.ObjectMeta.Name = "test-policy"
246
err = mgr.AddTracingPolicy(ctx, &policy)
247
assert.NoError(t, err)
249
l, err := mgr.ListTracingPolicies(ctx)
250
assert.NoError(t, err)
251
assert.Len(t, l.Policies, 1)
252
assert.Equal(t, EnabledState.ToTetragonState(), l.Policies[0].State)
254
err = mgr.DisableTracingPolicy(ctx, policy.ObjectMeta.Name, policy.Namespace)
255
assert.NoError(t, err)
256
l, err = mgr.ListTracingPolicies(ctx)
257
assert.NoError(t, err)
258
assert.Len(t, l.Policies, 1)
259
assert.Equal(t, DisabledState.ToTetragonState(), l.Policies[0].State)
263
// TestPolicyLoadErrorOverride tests the fact that you can add a TracingPolicy
264
// with the same name as an existing one if it's in a LoadError state
265
func TestPolicyLoadErrorOverride(t *testing.T) {
266
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
269
RegisterPolicyHandlerAtInit("load-fail", &dummyHandler{s: &Sensor{
270
Name: "dummy-sensor",
271
Progs: []*program.Program{{Name: "bpf-program-that-does-not-exist"}},
274
delete(registeredPolicyHandlers, "load-fail")
277
policy := v1alpha1.TracingPolicy{}
278
mgr, err := StartSensorManager("", nil)
279
require.NoError(t, err)
281
if err := mgr.StopSensorManager(ctx); err != nil {
282
panic("failed to stop sensor manager")
285
policy.ObjectMeta.Name = "test-policy"
286
addError := mgr.AddTracingPolicy(ctx, &policy)
287
assert.NotNil(t, addError)
289
l, err := mgr.ListTracingPolicies(ctx)
290
assert.NoError(t, err)
291
assert.Len(t, l.Policies, 1)
292
assert.Equal(t, LoadErrorState.ToTetragonState(), l.Policies[0].State)
293
assert.Equal(t, addError.Error(), l.Policies[0].Error)
295
// try to override the existing registered LoadError policy
296
delete(registeredPolicyHandlers, "load-fail")
297
RegisterPolicyHandlerAtInit("dummy", &dummyHandler{s: &Sensor{Name: "dummy-sensor"}})
299
delete(registeredPolicyHandlers, "dummy")
301
addError = mgr.AddTracingPolicy(ctx, &policy)
302
assert.NoError(t, addError)
304
l, err = mgr.ListTracingPolicies(ctx)
305
assert.NoError(t, err)
306
assert.Len(t, l.Policies, 1)
307
assert.Equal(t, EnabledState.ToTetragonState(), l.Policies[0].State)
310
func TestPolicyListingWhileLoadUnload(t *testing.T) {
311
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
314
polName := "test-policy"
315
testSensor := makeTestDelayedSensor(t)
317
mgr, err := StartSensorManager("", nil)
318
require.NoError(t, err)
320
if err := mgr.StopSensorManager(ctx); err != nil {
321
panic("failed to stop sensor manager")
325
checkPolicy := func(t *testing.T, statuses []*tetragon.TracingPolicyStatus, state tetragon.TracingPolicyState) {
326
require.Equal(t, 1, len(statuses))
328
require.Equal(t, pol.Name, polName)
329
require.Equal(t, pol.State, state)
332
var wg sync.WaitGroup
336
// wait until at least one policy shows up, verify that it's in loading state and
337
// unblock the loading of the policy
339
l, err := mgr.ListTracingPolicies(ctx)
340
require.NoError(t, err)
341
if len(l.Policies) > 0 {
342
checkPolicy(t, l.Policies, tetragon.TracingPolicyState_TP_STATE_LOADING)
343
testSensor.unblock(t)
346
time.Sleep(1 * time.Millisecond)
351
t.Log("adding policy")
352
policy := v1alpha1.TracingPolicy{}
353
policy.ObjectMeta.Name = polName
354
err = mgr.AddTracingPolicy(ctx, &policy)
355
require.NoError(t, err)
358
// check that policy is now enabled
359
l, err := mgr.ListTracingPolicies(ctx)
360
require.NoError(t, err)
361
checkPolicy(t, l.Policies, tetragon.TracingPolicyState_TP_STATE_ENABLED)
365
// wait until at least one policy shows up, verify that it's in unloading state and
366
// unblock the unloading of the policy
368
l, err := mgr.ListTracingPolicies(ctx)
369
require.NoError(t, err)
370
require.Equal(t, len(l.Policies), 1)
371
if l.Policies[0].State == tetragon.TracingPolicyState_TP_STATE_UNLOADING {
372
testSensor.unblock(t)
375
time.Sleep(1 * time.Millisecond)
380
t.Log("disabling policy")
381
err = mgr.DisableTracingPolicy(ctx, polName, "")
382
require.NoError(t, err)
385
// check that policy is now disabled
386
l, err = mgr.ListTracingPolicies(ctx)
387
require.NoError(t, err)
388
checkPolicy(t, l.Policies, tetragon.TracingPolicyState_TP_STATE_DISABLED)
393
l, err := mgr.ListTracingPolicies(ctx)
394
require.NoError(t, err)
395
require.Equal(t, len(l.Policies), 1, "policies:", l.Policies)
396
if l.Policies[0].State == tetragon.TracingPolicyState_TP_STATE_LOADING {
397
testSensor.unblock(t)
400
time.Sleep(1000 * time.Millisecond)
405
t.Log("re-enabling policy")
406
err = mgr.EnableTracingPolicy(ctx, polName, "")
407
require.NoError(t, err)
410
// check that policy is now diabled
411
l, err = mgr.ListTracingPolicies(ctx)
412
require.NoError(t, err)
413
checkPolicy(t, l.Policies, tetragon.TracingPolicyState_TP_STATE_ENABLED)
415
t.Log("deleting policy")
416
err = mgr.DeleteTracingPolicy(ctx, polName, "")
417
require.NoError(t, err)
418
l, err = mgr.ListTracingPolicies(ctx)
419
require.NoError(t, err)
420
require.Equal(t, 0, len(l.Policies))