1
2
3
4
19
20 package sysctl
21
22 import (
23 "testing"
24
25 v1 "k8s.io/api/core/v1"
26 "k8s.io/kubernetes/pkg/kubelet/lifecycle"
27 )
28
29 func TestNewAllowlist(t *testing.T) {
30 type Test struct {
31 sysctls []string
32 err bool
33 }
34 for _, test := range []Test{
35 {sysctls: []string{"kernel.msg*", "kernel.sem"}},
36 {sysctls: []string{"kernel/msg*", "kernel/sem"}},
37 {sysctls: []string{" kernel.msg*"}, err: true},
38 {sysctls: []string{"kernel.msg* "}, err: true},
39 {sysctls: []string{"net.-"}, err: true},
40 {sysctls: []string{"net.*.foo"}, err: true},
41 {sysctls: []string{"net.*/foo"}, err: true},
42 {sysctls: []string{"foo"}, err: true},
43 {sysctls: []string{"foo*"}, err: true},
44 } {
45 _, err := NewAllowlist(append(SafeSysctlAllowlist(), test.sysctls...))
46 if test.err && err == nil {
47 t.Errorf("expected an error creating a allowlist for %v", test.sysctls)
48 } else if !test.err && err != nil {
49 t.Errorf("got unexpected error creating a allowlist for %v: %v", test.sysctls, err)
50 }
51 }
52 }
53
54 func TestAllowlist(t *testing.T) {
55 type Test struct {
56 sysctl string
57 hostNet, hostIPC bool
58 }
59 valid := []Test{
60 {sysctl: "kernel.shm_rmid_forced"},
61 {sysctl: "kernel/shm_rmid_forced"},
62 {sysctl: "net.ipv4.ip_local_port_range"},
63 {sysctl: "kernel.msgmax"},
64 {sysctl: "kernel.sem"},
65 {sysctl: "kernel/sem"},
66 }
67 invalid := []Test{
68 {sysctl: "kernel.shm_rmid_forced", hostIPC: true},
69 {sysctl: "net.ipv4.ip_local_port_range", hostNet: true},
70 {sysctl: "foo"},
71 {sysctl: "net.a.b.c", hostNet: false},
72 {sysctl: "net.ipv4.ip_local_port_range.a.b.c", hostNet: false},
73 {sysctl: "kernel.msgmax", hostIPC: true},
74 {sysctl: "kernel.sem", hostIPC: true},
75 {sysctl: "net.b.c", hostNet: true},
76 }
77 pod := &v1.Pod{}
78 pod.Spec.SecurityContext = &v1.PodSecurityContext{}
79 attrs := &lifecycle.PodAdmitAttributes{Pod: pod}
80
81 w, err := NewAllowlist(append(SafeSysctlAllowlist(), "kernel.msg*", "kernel.sem", "net.b.*"))
82 if err != nil {
83 t.Fatalf("failed to create allowlist: %v", err)
84 }
85
86 for _, test := range valid {
87 if err := w.validateSysctl(test.sysctl, test.hostNet, test.hostIPC); err != nil {
88 t.Errorf("expected to be allowlisted: %+v, got: %v", test, err)
89 }
90 pod.Spec.SecurityContext.Sysctls = []v1.Sysctl{{Name: test.sysctl, Value: test.sysctl}}
91 status := w.Admit(attrs)
92 if !status.Admit {
93 t.Errorf("expected to be allowlisted: %+v, got: %+v", test, status)
94 }
95 }
96
97 for _, test := range invalid {
98 if err := w.validateSysctl(test.sysctl, test.hostNet, test.hostIPC); err == nil {
99 t.Errorf("expected to be rejected: %+v", test)
100 }
101 pod.Spec.HostNetwork = test.hostNet
102 pod.Spec.HostIPC = test.hostIPC
103 pod.Spec.SecurityContext.Sysctls = []v1.Sysctl{{Name: test.sysctl, Value: test.sysctl}}
104 status := w.Admit(attrs)
105 if status.Admit {
106 t.Errorf("expected to be rejected: %+v", test)
107 }
108 }
109
110
111 pod.Spec.SecurityContext.Sysctls = []v1.Sysctl{}
112 status := w.Admit(attrs)
113 if !status.Admit {
114 t.Errorf("expected to be allowlisted,got %+v", status)
115 }
116 }
117
View as plain text