As Kubernetes and DevSecOps become more widespread, the desire to secure Kubernetes workloads is also growing.While concepts such as NetworkPolicies are now well established, SeurityContext has so far been rather rare in K8s.This article deals with the two SecurityContexts, namely the SecurityContext and the ContainerSecurityContext.
SecurityContext
A SecurityContext can be applied to ressources like Deployments, Pods or ReplicaSets. It formulates basic requirements that the containers must match in this workload. Therefore, you can specify the following values:
- runAsUser
- runAsGroup
- fsGroup
- fsGroupChangePolicy
- supplementalGroups
- sysctls
ContainerSecurityContext
In contrast to the normal SecurityContext, the ContainerSecurityContext offers further restriction options on container level:
- allowPrivilegeEscalation
- privileged
- procMount
- readOnlyRootFilesystem
- capabilities
K8s does not work without a pitfall
It would be too easy if there were only these two variants. However, there are also values that can be used in both SecurityContexts:
- runAsUser
- runAsGroup
- runAsNonRoot
- seLinuxOptions
- seccompprofile
- windowsOptions
But which of the dual-use values is prioritized? Values defined in a ContainerSecurityContext will always override the SecurityContext.
Example
Lets assume we want to start a custom Pod, that does not need any privileges. A simple deployment could look like this. Note, that I did not mount any volumes to keep the YAML clear:
apiVersion: v1
kind: Pod
metadata:
name: worker-pod
spec:
securityContext:
runAsUser: 10000
runAsGroup: 20000
fsGroup: 20001
containers:
- name: worker-pod-container
image: nginx:1.25.3
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
add: ["NET_RAW", "NET_BIND_SERVICE"]
Lets clarify the overriding of values:
apiVersion: v1
kind: Pod
metadata:
name: worker-pod
spec:
securityContext:
runAsUser: 10000
runAsGroup: 20000
fsGroup: 20001
containers:
- name: worker-pod-container
image: nginx:1.25.3
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
runAsUser: 1111
drop: ["ALL"]
add: ["NET_RAW", "NET_BIND_SERVICE"]
The container will run as UID 1111, because the ContainerSecurityContext overrides the values in SecurityContext.
Comparison
SecurityContext | ContainerSecurityContext | Both |
runAsUser | allowPrivilegeEscalation | runAsUser |
runAsGroup | privileged | runAsGroup |
fsGroup | procMount | runAsNonRoot |
fsGroupChangePolicy | readOnlyRootFilesystem | seLinuxOptions |
fsGroupChangePolicy | capabilities | seccompprofile |
supplementalGroups | windowsOptions | |
sysctls |
Ressources
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#podsecuritycontext-v1-core
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#securitycontext-v1-core
https://kubernetes.io/docs/tasks/configure-pod-container/security-context/