Add seccomp and AppArmor profile support to Kubernetes executor security context
Feature Request: Add SeccompProfile and AppArmorProfile to Kubernetes executor security context configuration
Summary
Add native seccomp_profile_type and app_armor_profile_type fields (with corresponding localhost_profile fields) to [runners.kubernetes.build_container_security_context] and the pod/helper/service/init security context sections in config.toml, so users can configure Seccomp and AppArmor profiles without relying on deprecated annotations or pod spec patches.
Motivation
The Kubernetes executor currently lacks native support for configuring seccomp profiles and AppArmor profiles through the security context configuration. Users who need these settings face three problematic workarounds:
-
Deprecated annotations —
container.seccomp.security.alpha.kubernetes.io/build = "unconfined"was removed in Kubernetes 1.27. The AppArmor annotation still works but is deprecated in favor of thesecurityContext.appArmorProfilefield (GA in K8s 1.30). -
Pod spec patches — Require the beta
FF_USE_ADVANCED_POD_SPEC_CONFIGURATIONfeature flag, embed JSON/YAML inside TOML, don't integrate with Helm charts, and lack validation. Prior to Runner 18.7.0, patches were silently dropped because the k8s client-go (v0.26) did not include theAppArmorProfiletype. - No coverage for all container types — Neither annotations nor pod spec patches reliably configure the helper container.
Real-world impact: Ubuntu 23.10+ enables kernel.apparmor_restrict_unprivileged_userns=1 by default, which blocks rootless container image building tools (BuildKit, Podman) from mounting /proc inside RUN steps. The only fix is setting appArmorProfile: { type: Unconfined } on the build container — which is impossible through config.toml today.
This also blocks compliance-driven environments (e.g., Azure AKS policy enforcement) that require explicit seccomp profiles on all pods.
Related Issues
- #26849 — Allow setting seccomp policy in security context in config.toml
- #38936 — Add ability to configure AppArmor for build pod Security Context
- #38266 — Unable to configure AppArmor profile for build pods when using Kubernetes executor
Proposal
Add four new fields to both KubernetesContainerSecurityContext and KubernetesPodSecurityContext config structs:
[runners.kubernetes.build_container_security_context]
seccomp_profile_type = "Unconfined" # RuntimeDefault | Localhost | Unconfined
seccomp_profile_localhost_profile = "" # required when type = Localhost
app_armor_profile_type = "Unconfined" # RuntimeDefault | Localhost | Unconfined
app_armor_profile_localhost_profile = "" # required when type = Localhost
[runners.kubernetes.pod_security_context]
seccomp_profile_type = "RuntimeDefault"
seccomp_profile_localhost_profile = ""
app_armor_profile_type = "RuntimeDefault"
app_armor_profile_localhost_profile = ""
Behavior:
- When
seccomp_profile_typeis set, constructapi.SeccompProfile{Type: ...}on the returnedSecurityContext - When
app_armor_profile_typeis set, constructapi.AppArmorProfile{Type: ...}on the returnedSecurityContext - When type is
Localhost, require the correspondinglocalhost_profilefield; log a warning and skip if missing - When type is empty, omit the field entirely (unchanged from today)
- Container-level overrides pod-level (standard Kubernetes precedence)
- Invalid type values produce a warning log and are ignored
Affected Files
Config struct (common/config.go):
-
KubernetesContainerSecurityContext— add 4 fields with TOML/JSON/env tags -
KubernetesPodSecurityContext— add 4 fields with TOML/JSON/env tags
Conversion logic (common/config.go):
-
GetContainerSecurityContext()— setSeccompProfileandAppArmorProfileon returnedapi.SecurityContext -
GetPodSecurityContext()— setSeccompProfileandAppArmorProfileon returnedapi.PodSecurityContext - Add helper functions
toSeccompProfile()andtoAppArmorProfile()for validation and conversion
Documentation (docs/executors/kubernetes/index.md or equivalent):
- Add
seccomp_profile_type,seccomp_profile_localhost_profile,app_armor_profile_type,app_armor_profile_localhost_profileto the container security context options table - Add same fields to the pod security context options table
- Document minimum Kubernetes version requirement: seccomp requires K8s >= 1.19, AppArmor field requires K8s >= 1.30
Example Usage
Rootless BuildKit image building on Ubuntu 23.10+ nodes:
[[runners]]
executor = "kubernetes"
[runners.kubernetes]
[runners.kubernetes.build_container_security_context]
app_armor_profile_type = "Unconfined"
seccomp_profile_type = "Unconfined"
Azure AKS compliance with RuntimeDefault seccomp:
[[runners]]
executor = "kubernetes"
[runners.kubernetes]
[runners.kubernetes.pod_security_context]
seccomp_profile_type = "RuntimeDefault"
Custom seccomp profile:
[[runners]]
executor = "kubernetes"
[runners.kubernetes]
[runners.kubernetes.build_container_security_context]
seccomp_profile_type = "Localhost"
seccomp_profile_localhost_profile = "profiles/my-profile.json"
Tests
Add test cases to existing security context test files following the project's Ginkgo/Gomega patterns:
-
Seccomp profile type set to Unconfined — verify
api.SecurityContext.SeccompProfile.Typeisapi.SeccompProfileTypeUnconfined -
Seccomp profile type set to Localhost with localhost_profile — verify both
TypeandLocalhostProfileare set - Seccomp profile type set to Localhost without localhost_profile — verify warning logged and field omitted
-
AppArmor profile type set to Unconfined — verify
api.SecurityContext.AppArmorProfile.Typeisapi.AppArmorProfileTypeUnconfined - AppArmor profile type set to Localhost with localhost_profile — verify both fields set
- Invalid profile type — verify warning logged and field omitted
- Pod-level security context — same tests at pod level
- Container-level overrides pod-level — verify container settings take precedence
Changelog
Changelog: added
Kubernetes executor: Add seccomp and AppArmor profile configuration to container and pod security contexts
Additional Context
- The k8s client-go was updated to v0.32.10 in Runner v18.7.0 (!5929 (merged)), so the
api.AppArmorProfiletype is now available in the codebase. - The
AppArmorProfilefield inSecurityContextis GA since Kubernetes 1.30. Setting it against older apiservers may cause pod creation to fail. This should be documented as a minimum version requirement. - For backward compatibility with clusters < 1.30, a future enhancement could add automatic fallback to legacy AppArmor annotations, but this is out of scope for the initial implementation.
- The existing
ProcMountandSELinuxTypefields follow the same pattern of string-typed config values converted to k8s API types, so this change is consistent with existing conventions.