Merge pull request #109819 from saschagrunert/seccomp-annotation

Partly remove support for seccomp annotations
This commit is contained in:
Kubernetes Prow Robot 2022-08-01 07:50:28 -07:00 committed by GitHub
commit 37b100bea6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 53 additions and 425 deletions

View File

@ -777,36 +777,6 @@ func SeccompAnnotationForField(field *api.SeccompProfile) string {
return ""
}
// SeccompFieldForAnnotation takes a pod annotation and returns the converted
// seccomp profile field.
func SeccompFieldForAnnotation(annotation string) *api.SeccompProfile {
// If only seccomp annotations are specified, copy the values into the
// corresponding fields. This ensures that existing applications continue
// to enforce seccomp, and prevents the kubelet from needing to resolve
// annotations & fields.
if annotation == v1.SeccompProfileNameUnconfined {
return &api.SeccompProfile{Type: api.SeccompProfileTypeUnconfined}
}
if annotation == api.SeccompProfileRuntimeDefault || annotation == api.DeprecatedSeccompProfileDockerDefault {
return &api.SeccompProfile{Type: api.SeccompProfileTypeRuntimeDefault}
}
if strings.HasPrefix(annotation, v1.SeccompLocalhostProfileNamePrefix) {
localhostProfile := strings.TrimPrefix(annotation, v1.SeccompLocalhostProfileNamePrefix)
if localhostProfile != "" {
return &api.SeccompProfile{
Type: api.SeccompProfileTypeLocalhost,
LocalhostProfile: &localhostProfile,
}
}
}
// we can only reach this code path if the localhostProfile name has a zero
// length or if the annotation has an unrecognized value
return nil
}
// setsWindowsHostProcess returns true if WindowsOptions.HostProcess is set (true or false)
// anywhere in the pod spec.
func setsWindowsHostProcess(podSpec *api.PodSpec) bool {

View File

@ -240,7 +240,7 @@ func warningsForPodSpecAndMeta(fieldPath *field.Path, podSpec *api.PodSpec, meta
// use of pod seccomp annotation without accompanying field
if podSpec.SecurityContext == nil || podSpec.SecurityContext.SeccompProfile == nil {
if _, exists := meta.Annotations[api.SeccompPodAnnotationKey]; exists {
warnings = append(warnings, fmt.Sprintf(`%s: deprecated since v1.19, non-functional in v1.25+; use the "seccompProfile" field instead`, fieldPath.Child("metadata", "annotations").Key(api.SeccompPodAnnotationKey)))
warnings = append(warnings, fmt.Sprintf(`%s: deprecated since v1.19, non-functional in a future release; use the "seccompProfile" field instead`, fieldPath.Child("metadata", "annotations").Key(api.SeccompPodAnnotationKey)))
}
}
@ -248,7 +248,7 @@ func warningsForPodSpecAndMeta(fieldPath *field.Path, podSpec *api.PodSpec, meta
// use of container seccomp annotation without accompanying field
if c.SecurityContext == nil || c.SecurityContext.SeccompProfile == nil {
if _, exists := meta.Annotations[api.SeccompContainerAnnotationKeyPrefix+c.Name]; exists {
warnings = append(warnings, fmt.Sprintf(`%s: deprecated since v1.19, non-functional in v1.25+; use the "seccompProfile" field instead`, fieldPath.Child("metadata", "annotations").Key(api.SeccompContainerAnnotationKeyPrefix+c.Name)))
warnings = append(warnings, fmt.Sprintf(`%s: deprecated since v1.19, non-functional in a future release; use the "seccompProfile" field instead`, fieldPath.Child("metadata", "annotations").Key(api.SeccompContainerAnnotationKeyPrefix+c.Name)))
}
}

View File

@ -432,8 +432,8 @@ func TestWarnings(t *testing.T) {
},
expected: []string{
`metadata.annotations[scheduler.alpha.kubernetes.io/critical-pod]: non-functional in v1.16+; use the "priorityClassName" field instead`,
`metadata.annotations[seccomp.security.alpha.kubernetes.io/pod]: deprecated since v1.19, non-functional in v1.25+; use the "seccompProfile" field instead`,
`metadata.annotations[container.seccomp.security.alpha.kubernetes.io/foo]: deprecated since v1.19, non-functional in v1.25+; use the "seccompProfile" field instead`,
`metadata.annotations[seccomp.security.alpha.kubernetes.io/pod]: deprecated since v1.19, non-functional in a future release; use the "seccompProfile" field instead`,
`metadata.annotations[container.seccomp.security.alpha.kubernetes.io/foo]: deprecated since v1.19, non-functional in a future release; use the "seccompProfile" field instead`,
`metadata.annotations[security.alpha.kubernetes.io/sysctls]: non-functional in v1.11+; use the "sysctls" field instead`,
`metadata.annotations[security.alpha.kubernetes.io/unsafe-sysctls]: non-functional in v1.11+; use the "sysctls" field instead`,
},

View File

@ -4218,7 +4218,7 @@ func ValidatePodCreate(pod *core.Pod, opts PodValidationOptions) field.ErrorList
return allErrs
}
// ValidateSeccompAnnotationsAndFields iterates through all containers and ensure that when both seccompProfile and seccomp annotations exist they match.
// validateSeccompAnnotationsAndFields iterates through all containers and ensure that when both seccompProfile and seccomp annotations exist they match.
func validateSeccompAnnotationsAndFields(objectMeta metav1.ObjectMeta, podSpec *core.PodSpec, specPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}

View File

@ -234,15 +234,6 @@ func fieldProfile(scmp *v1.SeccompProfile, profileRootPath string, fallbackToRun
return ""
}
func annotationProfile(profile, profileRootPath string) string {
if strings.HasPrefix(profile, v1.SeccompLocalhostProfileNamePrefix) {
name := strings.TrimPrefix(profile, v1.SeccompLocalhostProfileNamePrefix)
fname := filepath.Join(profileRootPath, filepath.FromSlash(name))
return v1.SeccompLocalhostProfileNamePrefix + fname
}
return profile
}
func (m *kubeGenericRuntimeManager) getSeccompProfilePath(annotations map[string]string, containerName string,
podSecContext *v1.PodSecurityContext, containerSecContext *v1.SecurityContext, fallbackToRuntimeDefault bool) string {
// container fields are applied first
@ -250,23 +241,11 @@ func (m *kubeGenericRuntimeManager) getSeccompProfilePath(annotations map[string
return fieldProfile(containerSecContext.SeccompProfile, m.seccompProfileRoot, fallbackToRuntimeDefault)
}
// if container field does not exist, try container annotation (deprecated)
if containerName != "" {
if profile, ok := annotations[v1.SeccompContainerAnnotationKeyPrefix+containerName]; ok {
return annotationProfile(profile, m.seccompProfileRoot)
}
}
// when container seccomp is not defined, try to apply from pod field
if podSecContext != nil && podSecContext.SeccompProfile != nil {
return fieldProfile(podSecContext.SeccompProfile, m.seccompProfileRoot, fallbackToRuntimeDefault)
}
// as last resort, try to apply pod annotation (deprecated)
if profile, ok := annotations[v1.SeccompPodAnnotationKey]; ok {
return annotationProfile(profile, m.seccompProfileRoot)
}
if fallbackToRuntimeDefault {
return v1.SeccompProfileRuntimeDefault
}

View File

@ -369,91 +369,6 @@ func TestGetSeccompProfilePath(t *testing.T) {
containerName: "container1",
expectedProfile: "",
},
{
description: "annotations: pod runtime/default seccomp profile should return runtime/default",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault,
},
expectedProfile: "runtime/default",
},
{
description: "annotations: pod docker/default seccomp profile should return docker/default",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.DeprecatedSeccompProfileDockerDefault,
},
expectedProfile: "docker/default",
},
{
description: "annotations: pod runtime/default seccomp profile with containerName should return runtime/default",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault,
},
containerName: "container1",
expectedProfile: "runtime/default",
},
{
description: "annotations: pod docker/default seccomp profile with containerName should return docker/default",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.DeprecatedSeccompProfileDockerDefault,
},
containerName: "container1",
expectedProfile: "docker/default",
},
{
description: "annotations: pod unconfined seccomp profile should return unconfined",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined,
},
expectedProfile: "unconfined",
},
{
description: "annotations: pod unconfined seccomp profile with containerName should return unconfined",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined,
},
containerName: "container1",
expectedProfile: "unconfined",
},
{
description: "annotations: pod localhost seccomp profile should return local profile path",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/chmod.json",
},
expectedProfile: seccompLocalhostPath("chmod.json"),
},
{
description: "annotations: pod localhost seccomp profile with containerName should return local profile path",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/chmod.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("chmod.json"),
},
{
description: "annotations: container localhost seccomp profile with containerName should return local profile path",
annotation: map[string]string{
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("chmod.json"),
},
{
description: "annotations: container localhost seccomp profile should override pod profile",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined,
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("chmod.json"),
},
{
description: "annotations: container localhost seccomp profile with unmatched containerName should return empty",
annotation: map[string]string{
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json",
},
containerName: "container2",
expectedProfile: "",
},
{
description: "pod seccomp profile set to unconfined returns unconfined",
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeUnconfined}},
@ -500,36 +415,6 @@ func TestGetSeccompProfilePath(t *testing.T) {
containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault}},
expectedProfile: "runtime/default",
},
{
description: "prioritise container field over container annotation, pod field and pod annotation",
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}},
containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-cont-profile.json")}},
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json",
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/annota-cont-profile.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("field-cont-profile.json"),
},
{
description: "prioritise container annotation over pod field",
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}},
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json",
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/annota-cont-profile.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("annota-cont-profile.json"),
},
{
description: "prioritise pod field over pod annotation",
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}},
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("field-pod-profile.json"),
},
}
for i, test := range tests {
@ -559,91 +444,6 @@ func TestGetSeccompProfilePathDefaultSeccomp(t *testing.T) {
containerName: "container1",
expectedProfile: v1.SeccompProfileRuntimeDefault,
},
{
description: "annotations: pod runtime/default seccomp profile should return runtime/default",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault,
},
expectedProfile: v1.SeccompProfileRuntimeDefault,
},
{
description: "annotations: pod docker/default seccomp profile should return docker/default",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.DeprecatedSeccompProfileDockerDefault,
},
expectedProfile: "docker/default",
},
{
description: "annotations: pod runtime/default seccomp profile with containerName should return runtime/default",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault,
},
containerName: "container1",
expectedProfile: v1.SeccompProfileRuntimeDefault,
},
{
description: "annotations: pod docker/default seccomp profile with containerName should return docker/default",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.DeprecatedSeccompProfileDockerDefault,
},
containerName: "container1",
expectedProfile: "docker/default",
},
{
description: "annotations: pod unconfined seccomp profile should return unconfined",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined,
},
expectedProfile: "unconfined",
},
{
description: "annotations: pod unconfined seccomp profile with containerName should return unconfined",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined,
},
containerName: "container1",
expectedProfile: "unconfined",
},
{
description: "annotations: pod localhost seccomp profile should return local profile path",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/chmod.json",
},
expectedProfile: seccompLocalhostPath("chmod.json"),
},
{
description: "annotations: pod localhost seccomp profile with containerName should return local profile path",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/chmod.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("chmod.json"),
},
{
description: "annotations: container localhost seccomp profile with containerName should return local profile path",
annotation: map[string]string{
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("chmod.json"),
},
{
description: "annotations: container localhost seccomp profile should override pod profile",
annotation: map[string]string{
v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined,
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("chmod.json"),
},
{
description: "annotations: container localhost seccomp profile with unmatched containerName should return runtime/default",
annotation: map[string]string{
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json",
},
containerName: "container2",
expectedProfile: v1.SeccompProfileRuntimeDefault,
},
{
description: "pod seccomp profile set to unconfined returns unconfined",
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeUnconfined}},
@ -690,36 +490,6 @@ func TestGetSeccompProfilePathDefaultSeccomp(t *testing.T) {
containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault}},
expectedProfile: "runtime/default",
},
{
description: "prioritise container field over container annotation, pod field and pod annotation",
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}},
containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-cont-profile.json")}},
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json",
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/annota-cont-profile.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("field-cont-profile.json"),
},
{
description: "prioritise container annotation over pod field",
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}},
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json",
v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/annota-cont-profile.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("annota-cont-profile.json"),
},
{
description: "prioritise pod field over pod annotation",
podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}},
annotation: map[string]string{
v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json",
},
containerName: "container1",
expectedProfile: seccompLocalhostPath("field-pod-profile.json"),
},
}
for i, test := range tests {

View File

@ -158,12 +158,6 @@ func newTestPod() *v1.Pod {
func newSeccompPod(podFieldProfile, containerFieldProfile *v1.SeccompProfile, podAnnotationProfile, containerAnnotationProfile string) *v1.Pod {
pod := newTestPod()
if podAnnotationProfile != "" {
pod.Annotations = map[string]string{v1.SeccompPodAnnotationKey: podAnnotationProfile}
}
if containerAnnotationProfile != "" {
pod.Annotations = map[string]string{v1.SeccompContainerAnnotationKeyPrefix + "": containerAnnotationProfile}
}
if podFieldProfile != nil {
pod.Spec.SecurityContext = &v1.PodSecurityContext{
SeccompProfile: podFieldProfile,

View File

@ -644,28 +644,20 @@ func validateContainer(container string, pod *api.Pod) (string, error) {
// applySeccompVersionSkew implements the version skew behavior described in:
// https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/135-seccomp#version-skew-strategy
// Note that we dropped copying the field to annotation synchronization in
// v1.25 with the functional removal of the annotations.
func applySeccompVersionSkew(pod *api.Pod) {
// get possible annotation and field
annotation, hasAnnotation := pod.Annotations[v1.SeccompPodAnnotationKey]
field, hasField := (*api.SeccompProfile)(nil), false
hasField := false
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SeccompProfile != nil {
field = pod.Spec.SecurityContext.SeccompProfile
hasField = true
}
// sync field and annotation
if hasField && !hasAnnotation {
newAnnotation := podutil.SeccompAnnotationForField(field)
if newAnnotation != "" {
if pod.Annotations == nil {
pod.Annotations = map[string]string{}
}
pod.Annotations[v1.SeccompPodAnnotationKey] = newAnnotation
}
} else if hasAnnotation && !hasField {
newField := podutil.SeccompFieldForAnnotation(annotation)
if hasAnnotation && !hasField {
newField := seccompFieldForAnnotation(annotation)
if newField != nil {
if pod.Spec.SecurityContext == nil {
@ -682,24 +674,14 @@ func applySeccompVersionSkew(pod *api.Pod) {
key := api.SeccompContainerAnnotationKeyPrefix + ctr.Name
annotation, hasAnnotation := pod.Annotations[key]
field, hasField := (*api.SeccompProfile)(nil), false
hasField := false
if ctr.SecurityContext != nil && ctr.SecurityContext.SeccompProfile != nil {
field = ctr.SecurityContext.SeccompProfile
hasField = true
}
// sync field and annotation
if hasField && !hasAnnotation {
newAnnotation := podutil.SeccompAnnotationForField(field)
if newAnnotation != "" {
if pod.Annotations == nil {
pod.Annotations = map[string]string{}
}
pod.Annotations[key] = newAnnotation
}
} else if hasAnnotation && !hasField {
newField := podutil.SeccompFieldForAnnotation(annotation)
if hasAnnotation && !hasField {
newField := seccompFieldForAnnotation(annotation)
if newField != nil {
if ctr.SecurityContext == nil {
@ -712,3 +694,33 @@ func applySeccompVersionSkew(pod *api.Pod) {
return true
})
}
// seccompFieldForAnnotation takes a pod annotation and returns the converted
// seccomp profile field.
func seccompFieldForAnnotation(annotation string) *api.SeccompProfile {
// If only seccomp annotations are specified, copy the values into the
// corresponding fields. This ensures that existing applications continue
// to enforce seccomp, and prevents the kubelet from needing to resolve
// annotations & fields.
if annotation == v1.SeccompProfileNameUnconfined {
return &api.SeccompProfile{Type: api.SeccompProfileTypeUnconfined}
}
if annotation == api.SeccompProfileRuntimeDefault || annotation == api.DeprecatedSeccompProfileDockerDefault {
return &api.SeccompProfile{Type: api.SeccompProfileTypeRuntimeDefault}
}
if strings.HasPrefix(annotation, v1.SeccompLocalhostProfileNamePrefix) {
localhostProfile := strings.TrimPrefix(annotation, v1.SeccompLocalhostProfileNamePrefix)
if localhostProfile != "" {
return &api.SeccompProfile{
Type: api.SeccompProfileTypeLocalhost,
LocalhostProfile: &localhostProfile,
}
}
}
// we can only reach this code path if the localhostProfile name has a zero
// length or if the annotation has an unrecognized value
return nil
}

View File

@ -749,7 +749,7 @@ func TestApplySeccompVersionSkew(t *testing.T) {
},
},
{
description: "Field type unconfined and no annotation present",
description: "Field set and no annotation present",
pod: &api.Pod{
Spec: api.PodSpec{
SecurityContext: &api.PodSecurityContext{
@ -759,55 +759,6 @@ func TestApplySeccompVersionSkew(t *testing.T) {
},
},
},
validation: func(t *testing.T, pod *api.Pod) {
require.Len(t, pod.Annotations, 1)
require.Equal(t, v1.SeccompProfileNameUnconfined, pod.Annotations[api.SeccompPodAnnotationKey])
},
},
{
description: "Field type default and no annotation present",
pod: &api.Pod{
Spec: api.PodSpec{
SecurityContext: &api.PodSecurityContext{
SeccompProfile: &api.SeccompProfile{
Type: api.SeccompProfileTypeRuntimeDefault,
},
},
},
},
validation: func(t *testing.T, pod *api.Pod) {
require.Len(t, pod.Annotations, 1)
require.Equal(t, v1.SeccompProfileRuntimeDefault, pod.Annotations[v1.SeccompPodAnnotationKey])
},
},
{
description: "Field type localhost and no annotation present",
pod: &api.Pod{
Spec: api.PodSpec{
SecurityContext: &api.PodSecurityContext{
SeccompProfile: &api.SeccompProfile{
Type: api.SeccompProfileTypeLocalhost,
LocalhostProfile: &testProfile,
},
},
},
},
validation: func(t *testing.T, pod *api.Pod) {
require.Len(t, pod.Annotations, 1)
require.Equal(t, "localhost/test", pod.Annotations[v1.SeccompPodAnnotationKey])
},
},
{
description: "Field type localhost but profile is nil",
pod: &api.Pod{
Spec: api.PodSpec{
SecurityContext: &api.PodSecurityContext{
SeccompProfile: &api.SeccompProfile{
Type: api.SeccompProfileTypeLocalhost,
},
},
},
},
validation: func(t *testing.T, pod *api.Pod) {
require.Len(t, pod.Annotations, 0)
},
@ -911,7 +862,7 @@ func TestApplySeccompVersionSkew(t *testing.T) {
},
},
{
description: "Field type unconfined and no annotation present (container)",
description: "Field set and no annotation present (container)",
pod: &api.Pod{
Spec: api.PodSpec{
Containers: []api.Container{
@ -927,51 +878,7 @@ func TestApplySeccompVersionSkew(t *testing.T) {
},
},
validation: func(t *testing.T, pod *api.Pod) {
require.Len(t, pod.Annotations, 1)
require.Equal(t, v1.SeccompProfileNameUnconfined, pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+containerName])
},
},
{
description: "Field type runtime/default and no annotation present (container)",
pod: &api.Pod{
Spec: api.PodSpec{
Containers: []api.Container{
{
Name: containerName,
SecurityContext: &api.SecurityContext{
SeccompProfile: &api.SeccompProfile{
Type: api.SeccompProfileTypeRuntimeDefault,
},
},
},
},
},
},
validation: func(t *testing.T, pod *api.Pod) {
require.Len(t, pod.Annotations, 1)
require.Equal(t, v1.SeccompProfileRuntimeDefault, pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+containerName])
},
},
{
description: "Field type localhost and no annotation present (container)",
pod: &api.Pod{
Spec: api.PodSpec{
Containers: []api.Container{
{
Name: containerName,
SecurityContext: &api.SecurityContext{
SeccompProfile: &api.SeccompProfile{
Type: api.SeccompProfileTypeLocalhost,
LocalhostProfile: &testProfile,
},
},
},
},
},
},
validation: func(t *testing.T, pod *api.Pod) {
require.Len(t, pod.Annotations, 1)
require.Equal(t, "localhost/test", pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+containerName])
require.Len(t, pod.Annotations, 0)
},
},
{
@ -1002,9 +909,7 @@ func TestApplySeccompVersionSkew(t *testing.T) {
},
},
validation: func(t *testing.T, pod *api.Pod) {
require.Len(t, pod.Annotations, 2)
require.Equal(t, v1.SeccompProfileNameUnconfined, pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+containerName+"1"])
require.Equal(t, v1.SeccompProfileRuntimeDefault, pod.Annotations[v1.SeccompContainerAnnotationKeyPrefix+containerName+"3"])
require.Len(t, pod.Annotations, 0)
},
},
{

View File

@ -626,13 +626,10 @@ func (a *Admission) PolicyToEvaluate(labels map[string]string) (api.Policy, fiel
}
// isSignificantPodUpdate determines whether a pod update should trigger a policy evaluation.
// Relevant mutable pod fields as of 1.21 are image and seccomp annotations:
// Relevant mutable pod fields as of 1.21 are image annotations:
// * https://github.com/kubernetes/kubernetes/blob/release-1.21/pkg/apis/core/validation/validation.go#L3947-L3949
func isSignificantPodUpdate(pod, oldPod *corev1.Pod) bool {
// TODO: invert this logic to only allow specific update types.
if pod.Annotations[corev1.SeccompPodAnnotationKey] != oldPod.Annotations[corev1.SeccompPodAnnotationKey] {
return true
}
if len(pod.Spec.Containers) != len(oldPod.Spec.Containers) {
return true
}
@ -672,6 +669,7 @@ func isSignificantContainerUpdate(container, oldContainer *corev1.Container, ann
if container.Image != oldContainer.Image {
return true
}
// TODO(saschagrunert): Remove this logic in 1.27.
seccompKey := corev1.SeccompContainerAnnotationKeyPrefix + container.Name
return annotations[seccompKey] != oldAnnotations[seccompKey]
}

View File

@ -165,27 +165,27 @@ var _ = SIGDescribe("Security Context", func() {
pod.Spec.Containers[0].SecurityContext = &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeUnconfined}}
pod.Spec.SecurityContext = &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault}}
pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"0"}) // seccomp disabled
f.TestContainerOutput("seccomp unconfined container", pod, 0, []string{"0"}) // seccomp disabled
})
ginkgo.It("should support seccomp unconfined on the pod [LinuxOnly]", func() {
pod := scTestPod(false, false)
pod.Spec.SecurityContext = &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeUnconfined}}
pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"0"}) // seccomp disabled
f.TestContainerOutput("seccomp unconfined pod", pod, 0, []string{"0"}) // seccomp disabled
})
ginkgo.It("should support seccomp runtime/default [LinuxOnly]", func() {
pod := scTestPod(false, false)
pod.Spec.Containers[0].SecurityContext = &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault}}
pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"2"}) // seccomp filtered
f.TestContainerOutput("seccomp runtime/default", pod, 0, []string{"2"}) // seccomp filtered
})
ginkgo.It("should support seccomp default which is unconfined [LinuxOnly]", func() {
pod := scTestPod(false, false)
pod.Spec.Containers[0].Command = []string{"grep", "ecc", "/proc/self/status"}
f.TestContainerOutput(v1.SeccompPodAnnotationKey, pod, 0, []string{"0"}) // seccomp disabled
f.TestContainerOutput("seccomp default unconfined", pod, 0, []string{"0"}) // seccomp disabled
})
})