mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Merge pull request #109819 from saschagrunert/seccomp-annotation
Partly remove support for seccomp annotations
This commit is contained in:
commit
37b100bea6
@ -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 {
|
||||
|
@ -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)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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`,
|
||||
},
|
||||
|
@ -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{}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -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]
|
||||
}
|
||||
|
@ -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
|
||||
})
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user