Security Context Constraints (SCCs) are OpenShift’s mechanism for controlling and enforcing the security posture of pods at admission time. They predate and are more expressive than Kubernetes PSA: where PSA validates a pod spec against a fixed profile and either admits or rejects it, an SCC acts as both a validator and a mutator — it can inject missing fields into the pod spec (a UID from the namespace’s allocated range, an SELinux context, capability drops) so that a pod that did not specify its full security context in its manifest is brought into compliance automatically rather than rejected. SCCs are cluster-scoped resources, and access to them is controlled via RBAC: a service account must be granted use of an SCC through a Role or ClusterRole binding before pods running under that service account can be admitted with the permissions that SCC grants.
An SCC is a declarative object that specifies allowed, required, and default values across a comprehensive set of security dimensions. Linux capabilities are controlled through three fields: allowedCapabilities (the ceiling of what a container may request), defaultAddCapabilities (injected into every pod using this SCC), and requiredDropCapabilities (always removed, regardless of what the container requests — restricted-v2 sets this to ALL). User identity is controlled by runAsUser strategy: MustRunAsRange constrains the pod to a UID within the namespace’s pre-allocated range (the default for the restricted-v2 SCC), MustRunAsNonRoot requires a non-zero UID without constraining which one, and RunAsAny imposes no constraint. SELinux context is similarly governed by strategy: MustRunAs requires and enforces a specific label; RunAsAny allows any. Additional axes include allowPrivilegedContainer, allowHostNetwork/allowHostPID/allowHostIPC, allowedVolumes (an enumeration of permitted volume plugin types), fsGroup strategy, seccompProfiles, and readOnlyRootFilesystem. OpenShift ships a set of built-in SCCs ordered by restrictiveness — restricted-v2 (default for all authenticated users since OCP 4.11, drops all capabilities), restricted, nonroot-v2, anyuid, hostaccess, hostmount-anyuid, node-exporter, and privileged — which should not be modified, with custom SCCs created for workloads needing specific grants.
The admission algorithm is the operationally critical part. When a pod is submitted, the SCC admission plugin collects all SCCs accessible to the pod’s service account (via RBAC), sorts them by priority (a numeric field, higher wins; anyuid has priority 10 by default), and then iterates through the sorted list to find the most restrictive SCC that the pod can satisfy — not necessarily the first one. If an SCC can admit the pod only by mutating its spec (injecting the UID or SELinux label), it does so; the admitted pod is annotated with openshift.io/scc: <name> identifying which SCC was applied. If no SCC in the list can accommodate the pod, admission is rejected with an error detailing which constraints failed. This selection model means that granting a service account access to a permissive SCC like anyuid does not unconditionally use it — if the pod is compatible with restricted-v2, that more restrictive SCC wins. On OCP 4.11 and later, OpenShift also runs a PSA label synchronisation controller alongside SCCs: it inspects the effective SCC privilege level of each namespace’s service accounts and automatically sets the corresponding PSA namespace labels, ensuring that PSA enforcement does not conflict with what SCCs already permit — PSA and SCCs are complementary layers on OpenShift, not competing ones.
