mirror of
https://github.com/optim-enterprises-bv/kubernetes.git
synced 2025-11-01 18:58:18 +00:00
Add seccomp GA version skew for pods
This adds a new conversion function to the pod strategy to handle the seccomp version skew strategy: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/20190717-seccomp-ga.mdversion-skew-strategy Signed-off-by: Sascha Grunert <sgrunert@suse.com>
This commit is contained in:
@@ -26,6 +26,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
@@ -74,6 +75,8 @@ func (podStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
||||
}
|
||||
|
||||
podutil.DropDisabledPodFields(pod, nil)
|
||||
|
||||
applySeccompVersionSkew(pod)
|
||||
}
|
||||
|
||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||
@@ -569,3 +572,129 @@ func validateContainer(container string, pod *api.Pod) (string, error) {
|
||||
|
||||
return container, nil
|
||||
}
|
||||
|
||||
// applySeccompVersionSkew implements the version skew behavior described in:
|
||||
// https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/20190717-seccomp-ga.md#version-skew-strategy
|
||||
func applySeccompVersionSkew(pod *api.Pod) {
|
||||
// get possible annotation and field
|
||||
annotation, hasAnnotation := pod.Annotations[v1.SeccompPodAnnotationKey]
|
||||
field, hasField := (*api.SeccompProfile)(nil), 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 := seccompAnnotationForField(field)
|
||||
|
||||
if newAnnotation != "" {
|
||||
if pod.Annotations == nil {
|
||||
pod.Annotations = map[string]string{}
|
||||
}
|
||||
pod.Annotations[v1.SeccompPodAnnotationKey] = newAnnotation
|
||||
}
|
||||
} else if hasAnnotation && !hasField {
|
||||
newField := seccompFieldForAnnotation(annotation)
|
||||
|
||||
if newField != nil {
|
||||
if pod.Spec.SecurityContext == nil {
|
||||
pod.Spec.SecurityContext = &api.PodSecurityContext{}
|
||||
}
|
||||
pod.Spec.SecurityContext.SeccompProfile = newField
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the containers of the pod
|
||||
podutil.VisitContainers(&pod.Spec, podutil.AllFeatureEnabledContainers(),
|
||||
func(ctr *api.Container, _ podutil.ContainerType) bool {
|
||||
// get possible annotation and field
|
||||
key := api.SeccompContainerAnnotationKeyPrefix + ctr.Name
|
||||
annotation, hasAnnotation := pod.Annotations[key]
|
||||
|
||||
field, hasField := (*api.SeccompProfile)(nil), false
|
||||
if ctr.SecurityContext != nil && ctr.SecurityContext.SeccompProfile != nil {
|
||||
field = ctr.SecurityContext.SeccompProfile
|
||||
hasField = true
|
||||
}
|
||||
|
||||
// sync field and annotation
|
||||
if hasField && !hasAnnotation {
|
||||
newAnnotation := seccompAnnotationForField(field)
|
||||
|
||||
if newAnnotation != "" {
|
||||
if pod.Annotations == nil {
|
||||
pod.Annotations = map[string]string{}
|
||||
}
|
||||
pod.Annotations[key] = newAnnotation
|
||||
}
|
||||
} else if hasAnnotation && !hasField {
|
||||
newField := seccompFieldForAnnotation(annotation)
|
||||
|
||||
if newField != nil {
|
||||
if ctr.SecurityContext == nil {
|
||||
ctr.SecurityContext = &api.SecurityContext{}
|
||||
}
|
||||
ctr.SecurityContext.SeccompProfile = newField
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// seccompFieldForAnnotation takes a pod seccomp profile field and returns the
|
||||
// converted annotation value
|
||||
func seccompAnnotationForField(field *api.SeccompProfile) string {
|
||||
// If only seccomp fields are specified, add the corresponding annotations.
|
||||
// This ensures that the fields are enforced even if the node version
|
||||
// trails the API version
|
||||
switch field.Type {
|
||||
case api.SeccompProfileTypeUnconfined:
|
||||
return v1.SeccompProfileNameUnconfined
|
||||
|
||||
case api.SeccompProfileTypeRuntimeDefault:
|
||||
return v1.SeccompProfileRuntimeDefault
|
||||
|
||||
case api.SeccompProfileTypeLocalhost:
|
||||
if field.LocalhostProfile != nil {
|
||||
return v1.SeccompLocalhostProfileNamePrefix + *field.LocalhostProfile
|
||||
}
|
||||
}
|
||||
|
||||
// we can only reach this code path if the LocalhostProfile is nil but the
|
||||
// provided field type is SeccompProfileTypeLocalhost or if an unrecognized
|
||||
// type is specified
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user