Update dropCapabilities check/fixtures

This commit is contained in:
Jordan Liggitt 2021-07-07 10:34:45 -04:00
parent a8793dcb3e
commit 08608a24f1
4 changed files with 61 additions and 46 deletions

View File

@ -29,7 +29,7 @@ import (
const ( const (
capabilityAll = "ALL" capabilityAll = "ALL"
capabilityNetBindService = "CAP_NET_BIND_SERVICE" capabilityNetBindService = "NET_BIND_SERVICE"
) )
func init() { func init() {
@ -52,12 +52,18 @@ func CheckDropCapabilities() Check {
} }
func dropCapabilities_1_22(podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSpec) CheckResult { func dropCapabilities_1_22(podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSpec) CheckResult {
containers := sets.NewString() var (
containersMissingDropAll []string
containersAddingForbidden []string
forbiddenCapabilities = sets.NewString()
)
visitContainersWithPath(podSpec, field.NewPath("spec"), func(container *corev1.Container, path *field.Path) { visitContainersWithPath(podSpec, field.NewPath("spec"), func(container *corev1.Container, path *field.Path) {
if container.SecurityContext == nil || container.SecurityContext.Capabilities == nil { if container.SecurityContext == nil || container.SecurityContext.Capabilities == nil {
containers.Insert(container.Name) containersMissingDropAll = append(containersMissingDropAll, container.Name)
return return
} }
found := false found := false
for _, c := range container.SecurityContext.Capabilities.Drop { for _, c := range container.SecurityContext.Capabilities.Drop {
if c == capabilityAll { if c == capabilityAll {
@ -66,23 +72,29 @@ func dropCapabilities_1_22(podMetadata *metav1.ObjectMeta, podSpec *corev1.PodSp
} }
} }
if !found { if !found {
containers.Insert(container.Name) containersMissingDropAll = append(containersMissingDropAll, container.Name)
return
} }
for index, c := range container.SecurityContext.Capabilities.Add {
for _, c := range container.SecurityContext.Capabilities.Add {
if c != capabilityNetBindService { if c != capabilityNetBindService {
capabilityPath := path.Child("securityContext", "capabilities", "add").Index(index) containersAddingForbidden = append(containersAddingForbidden, container.Name)
msg := fmt.Sprintf("%s=%s", capabilityPath.String(), string(c)) forbiddenCapabilities.Insert(string(c))
containers.Insert(msg)
} }
} }
}) })
if len(containers) > 0 { var forbiddenDetails []string
if len(containersMissingDropAll) > 0 {
forbiddenDetails = append(forbiddenDetails, fmt.Sprintf("containers %q must drop ALL", containersMissingDropAll))
}
if len(containersAddingForbidden) > 0 {
forbiddenDetails = append(forbiddenDetails, fmt.Sprintf("containers %q must not add %q", containersAddingForbidden, forbiddenCapabilities.List()))
}
if len(forbiddenDetails) > 0 {
return CheckResult{ return CheckResult{
Allowed: false, Allowed: false,
ForbiddenReason: "containers must drop ALL capability", ForbiddenReason: "containers must restrict capabilities",
ForbiddenDetail: strings.Join(containers.List(), ", "), ForbiddenDetail: strings.Join(forbiddenDetails, "; "),
} }
} }
return CheckResult{Allowed: true} return CheckResult{Allowed: true}

View File

@ -66,6 +66,13 @@ func init() {
} }
}) })
minimalValidPods[api.LevelRestricted][api.MajorMinorVersion(1, 19)] = restricted_1_19 minimalValidPods[api.LevelRestricted][api.MajorMinorVersion(1, 19)] = restricted_1_19
// 1.22+: capabilities.drop=["ALL"]
restricted_1_22 := tweak(restricted_1_19, func(p *corev1.Pod) {
p.Spec.Containers[0].SecurityContext.Capabilities = &corev1.Capabilities{Drop: []corev1.Capability{"ALL"}}
p.Spec.InitContainers[0].SecurityContext.Capabilities = &corev1.Capabilities{Drop: []corev1.Capability{"ALL"}}
})
minimalValidPods[api.LevelRestricted][api.MajorMinorVersion(1, 22)] = restricted_1_22
} }
// getValidPod returns a minimal valid pod for the specified level and version. // getValidPod returns a minimal valid pod for the specified level and version.

