1
16
17 package debug
18
19 import (
20 "fmt"
21 "testing"
22
23 "github.com/google/go-cmp/cmp"
24
25 corev1 "k8s.io/api/core/v1"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/utils/pointer"
29 )
30
31 var testNode = &corev1.Node{
32 ObjectMeta: metav1.ObjectMeta{
33 Name: "node-XXX",
34 },
35 }
36
37 func TestGeneralProfile(t *testing.T) {
38 pod := &corev1.Pod{
39 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
40 Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
41 {
42 EphemeralContainerCommon: corev1.EphemeralContainerCommon{
43 Name: "dbg", Image: "dbgimage",
44 },
45 },
46 }},
47 }
48
49 tests := map[string]struct {
50 pod *corev1.Pod
51 containerName string
52 target runtime.Object
53 expectPod *corev1.Pod
54 expectErr bool
55 }{
56 "bad inputs results in error": {
57 pod: nil,
58 containerName: "dbg",
59 target: runtime.Object(nil),
60 expectErr: true,
61 },
62 "debug by ephemeral container": {
63 pod: pod,
64 containerName: "dbg",
65 target: pod,
66 expectPod: &corev1.Pod{
67 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
68 Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
69 {
70 EphemeralContainerCommon: corev1.EphemeralContainerCommon{
71 Name: "dbg", Image: "dbgimage",
72 SecurityContext: &corev1.SecurityContext{
73 Capabilities: &corev1.Capabilities{
74 Add: []corev1.Capability{"SYS_PTRACE"},
75 },
76 },
77 },
78 },
79 }},
80 },
81 },
82 "debug by pod copy": {
83 pod: &corev1.Pod{
84 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
85 Spec: corev1.PodSpec{
86 Containers: []corev1.Container{
87 {Name: "app", Image: "appimage"},
88 {
89 Name: "dbg",
90 Image: "dbgimage",
91 SecurityContext: &corev1.SecurityContext{
92 Capabilities: &corev1.Capabilities{
93 Add: []corev1.Capability{"NET_ADMIN"},
94 },
95 },
96 },
97 },
98 },
99 },
100 containerName: "dbg",
101 target: &corev1.Pod{
102 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
103 Spec: corev1.PodSpec{
104 Containers: []corev1.Container{
105 {Name: "app", Image: "appimage"},
106 },
107 },
108 },
109 expectPod: &corev1.Pod{
110 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
111 Spec: corev1.PodSpec{
112 Containers: []corev1.Container{
113 {Name: "app", Image: "appimage"},
114 {
115 Name: "dbg",
116 Image: "dbgimage",
117 SecurityContext: &corev1.SecurityContext{
118 Capabilities: &corev1.Capabilities{
119 Add: []corev1.Capability{"NET_ADMIN", "SYS_PTRACE"},
120 },
121 },
122 },
123 },
124 ShareProcessNamespace: pointer.Bool(true),
125 },
126 },
127 },
128 "debug by node": {
129 pod: &corev1.Pod{
130 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
131 Spec: corev1.PodSpec{
132 Containers: []corev1.Container{
133 {Name: "dbg", Image: "dbgimage"},
134 },
135 },
136 },
137 containerName: "dbg",
138 target: testNode,
139 expectPod: &corev1.Pod{
140 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
141 Spec: corev1.PodSpec{
142 HostNetwork: true,
143 HostPID: true,
144 HostIPC: true,
145 Containers: []corev1.Container{
146 {
147 Name: "dbg",
148 Image: "dbgimage",
149 VolumeMounts: []corev1.VolumeMount{
150 {
151 MountPath: "/host",
152 Name: "host-root",
153 },
154 },
155 },
156 },
157 Volumes: []corev1.Volume{
158 {
159 Name: "host-root",
160 VolumeSource: corev1.VolumeSource{
161 HostPath: &corev1.HostPathVolumeSource{Path: "/"},
162 },
163 },
164 },
165 },
166 },
167 },
168 }
169
170 for name, test := range tests {
171 t.Run(name, func(t *testing.T) {
172 err := (&generalProfile{}).Apply(test.pod, test.containerName, test.target)
173 if (err != nil) != test.expectErr {
174 t.Fatalf("expect error: %v, got error: %v", test.expectErr, (err != nil))
175 }
176 if err != nil {
177 return
178 }
179 if diff := cmp.Diff(test.expectPod, test.pod); diff != "" {
180 t.Error("unexpected diff in generated object: (-want +got):\n", diff)
181 }
182 })
183 }
184 }
185
186 func TestBaselineProfile(t *testing.T) {
187 pod := &corev1.Pod{
188 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
189 Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
190 {
191 EphemeralContainerCommon: corev1.EphemeralContainerCommon{
192 Name: "dbg", Image: "dbgimage",
193 SecurityContext: &corev1.SecurityContext{
194 Capabilities: &corev1.Capabilities{
195 Add: []corev1.Capability{"SYS_PTRACE"},
196 },
197 },
198 },
199 },
200 }},
201 }
202
203 tests := map[string]struct {
204 pod *corev1.Pod
205 containerName string
206 target runtime.Object
207 expectPod *corev1.Pod
208 expectErr bool
209 }{
210 "bad inputs results in error": {
211 pod: nil,
212 containerName: "dbg",
213 target: runtime.Object(nil),
214 expectErr: true,
215 },
216 "debug by ephemeral container": {
217 pod: pod,
218 containerName: "dbg",
219 target: pod,
220 expectPod: &corev1.Pod{
221 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
222 Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
223 {
224 EphemeralContainerCommon: corev1.EphemeralContainerCommon{
225 Name: "dbg", Image: "dbgimage",
226 },
227 },
228 }},
229 },
230 },
231 "debug by pod copy": {
232 pod: &corev1.Pod{
233 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
234 Spec: corev1.PodSpec{
235 Containers: []corev1.Container{
236 {Name: "app", Image: "appimage"},
237 {Name: "dbg", Image: "dbgimage"},
238 },
239 },
240 },
241 containerName: "dbg",
242 target: &corev1.Pod{
243 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
244 Spec: corev1.PodSpec{
245 Containers: []corev1.Container{
246 {Name: "app", Image: "appimage"},
247 },
248 },
249 },
250 expectPod: &corev1.Pod{
251 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
252 Spec: corev1.PodSpec{
253 ShareProcessNamespace: pointer.Bool(true),
254 Containers: []corev1.Container{
255 {Name: "app", Image: "appimage"},
256 {
257 Name: "dbg",
258 Image: "dbgimage",
259 },
260 },
261 },
262 },
263 },
264 "debug by node": {
265 pod: &corev1.Pod{
266 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
267 Spec: corev1.PodSpec{
268 Containers: []corev1.Container{
269 {Name: "dbg", Image: "dbgimage"},
270 },
271 },
272 },
273 containerName: "dbg",
274 target: testNode,
275 expectPod: &corev1.Pod{
276 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
277 Spec: corev1.PodSpec{
278 Containers: []corev1.Container{
279 {
280 Name: "dbg",
281 Image: "dbgimage",
282 },
283 },
284 },
285 },
286 },
287 }
288
289 for name, test := range tests {
290 t.Run(name, func(t *testing.T) {
291 err := (&baselineProfile{}).Apply(test.pod, test.containerName, test.target)
292 if (err != nil) != test.expectErr {
293 t.Fatalf("expect error: %v, got error: %v", test.expectErr, (err != nil))
294 }
295 if err != nil {
296 return
297 }
298 if diff := cmp.Diff(test.expectPod, test.pod); diff != "" {
299 t.Error("unexpected diff in generated object: (-want +got):\n", diff)
300 }
301 })
302 }
303 }
304
305 func TestRestrictedProfile(t *testing.T) {
306 pod := &corev1.Pod{
307 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
308 Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
309 {
310 EphemeralContainerCommon: corev1.EphemeralContainerCommon{
311 Name: "dbg", Image: "dbgimage",
312 SecurityContext: &corev1.SecurityContext{
313 Capabilities: &corev1.Capabilities{
314 Add: []corev1.Capability{"SYS_PTRACE"},
315 },
316 },
317 },
318 },
319 }},
320 }
321
322 tests := map[string]struct {
323 pod *corev1.Pod
324 containerName string
325 target runtime.Object
326 expectPod *corev1.Pod
327 expectErr bool
328 }{
329 "bad inputs results in error": {
330 pod: nil,
331 containerName: "dbg",
332 target: runtime.Object(nil),
333 expectErr: true,
334 },
335 "debug by ephemeral container": {
336 pod: pod,
337 containerName: "dbg",
338 target: pod,
339 expectPod: &corev1.Pod{
340 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
341 Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
342 {
343 EphemeralContainerCommon: corev1.EphemeralContainerCommon{
344 Name: "dbg", Image: "dbgimage",
345 SecurityContext: &corev1.SecurityContext{
346 RunAsNonRoot: pointer.Bool(true),
347 Capabilities: &corev1.Capabilities{
348 Drop: []corev1.Capability{"ALL"},
349 },
350 AllowPrivilegeEscalation: pointer.Bool(false),
351 SeccompProfile: &corev1.SeccompProfile{Type: "RuntimeDefault"},
352 },
353 },
354 },
355 }},
356 },
357 },
358 "debug by pod copy": {
359 pod: &corev1.Pod{
360 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
361 Spec: corev1.PodSpec{
362 Containers: []corev1.Container{
363 {Name: "app", Image: "appimage"},
364 {Name: "dbg", Image: "dbgimage"},
365 },
366 },
367 },
368 containerName: "dbg",
369 target: &corev1.Pod{
370 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
371 Spec: corev1.PodSpec{
372 Containers: []corev1.Container{
373 {Name: "app", Image: "appimage"},
374 },
375 },
376 },
377 expectPod: &corev1.Pod{
378 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
379 Spec: corev1.PodSpec{
380 ShareProcessNamespace: pointer.Bool(true),
381 Containers: []corev1.Container{
382 {Name: "app", Image: "appimage"},
383 {
384 Name: "dbg",
385 Image: "dbgimage",
386 SecurityContext: &corev1.SecurityContext{
387 RunAsNonRoot: pointer.Bool(true),
388 Capabilities: &corev1.Capabilities{
389 Drop: []corev1.Capability{"ALL"},
390 },
391 AllowPrivilegeEscalation: pointer.Bool(false),
392 SeccompProfile: &corev1.SeccompProfile{Type: "RuntimeDefault"},
393 },
394 },
395 },
396 },
397 },
398 },
399 "debug by node": {
400 pod: &corev1.Pod{
401 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
402 Spec: corev1.PodSpec{
403 Containers: []corev1.Container{
404 {
405 Name: "dbg",
406 Image: "dbgimage",
407 SecurityContext: &corev1.SecurityContext{
408 Capabilities: &corev1.Capabilities{
409 Add: []corev1.Capability{"ALL"},
410 },
411 AllowPrivilegeEscalation: pointer.Bool(false),
412 SeccompProfile: &corev1.SeccompProfile{Type: "RuntimeDefault"},
413 },
414 },
415 },
416 },
417 },
418 containerName: "dbg",
419 target: testNode,
420 expectPod: &corev1.Pod{
421 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
422 Spec: corev1.PodSpec{
423 Containers: []corev1.Container{
424 {
425 Name: "dbg",
426 Image: "dbgimage",
427 SecurityContext: &corev1.SecurityContext{
428 RunAsNonRoot: pointer.Bool(true),
429 Capabilities: &corev1.Capabilities{
430 Drop: []corev1.Capability{"ALL"},
431 },
432 AllowPrivilegeEscalation: pointer.Bool(false),
433 SeccompProfile: &corev1.SeccompProfile{Type: "RuntimeDefault"},
434 },
435 },
436 },
437 },
438 },
439 },
440 }
441
442 for name, test := range tests {
443 t.Run(name, func(t *testing.T) {
444 err := (&restrictedProfile{}).Apply(test.pod, test.containerName, test.target)
445 if (err != nil) != test.expectErr {
446 t.Fatalf("expect error: %v, got error: %v", test.expectErr, (err != nil))
447 }
448 if err != nil {
449 return
450 }
451 if diff := cmp.Diff(test.expectPod, test.pod); diff != "" {
452 t.Error("unexpected diff in generated object: (-want +got):\n", diff)
453 }
454 })
455 }
456 }
457
458 func TestNetAdminProfile(t *testing.T) {
459 pod := &corev1.Pod{
460 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
461 Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
462 {
463 EphemeralContainerCommon: corev1.EphemeralContainerCommon{
464 Name: "dbg", Image: "dbgimage",
465 },
466 },
467 }},
468 }
469
470 tests := []struct {
471 name string
472 pod *corev1.Pod
473 containerName string
474 target runtime.Object
475 expectPod *corev1.Pod
476 expectErr error
477 }{
478 {
479 name: "nil target",
480 pod: pod,
481 containerName: "dbg",
482 target: nil,
483 expectErr: fmt.Errorf("netadmin profile: objects of type <nil> are not supported"),
484 },
485 {
486 name: "debug by ephemeral container",
487 pod: pod,
488 containerName: "dbg",
489 target: pod,
490 expectPod: &corev1.Pod{
491 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
492 Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
493 {
494 EphemeralContainerCommon: corev1.EphemeralContainerCommon{
495 Name: "dbg", Image: "dbgimage",
496 SecurityContext: &corev1.SecurityContext{
497 Capabilities: &corev1.Capabilities{
498 Add: []corev1.Capability{"NET_ADMIN", "NET_RAW"},
499 },
500 },
501 },
502 },
503 }},
504 },
505 },
506 {
507 name: "debug by pod copy",
508 pod: &corev1.Pod{
509 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
510 Spec: corev1.PodSpec{
511 Containers: []corev1.Container{
512 {Name: "app", Image: "appimage"},
513 {Name: "dbg", Image: "dbgimage"},
514 },
515 },
516 },
517 containerName: "dbg",
518 target: &corev1.Pod{
519 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
520 Spec: corev1.PodSpec{
521 Containers: []corev1.Container{
522 {Name: "app", Image: "appimage"},
523 },
524 },
525 },
526 expectPod: &corev1.Pod{
527 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
528 Spec: corev1.PodSpec{
529 ShareProcessNamespace: pointer.Bool(true),
530 Containers: []corev1.Container{
531 {Name: "app", Image: "appimage"},
532 {
533 Name: "dbg",
534 Image: "dbgimage",
535 SecurityContext: &corev1.SecurityContext{
536 Capabilities: &corev1.Capabilities{
537 Add: []corev1.Capability{"NET_ADMIN", "NET_RAW"},
538 },
539 },
540 },
541 },
542 },
543 },
544 },
545 {
546 name: "debug by pod copy preserve existing capability",
547 pod: &corev1.Pod{
548 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
549 Spec: corev1.PodSpec{
550 Containers: []corev1.Container{
551 {Name: "app", Image: "appimage"},
552 {
553 Name: "dbg",
554 Image: "dbgimage",
555 SecurityContext: &corev1.SecurityContext{
556 Capabilities: &corev1.Capabilities{
557 Add: []corev1.Capability{"SYS_PTRACE"},
558 },
559 },
560 },
561 },
562 },
563 },
564 containerName: "dbg",
565 target: &corev1.Pod{
566 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
567 Spec: corev1.PodSpec{
568 Containers: []corev1.Container{
569 {Name: "app", Image: "appimage"},
570 },
571 },
572 },
573 expectPod: &corev1.Pod{
574 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
575 Spec: corev1.PodSpec{
576 ShareProcessNamespace: pointer.Bool(true),
577 Containers: []corev1.Container{
578 {Name: "app", Image: "appimage"},
579 {
580 Name: "dbg",
581 Image: "dbgimage",
582 SecurityContext: &corev1.SecurityContext{
583 Capabilities: &corev1.Capabilities{
584 Add: []corev1.Capability{"SYS_PTRACE", "NET_ADMIN", "NET_RAW"},
585 },
586 },
587 },
588 },
589 },
590 },
591 },
592 {
593 name: "debug by node",
594 pod: &corev1.Pod{
595 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
596 Spec: corev1.PodSpec{
597 Containers: []corev1.Container{
598 {Name: "dbg", Image: "dbgimage"},
599 },
600 },
601 },
602 containerName: "dbg",
603 target: testNode,
604 expectPod: &corev1.Pod{
605 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
606 Spec: corev1.PodSpec{
607 HostNetwork: true,
608 HostPID: true,
609 HostIPC: true,
610 Containers: []corev1.Container{
611 {
612 Name: "dbg",
613 Image: "dbgimage",
614 SecurityContext: &corev1.SecurityContext{
615 Capabilities: &corev1.Capabilities{
616 Add: []corev1.Capability{"NET_ADMIN", "NET_RAW"},
617 },
618 },
619 },
620 },
621 },
622 },
623 },
624 {
625 name: "debug by node preserve existing capability",
626 pod: &corev1.Pod{
627 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
628 Spec: corev1.PodSpec{
629 Containers: []corev1.Container{
630 {
631 Name: "dbg",
632 Image: "dbgimage",
633 SecurityContext: &corev1.SecurityContext{
634 Capabilities: &corev1.Capabilities{
635 Add: []corev1.Capability{"SYS_PTRACE"},
636 },
637 },
638 },
639 },
640 },
641 },
642 containerName: "dbg",
643 target: testNode,
644 expectPod: &corev1.Pod{
645 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
646 Spec: corev1.PodSpec{
647 HostNetwork: true,
648 HostPID: true,
649 HostIPC: true,
650 Containers: []corev1.Container{
651 {
652 Name: "dbg",
653 Image: "dbgimage",
654 SecurityContext: &corev1.SecurityContext{
655 Capabilities: &corev1.Capabilities{
656 Add: []corev1.Capability{"SYS_PTRACE", "NET_ADMIN", "NET_RAW"},
657 },
658 },
659 },
660 },
661 },
662 },
663 },
664 }
665
666 for _, test := range tests {
667 t.Run(test.name, func(t *testing.T) {
668 err := (&netadminProfile{}).Apply(test.pod, test.containerName, test.target)
669 if (err == nil) != (test.expectErr == nil) || (err != nil && test.expectErr != nil && err.Error() != test.expectErr.Error()) {
670 t.Fatalf("expect error: %v, got error: %v", test.expectErr, err)
671 }
672 if err != nil {
673 return
674 }
675 if diff := cmp.Diff(test.expectPod, test.pod); diff != "" {
676 t.Error("unexpected diff in generated object: (-want +got):\n", diff)
677 }
678 })
679 }
680 }
681
682 func TestSysAdminProfile(t *testing.T) {
683 pod := &corev1.Pod{
684 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
685 Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
686 {
687 EphemeralContainerCommon: corev1.EphemeralContainerCommon{
688 Name: "dbg", Image: "dbgimage",
689 },
690 },
691 }},
692 }
693
694 tests := []struct {
695 name string
696 pod *corev1.Pod
697 containerName string
698 target runtime.Object
699 expectPod *corev1.Pod
700 expectErr error
701 }{
702 {
703 name: "nil target",
704 pod: pod,
705 containerName: "dbg",
706 target: nil,
707 expectErr: fmt.Errorf("sysadmin profile: objects of type <nil> are not supported"),
708 },
709 {
710 name: "debug by ephemeral container",
711 pod: pod,
712 containerName: "dbg",
713 target: pod,
714 expectPod: &corev1.Pod{
715 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
716 Spec: corev1.PodSpec{EphemeralContainers: []corev1.EphemeralContainer{
717 {
718 EphemeralContainerCommon: corev1.EphemeralContainerCommon{
719 Name: "dbg", Image: "dbgimage",
720 SecurityContext: &corev1.SecurityContext{
721 Privileged: pointer.Bool(true),
722 },
723 },
724 },
725 }},
726 },
727 },
728 {
729 name: "debug by pod copy",
730 pod: &corev1.Pod{
731 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
732 Spec: corev1.PodSpec{
733 Containers: []corev1.Container{
734 {Name: "app", Image: "appimage"},
735 {Name: "dbg", Image: "dbgimage"},
736 },
737 },
738 },
739 containerName: "dbg",
740 target: &corev1.Pod{
741 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
742 Spec: corev1.PodSpec{
743 Containers: []corev1.Container{
744 {Name: "app", Image: "appimage"},
745 },
746 },
747 },
748 expectPod: &corev1.Pod{
749 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
750 Spec: corev1.PodSpec{
751 Containers: []corev1.Container{
752 {Name: "app", Image: "appimage"},
753 {
754 Name: "dbg",
755 Image: "dbgimage",
756 SecurityContext: &corev1.SecurityContext{
757 Privileged: pointer.Bool(true),
758 },
759 },
760 },
761 ShareProcessNamespace: pointer.Bool(true),
762 },
763 },
764 },
765 {
766 name: "debug by pod copy preserve existing capability",
767 pod: &corev1.Pod{
768 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
769 Spec: corev1.PodSpec{
770 Containers: []corev1.Container{
771 {Name: "app", Image: "appimage"},
772 {
773 Name: "dbg",
774 Image: "dbgimage",
775 SecurityContext: &corev1.SecurityContext{
776 Capabilities: &corev1.Capabilities{
777 Add: []corev1.Capability{"SYS_PTRACE"},
778 },
779 },
780 },
781 },
782 },
783 },
784 containerName: "dbg",
785 target: &corev1.Pod{
786 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
787 Spec: corev1.PodSpec{
788 Containers: []corev1.Container{
789 {Name: "app", Image: "appimage"},
790 },
791 },
792 },
793 expectPod: &corev1.Pod{
794 ObjectMeta: metav1.ObjectMeta{Name: "podcopy"},
795 Spec: corev1.PodSpec{
796 Containers: []corev1.Container{
797 {Name: "app", Image: "appimage"},
798 {
799 Name: "dbg",
800 Image: "dbgimage",
801 SecurityContext: &corev1.SecurityContext{
802 Privileged: pointer.Bool(true),
803 Capabilities: &corev1.Capabilities{
804 Add: []corev1.Capability{"SYS_PTRACE"},
805 },
806 },
807 },
808 },
809 ShareProcessNamespace: pointer.Bool(true),
810 },
811 },
812 },
813 {
814 name: "debug by node",
815 pod: &corev1.Pod{
816 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
817 Spec: corev1.PodSpec{
818 Containers: []corev1.Container{
819 {Name: "dbg", Image: "dbgimage"},
820 },
821 },
822 },
823 containerName: "dbg",
824 target: testNode,
825 expectPod: &corev1.Pod{
826 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
827 Spec: corev1.PodSpec{
828 HostNetwork: true,
829 HostPID: true,
830 HostIPC: true,
831 Volumes: []corev1.Volume{
832 {
833 Name: "host-root",
834 VolumeSource: corev1.VolumeSource{HostPath: &corev1.HostPathVolumeSource{Path: "/"}},
835 },
836 },
837 Containers: []corev1.Container{
838 {
839 Name: "dbg",
840 Image: "dbgimage",
841 SecurityContext: &corev1.SecurityContext{
842 Privileged: pointer.Bool(true),
843 },
844 VolumeMounts: []corev1.VolumeMount{{Name: "host-root", MountPath: "/host"}},
845 },
846 },
847 },
848 },
849 },
850 {
851 name: "debug by node preserve existing capability",
852 pod: &corev1.Pod{
853 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
854 Spec: corev1.PodSpec{
855 Containers: []corev1.Container{
856 {
857 Name: "dbg",
858 Image: "dbgimage",
859 SecurityContext: &corev1.SecurityContext{
860 Capabilities: &corev1.Capabilities{
861 Add: []corev1.Capability{"SYS_PTRACE"},
862 },
863 },
864 },
865 },
866 },
867 },
868 containerName: "dbg",
869 target: testNode,
870 expectPod: &corev1.Pod{
871 ObjectMeta: metav1.ObjectMeta{Name: "pod"},
872 Spec: corev1.PodSpec{
873 HostNetwork: true,
874 HostPID: true,
875 HostIPC: true,
876 Volumes: []corev1.Volume{
877 {
878 Name: "host-root",
879 VolumeSource: corev1.VolumeSource{HostPath: &corev1.HostPathVolumeSource{Path: "/"}},
880 },
881 },
882 Containers: []corev1.Container{
883 {
884 Name: "dbg",
885 Image: "dbgimage",
886 SecurityContext: &corev1.SecurityContext{
887 Privileged: pointer.Bool(true),
888 Capabilities: &corev1.Capabilities{
889 Add: []corev1.Capability{"SYS_PTRACE"},
890 },
891 },
892 VolumeMounts: []corev1.VolumeMount{{Name: "host-root", MountPath: "/host"}},
893 },
894 },
895 },
896 },
897 },
898 }
899
900 for _, test := range tests {
901 t.Run(test.name, func(t *testing.T) {
902 err := (&sysadminProfile{}).Apply(test.pod, test.containerName, test.target)
903 if (err == nil) != (test.expectErr == nil) || (err != nil && test.expectErr != nil && err.Error() != test.expectErr.Error()) {
904 t.Fatalf("expect error: %v, got error: %v", test.expectErr, err)
905 }
906 if err != nil {
907 return
908 }
909 if diff := cmp.Diff(test.expectPod, test.pod); diff != "" {
910 t.Error("unexpected diff in generated object: (-want +got):\n", diff)
911 }
912 })
913 }
914 }
915
View as plain text