diff --git a/staging/src/k8s.io/pod-security-admission/policy/check_sysctls.go b/staging/src/k8s.io/pod-security-admission/policy/check_sysctls.go index da1479373eb..63fb07e9173 100644 --- a/staging/src/k8s.io/pod-security-admission/policy/check_sysctls.go +++ b/staging/src/k8s.io/pod-security-admission/policy/check_sysctls.go @@ -25,6 +25,26 @@ import ( "k8s.io/pod-security-admission/api" ) +/* + +Sysctls can disable security mechanisms or affect all containers on a host, +and should be disallowed except for an allowed "safe" subset. + +A sysctl is considered safe if it is namespaced in the container or the Pod, +and it is isolated from other Pods or processes on the same Node. + +**Restricted Fields:** +spec.securityContext.sysctls[*].name + +**Allowed Values:** +'kernel.shm_rmid_forced' +'net.ipv4.ip_local_port_range' +'net.ipv4.tcp_syncookies' +'net.ipv4.ping_group_range' +'net.ipv4.ip_unprivileged_port_start' + +*/ + func init() { addCheck(CheckSysctls) } @@ -38,7 +58,7 @@ func CheckSysctls() Check { Versions: []VersionedCheck{ { MinimumVersion: api.MajorMinorVersion(1, 0), - CheckPod: checkSysctls_1_0, + CheckPod: sysctls_1_0, }, }, } @@ -54,7 +74,7 @@ var ( ) ) -func checkSysctls_1_0(podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSpec) CheckResult { +func sysctls_1_0(podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSpec) CheckResult { var forbiddenSysctls []string if podSpec.SecurityContext != nil { diff --git a/staging/src/k8s.io/pod-security-admission/policy/check_sysctls_test.go b/staging/src/k8s.io/pod-security-admission/policy/check_sysctls_test.go new file mode 100644 index 00000000000..450b383146e --- /dev/null +++ b/staging/src/k8s.io/pod-security-admission/policy/check_sysctls_test.go @@ -0,0 +1,58 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package policy + +import ( + "testing" + + corev1 "k8s.io/api/core/v1" +) + +func TestSysctls(t *testing.T) { + tests := []struct { + name string + pod *corev1.Pod + expectReason string + expectDetail string + }{ + { + name: "forbidden sysctls", + pod: &corev1.Pod{Spec: corev1.PodSpec{ + SecurityContext: &corev1.PodSecurityContext{ + Sysctls: []corev1.Sysctl{{Name: "a"}, {Name: "b"}}, + }, + }}, + expectReason: `forbidden sysctls`, + expectDetail: `a, b`, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + result := sysctls_1_0(&tc.pod.ObjectMeta, &tc.pod.Spec) + if result.Allowed { + t.Fatal("expected disallowed") + } + if e, a := tc.expectReason, result.ForbiddenReason; e != a { + t.Errorf("expected\n%s\ngot\n%s", e, a) + } + if e, a := tc.expectDetail, result.ForbiddenDetail; e != a { + t.Errorf("expected\n%s\ngot\n%s", e, a) + } + }) + } +}