Security Contexts¶
A security context defines privilege and access control settings for a Pod or container: which user and group it runs as, which Linux capabilities it has, whether it can escalate privileges, whether its root filesystem is read-only, and which seccomp and SELinux profiles apply.
spec.securityContext(aPodSecurityContext) applies to every container in the Pod, for examplerunAsUser,runAsGroup,fsGroupandseccompProfile.spec.containers[].securityContextapplies to a single container and overrides the Pod-level values, for exampleallowPrivilegeEscalation,capabilities,readOnlyRootFilesystemandprivileged.
How the cluster enforces security contexts¶
OpenShift uses Security Context Constraints (SCCs). By default, every Pod is admitted under the restricted-v2 SCC, which:
- runs the container as a random UID from a range allocated to the project, ignoring the image's
USER, with group0(root group) as a supplemental group - drops all Linux capabilities and blocks privilege escalation
- applies the
RuntimeDefaultseccomp profile and a per-project SELinux context - blocks
hostPathvolumes, host networking and privileged containers
OpenShift fills in these settings for you. A Pod that doesn't set a security context is simply given one. A Pod that asks for more (for example runAsUser: 0 or privileged: true) is rejected unless its ServiceAccount has been granted a less restrictive SCC by a cluster administrator.
Upstream Kubernetes uses Pod Security Admission, configured per namespace with labels such as pod-security.kubernetes.io/enforce: restricted. Unlike SCCs, Pod Security Admission only validates Pods and never changes them. Under the restricted level, you must set the secure values yourself or the Pod is rejected.
Resources¶
Example¶
This Pod follows the restricted rules and adds a read-only root filesystem. The app can only write to the emptyDir volume mounted at /tmp.
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
containers:
- name: demo
image: registry.access.redhat.com/ubi9/ubi-minimal
command:
- sh
- -c
- |
id
touch /tmp/ok && echo "can write to /tmp"
touch /hello 2>/dev/null || echo "cannot write to /"
sleep infinity
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
The remaining restricted settings (UID, capabilities, seccomp, privilege escalation) are added by the restricted-v2 SCC.
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1001
runAsGroup: 0
seccompProfile:
type: RuntimeDefault
containers:
- name: demo
image: registry.access.redhat.com/ubi9/ubi-minimal
command:
- sh
- -c
- |
id
touch /tmp/ok && echo "can write to /tmp"
touch /hello 2>/dev/null || echo "cannot write to /"
sleep infinity
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
Warning
Don't hard-code runAsUser in manifests meant for OpenShift. A fixed UID outside the project's range is rejected by restricted-v2.
uid=1000680000(1000680000) gid=0(root) groups=0(root),1000680000
can write to /tmp
cannot write to /
See what the cluster applied:
oc get pod security-context-demo -o jsonpath='{.spec.securityContext}{"\n"}{.spec.containers[0].securityContext}{"\n"}'
Try it: a pod that asks for too much¶
Try to create a Pod that runs as root:
apiVersion: v1
kind: Pod
metadata:
name: root-pod
spec:
containers:
- name: demo
image: registry.access.redhat.com/ubi9/ubi-minimal
command: ["sleep", "infinity"]
securityContext:
runAsUser: 0
OpenShift rejects it with an error like pods "root-pod" is forbidden: unable to validate against any security context constraint: ... runAsUser: Invalid value: 0: must be in the ranges: [1000680000, 1000689999].