View File

@ -50,9 +50,11 @@ func init() {
expectErrorSubstring: "forbidden capabilities", expectErrorSubstring: "forbidden capabilities",
generatePass: func(p *corev1.Pod) []*corev1.Pod { generatePass: func(p *corev1.Pod) []*corev1.Pod {
// don't generate fixtures if minimal valid pod drops ALL // don't generate fixtures if minimal valid pod drops ALL
for _, capability := range p.Spec.Containers[0].SecurityContext.Capabilities.Drop { if p.Spec.Containers[0].SecurityContext != nil && p.Spec.Containers[0].SecurityContext.Capabilities != nil {
if capability == corev1.Capability("ALL") { for _, capability := range p.Spec.Containers[0].SecurityContext.Capabilities.Drop {
return nil if capability == corev1.Capability("ALL") {
return nil
}
} }
} }

View File

@ -1,9 +1,12 @@
/* /*
Copyright 2021 The Kubernetes Authors. Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -27,8 +30,9 @@ containerFields: []string{
func init() { func init() {
fixtureData_1_22 := fixtureGenerator{ fixtureData_1_22 := fixtureGenerator{
expectErrorSubstring: "drop all", expectErrorSubstring: "restrict capabilities",
generatePass: func(p *corev1.Pod) []*corev1.Pod { generatePass: func(p *corev1.Pod) []*corev1.Pod {
p = ensureCapabilities(p)
return []*corev1.Pod{ return []*corev1.Pod{
tweak(p, func(p *corev1.Pod) { tweak(p, func(p *corev1.Pod) {
p.Spec.Containers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{"ALL"} p.Spec.Containers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{"ALL"}
@ -37,8 +41,8 @@ func init() {
tweak(p, func(p *corev1.Pod) { tweak(p, func(p *corev1.Pod) {
p.Spec.Containers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{"ALL"} p.Spec.Containers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{"ALL"}
p.Spec.InitContainers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{"ALL"} p.Spec.InitContainers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{"ALL"}
p.Spec.Containers[0].SecurityContext.Capabilities.Add = []corev1.Capability{"CAP_NET_BIND_SERVICE"} p.Spec.Containers[0].SecurityContext.Capabilities.Add = []corev1.Capability{"NET_BIND_SERVICE"}
p.Spec.InitContainers[0].SecurityContext.Capabilities.Add = []corev1.Capability{"CAP_NET_BIND_SERVICE"} p.Spec.InitContainers[0].SecurityContext.Capabilities.Add = []corev1.Capability{"NET_BIND_SERVICE"}
}), }),
} }
}, },
@ -51,44 +55,34 @@ func init() {
}), }),
tweak(p, func(p *corev1.Pod) { tweak(p, func(p *corev1.Pod) {
p.Spec.Containers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{ p.Spec.Containers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{
"CAP_SYS_TIME", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_NICE", "SYS_TIME", "SYS_MODULE", "SYS_RAWIO", "SYS_PACCT", "SYS_ADMIN", "SYS_NICE",
"CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_AUDIT_WRITE", "SYS_RESOURCE", "SYS_TIME", "SYS_TTY_CONFIG", "MKNOD", "AUDIT_WRITE",
"CAP_AUDIT_CONTROL", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_NET_ADMIN", "CAP_SYSLOG", "AUDIT_CONTROL", "MAC_OVERRIDE", "MAC_ADMIN", "NET_ADMIN", "SYSLOG",
"CAP_CHOWN", "CAP_NET_RAW", "CAP_DAC_OVERRIDE", "CAP_FOWNER", "CAP_DAC_READ_SEARCH", "CHOWN", "NET_RAW", "DAC_OVERRIDE", "FOWNER", "DAC_READ_SEARCH",
"CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_LINUX_IMMUTABLE", "CAP_NET_BIND_SERVICE", "FSETID", "KILL", "SETGID", "SETUID", "LINUX_IMMUTABLE", "NET_BIND_SERVICE",
"CAP_NET_BROADCAST", "CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "NET_BROADCAST", "IPC_LOCK", "IPC_OWNER", "SYS_CHROOT", "SYS_PTRACE",
"CAP_SYS_BOOT", "CAP_LEASE", "CAP_SETFCAP", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND", "SYS_BOOT", "LEASE", "SETFCAP", "WAKE_ALARM", "BLOCK_SUSPEND",
} }
p.Spec.InitContainers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{ p.Spec.InitContainers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{
"CAP_SYS_TIME", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_NICE", "SYS_TIME", "SYS_MODULE", "SYS_RAWIO", "SYS_PACCT", "SYS_ADMIN", "SYS_NICE",
"CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_AUDIT_WRITE", "SYS_RESOURCE", "SYS_TIME", "SYS_TTY_CONFIG", "MKNOD", "AUDIT_WRITE",
"CAP_AUDIT_CONTROL", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_NET_ADMIN", "CAP_SYSLOG", "AUDIT_CONTROL", "MAC_OVERRIDE", "MAC_ADMIN", "NET_ADMIN", "SYSLOG",
"CAP_CHOWN", "CAP_NET_RAW", "CAP_DAC_OVERRIDE", "CAP_FOWNER", "CAP_DAC_READ_SEARCH", "CHOWN", "NET_RAW", "DAC_OVERRIDE", "FOWNER", "DAC_READ_SEARCH",
"CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_LINUX_IMMUTABLE", "CAP_NET_BIND_SERVICE", "FSETID", "KILL", "SETGID", "SETUID", "LINUX_IMMUTABLE", "NET_BIND_SERVICE",
"CAP_NET_BROADCAST", "CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "NET_BROADCAST", "IPC_LOCK", "IPC_OWNER", "SYS_CHROOT", "SYS_PTRACE",
"CAP_SYS_BOOT", "CAP_LEASE", "CAP_SETFCAP", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND", "SYS_BOOT", "LEASE", "SETFCAP", "WAKE_ALARM", "BLOCK_SUSPEND",
} }
}), }),
tweak(p, func(p *corev1.Pod) { tweak(p, func(p *corev1.Pod) {
p.Spec.Containers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{"ALL"} p.Spec.Containers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{"ALL"}
p.Spec.InitContainers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{"ALL"} p.Spec.InitContainers[0].SecurityContext.Capabilities.Drop = []corev1.Capability{"ALL"}
p.Spec.Containers[0].SecurityContext.Capabilities.Add = []corev1.Capability{ p.Spec.Containers[0].SecurityContext.Capabilities.Add = []corev1.Capability{
"CAP_SYS_TIME", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_NICE", // try adding back capabilities other than NET_BIND_SERVICE, should be forbidden
"CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_AUDIT_WRITE", "AUDIT_WRITE", "CHOWN", "DAC_OVERRIDE", "FOWNER", "FSETID", "KILL", "MKNOD", "NET_BIND_SERVICE", "SETFCAP", "SETGID", "SETPCAP", "SETUID", "SYS_CHROOT",
"CAP_AUDIT_CONTROL", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_NET_ADMIN", "CAP_SYSLOG",
"CAP_CHOWN", "CAP_NET_RAW", "CAP_DAC_OVERRIDE", "CAP_FOWNER", "CAP_DAC_READ_SEARCH",
"CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_LINUX_IMMUTABLE", "CAP_NET_BROADCAST",
"CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "CAP_SYS_BOOT", "CAP_LEASE",
"CAP_SETFCAP", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND",
} }
p.Spec.InitContainers[0].SecurityContext.Capabilities.Add = []corev1.Capability{ p.Spec.InitContainers[0].SecurityContext.Capabilities.Add = []corev1.Capability{
"CAP_SYS_TIME", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_NICE", // try adding back capabilities other than NET_BIND_SERVICE, should be forbidden
"CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_AUDIT_WRITE", "AUDIT_WRITE", "CHOWN", "DAC_OVERRIDE", "FOWNER", "FSETID", "KILL", "MKNOD", "NET_BIND_SERVICE", "SETFCAP", "SETGID", "SETPCAP", "SETUID", "SYS_CHROOT",
"CAP_AUDIT_CONTROL", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_NET_ADMIN", "CAP_SYSLOG",
"CAP_CHOWN", "CAP_NET_RAW", "CAP_DAC_OVERRIDE", "CAP_FOWNER", "CAP_DAC_READ_SEARCH",
"CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_LINUX_IMMUTABLE", "CAP_NET_BROADCAST",
"CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "CAP_SYS_BOOT", "CAP_LEASE",
"CAP_SETFCAP", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND",
} }
}), }),
} }