Skip to content

Commit

Permalink
Partly remove support for seccomp annotations
Browse files Browse the repository at this point in the history
We now partly drop the support for seccomp annotations which is planned
for v1.25 as part of the KEP:

kubernetes/enhancements#135

Pod security policies are not touched by this change and therefore we
have to keep the annotation key constants.

This means we only allow the usage of the annotations for backwards
compatibility reasons while the synchronization of the field to
annotation is no longer supported. Using the annotations for static pods
is also not supported any more.

Making the annotations fully non-functional will be deferred to a
future release.

Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
  • Loading branch information
saschagrunert committed Aug 1, 2022
1 parent d046a58 commit 584783e
Show file tree
Hide file tree
Showing 11 changed files with 53 additions and 425 deletions.
30 changes: 0 additions & 30 deletions pkg/api/pod/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions pkg/api/pod/warnings.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,15 +240,15 @@ 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)))
}
}

pods.VisitContainersWithPath(podSpec, fieldPath.Child("spec"), func(c *api.Container, p *field.Path) bool {
// 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)))
}
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/api/pod/warnings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
},
Expand Down
2 changes: 1 addition & 1 deletion pkg/apis/core/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}

Expand Down
21 changes: 0 additions & 21 deletions pkg/kubelet/kuberuntime/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,39 +234,18 @@ 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
if containerSecContext != nil && containerSecContext.SeccompProfile != nil {
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
}
Expand Down
230 changes: 0 additions & 230 deletions pkg/kubelet/kuberuntime/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}},
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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}},
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 0 additions & 6 deletions pkg/kubelet/kuberuntime/kuberuntime_sandbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 584783e

Please sign in to comment.