diff --git a/docs/docs/30-administration/22-backends/40-kubernetes.md b/docs/docs/30-administration/22-backends/40-kubernetes.md index 5637eb43b..f2e11ff80 100644 --- a/docs/docs/30-administration/22-backends/40-kubernetes.md +++ b/docs/docs/30-administration/22-backends/40-kubernetes.md @@ -197,7 +197,7 @@ backend_options: ``` :::note -AppArmor syntax follows [KEP-24](https://github.com/kubernetes/enhancements/blob/fddcbb9cbf3df39ded03bad71228265ac6e5215f/keps/sig-node/24-apparmor/README.md). +The feature requires Kubernetes v1.30 or above. ::: ### Annotations and labels diff --git a/pipeline/backend/kubernetes/pod.go b/pipeline/backend/kubernetes/pod.go index 679543470..53efbc8cd 100644 --- a/pipeline/backend/kubernetes/pod.go +++ b/pipeline/backend/kubernetes/pod.go @@ -84,7 +84,7 @@ func podMeta(step *types.Step, config *config, options BackendOptions, podName s meta := meta_v1.ObjectMeta{ Name: podName, Namespace: config.Namespace, - Annotations: podAnnotations(config, options, podName), + Annotations: podAnnotations(config, options), } meta.Labels, err = podLabels(step, config, options) @@ -126,7 +126,7 @@ func stepLabel(step *types.Step) (string, error) { return toDNSName(step.Name) } -func podAnnotations(config *config, options BackendOptions, podName string) map[string]string { +func podAnnotations(config *config, options BackendOptions) map[string]string { annotations := make(map[string]string) if len(options.Annotations) > 0 { @@ -141,13 +141,6 @@ func podAnnotations(config *config, options BackendOptions, podName string) map[ log.Trace().Msgf("using annotations from the configuration: %v", config.PodAnnotations) maps.Copy(annotations, config.PodAnnotations) } - securityContext := options.SecurityContext - if securityContext != nil { - key, value := apparmorAnnotation(podName, securityContext.ApparmorProfile) - if key != nil && value != nil { - annotations[*key] = *value - } - } return annotations } @@ -377,11 +370,12 @@ func toleration(backendToleration Toleration) v1.Toleration { func podSecurityContext(sc *SecurityContext, secCtxConf SecurityContextConfig, stepPrivileged bool) *v1.PodSecurityContext { var ( - nonRoot *bool - user *int64 - group *int64 - fsGroup *int64 - seccomp *v1.SeccompProfile + nonRoot *bool + user *int64 + group *int64 + fsGroup *int64 + seccomp *v1.SeccompProfile + apparmor *v1.AppArmorProfile ) if secCtxConf.RunAsNonRoot { @@ -410,6 +404,7 @@ func podSecurityContext(sc *SecurityContext, secCtxConf SecurityContextConfig, s } seccomp = seccompProfile(sc.SeccompProfile) + apparmor = apparmorProfile(sc.ApparmorProfile) } if nonRoot == nil && user == nil && group == nil && fsGroup == nil && seccomp == nil { @@ -417,11 +412,12 @@ func podSecurityContext(sc *SecurityContext, secCtxConf SecurityContextConfig, s } securityContext := &v1.PodSecurityContext{ - RunAsNonRoot: nonRoot, - RunAsUser: user, - RunAsGroup: group, - FSGroup: fsGroup, - SeccompProfile: seccomp, + RunAsNonRoot: nonRoot, + RunAsUser: user, + RunAsGroup: group, + FSGroup: fsGroup, + SeccompProfile: seccomp, + AppArmorProfile: apparmor, } log.Trace().Msgf("pod security context that will be used: %v", securityContext) return securityContext @@ -443,6 +439,22 @@ func seccompProfile(scp *SecProfile) *v1.SeccompProfile { return seccompProfile } +func apparmorProfile(scp *SecProfile) *v1.AppArmorProfile { + if scp == nil || len(scp.Type) == 0 { + return nil + } + log.Trace().Msgf("using AppArmor profile: %v", scp) + + apparmorProfile := &v1.AppArmorProfile{ + Type: v1.AppArmorProfileType(scp.Type), + } + if len(scp.LocalhostProfile) > 0 { + apparmorProfile.LocalhostProfile = &scp.LocalhostProfile + } + + return apparmorProfile +} + func containerSecurityContext(sc *SecurityContext, stepPrivileged bool) *v1.SecurityContext { if !stepPrivileged { return nil @@ -471,36 +483,6 @@ func containerSecurityContext(sc *SecurityContext, stepPrivileged bool) *v1.Secu return nil } -func apparmorAnnotation(containerName string, scp *SecProfile) (*string, *string) { - if scp == nil { - return nil, nil - } - log.Trace().Msgf("using AppArmor profile: %v", scp) - - var ( - profileType string - profilePath string - ) - - if scp.Type == SecProfileTypeRuntimeDefault { - profileType = "runtime" - profilePath = "default" - } - - if scp.Type == SecProfileTypeLocalhost { - profileType = "localhost" - profilePath = scp.LocalhostProfile - } - - if len(profileType) == 0 { - return nil, nil - } - - key := v1.DeprecatedAppArmorBetaContainerAnnotationKeyPrefix + containerName - value := profileType + "/" + profilePath - return &key, &value -} - func mapToEnvVars(m map[string]string) []v1.EnvVar { var ev []v1.EnvVar for k, v := range m { diff --git a/pipeline/backend/kubernetes/pod_test.go b/pipeline/backend/kubernetes/pod_test.go index 8b8241545..4f7732878 100644 --- a/pipeline/backend/kubernetes/pod_test.go +++ b/pipeline/backend/kubernetes/pod_test.go @@ -162,7 +162,6 @@ func TestFullPod(t *testing.T) { }, "annotations": { "apps.kubernetes.io/pod-index": "0", - "container.apparmor.security.beta.kubernetes.io/wp-01he8bebctabr3kgk0qj36d2me-0": "localhost/k8s-apparmor-example-deny-write", "kubernetes.io/limit-ranger": "LimitRanger plugin set: cpu, memory request and limit for container" } }, @@ -250,9 +249,13 @@ func TestFullPod(t *testing.T) { "runAsGroup": 101, "runAsNonRoot": true, "fsGroup": 101, + "appArmorProfile": { + "type": "Localhost", + "localhostProfile": "k8s-apparmor-example-deny-write" + }, "seccompProfile": { - "type": "Localhost", - "localhostProfile": "profiles/audit.json" + "type": "Localhost", + "localhostProfile": "profiles/audit.json" } }, "imagePullSecrets": [