
In this guide, we will explain OpenShift Security Context Constraints (SCCs) in simple terms. SCCs are essential components of OpenShift that help keep cluster containers and applications secure. If you’ve worked with OpenShift, you might have heard of SCCs, whether during deployment troubleshooting or while configuring advanced security policies for your workloads. But what are OpenShift Security Context Constraints exactly, and why should you care about it? Let’s find out!
Table of Contents
Understanding OpenShift Security Context Constraints (SCCs)
Introduction to Security Contexts and SCCs
Red Hat OpenShift provides robust security features to manage what containerized applications can and cannot do. Two critical components of this security framework are Security Contexts (SCs) and Security Context Constraints (SCCs).
Security Context Constraints (SCCs) are OpenShift-specific resources that extend Kubernetes’ native concept of security contexts. In Kubernetes, a security context defines privileges and access control settings for a pod or container. OpenShift SCCs enhances this by providing a cluster-wide mechanism to enforce the security settings consistently across all workloads.
Both security contexts and security context constraints work together to protect the nodes by restricting what pods and containers are allowed to do.
They enforce controls over several key security aspects, including:
- Whether a pod can run as a privileged container
- User ID (UID) or group ID (GID) the container runs as
- Access to host resources, such as:
- Host network
- Host IPC and process namespaces
- Host-mounted file systems
- Linux capabilities the container can request or must drop (e.g.,
KILL
,SYS_ADMIN
,NET_ADMIN
) - SELinux contexts applied to the container
- Volume types the pod is permitted to use (e.g.,
hostPath
,emptyDir
, etc.)
Many cloud-native applications such as stateless microservices, APIs, and web apps etc… are designed to operate smoothly within these sandboxed, restricted environments and do not require elevated privileges or access to host-level resources.
However, some stateful workloads like databases, storage systems, monitoring agents, or networking plugins may require access to these protected host-level functions in order to operate correctly. These include the ability to:
- Access raw storage devices
- Mount host file systems
- Use host network or process namespaces
- Run as the root user or with specific Linux capabilities
In such cases, more permissive SCCs (e.g., privileged
) must be used to grant the necessary access, while still maintaining control over security and risk.
Security Context Settings for Pods and Containers
There are different security context settings that can be applied to pods and containers to control specific Linux functions, organized into groups such as:
User and Group Identity settings
These settings control the user and group IDs under which processes and files operate. SCCs enforce these settings to restrict root access or define valid ID ranges.
- Pod-level fields (spec.securityContext):
- runAsUser: Sets the UID for all containers’ processes (e.g., 1000). SCCs check if the UID is allowed (e.g., MustRunAs range or RunAsAny).
- runAsGroup: Defines the primary GID for containers’ processes (e.g., 2000). SCCs enforce valid GID ranges.
- runAsNonRoot: Ensures containers run as non-root (boolean; true blocks UID 0). SCCs use MustRunAsNonRoot to mandate this.
- fsGroup: Sets GID for volume ownership and permissions (e.g., 3000). SCCs enforce MustRunAs or RunAsAny for volume GIDs.
- supplementalGroups: Adds extra GIDs for containers (e.g., [4000, 5000]). SCCs restrict allowed supplemental GIDs.
- supplementalGroupsPolicy: Defines how supplementary groups are calculated (Merge: includes /etc/group for primary user; nbvm : uses only fsGroup, supplementalGroups, runAsGroup; default is Merge if unset).
- Container-level fields (spec.containers.securityContext):
- runAsUser: Overrides pod-level UID for this container (e.g., 1001). SCCs validate against allowed UID ranges.
- runAsGroup: Overrides pod-level GID for this container (e.g., 2001). SCCs ensure GID compliance.
- runAsNonRoot: Enforces non-root for this container (boolean; true prevents root). SCCs align with MustRunAsNonRoot.
Privilege and Escalation Controls
These settings manage elevated permissions and prevent unauthorized privilege gains. SCCs restrict these settings to limit powerful containers.
- Container-level fields only:
- privileged: Runs container with full host access (boolean; true enables). SCCs often forbid this (e.g., restricted SCC disallows).
- allowPrivilegeEscalation: Permits processes to gain more privileges (boolean; false blocks escalation). SCCs enforce AllowPrivilegedEscalation to restrict this.
Linux Capabilities Settings
These settings define kernel-level permissions for container processes. SCCs tightly control them to prevent abuse.
- Container-level fields only:
- capabilities:
- add: Grants extra capabilities (e.g., [“NET_ADMIN”, “SYS_TIME”]); SCCs limit to allowedCapabilities.
- drop: Removes capabilities (e.g., [“CHOWN”, “SETUID”]); SCCs mandate requiredDropCapabilities (e.g., ALL for restricted).
- capabilities:
Here is a description of most common Linux capabilities.
Networking Capabilities:
- CAP_NET_BIND_SERVICE
- Allows binding to TCP/UDP sockets below 1024 (privileged ports) without having to run as root user.
- Example use case: Running an HTTP server on port 80.
- CAP_NET_ADMIN
- Grants administrative control over the network stack (e.g., modifying routing tables, firewall rules, or interfaces).
- Example use case: Configuring network settings inside the container.
- CAP_NET_RAW
- Allows raw socket access (e.g., sending ICMP packets or custom network protocols, traffic monitoring/spoofing/scanning).
- Example use case: Running diagnostic tools like
ping, tcpdump
.
Filesystem and Device Capabilities:
- CAP_CHOWN
- Allows changing file ownership (
chown
). - Example use case: Modifying file permissions in shared volumes.
- Allows changing file ownership (
- CAP_DAC_OVERRIDE
- Bypasses file read/write/execute permission checks.
- Example use case: Accessing restricted files during debugging.
- DAC is an abbreviation of Discretionary Access Control (Access to files is given to users at the discretion of owner)
- CAP_DAC_READ_SEARCH
- Bypasses file/directory read/search permission checks.
- Example use case: Reading restricted files without altering permissions.
- CAP_FOWNER
- Acts as the owner of a file, even if the process isn’t the actual owner.
- Example use case: Managing files in shared storage.
- CAP_MKNOD
- Creates special files (e.g., block or character devices).
- Example use case: Setting up device nodes in containers.
Process Management Capabilities:
- CAP_KILL
- Allows sending signals (like SIGKILL) to arbitrary processes.
- Example use case: Terminating misbehaving processes.
- CAP_SYS_BOOT
- Reboots the system.
- Rarely needed in containers; typically restricted.
- CAP_SYS_NICE
- Modifies process priorities (e.g.,
nice
,realtime
). - Example use case: Prioritizing critical tasks in a container.
- Modifies process priorities (e.g.,
- CAP_SYS_PTRACE
- Allows debugging or tracing processes (e.g.,
ptrace
). - Example use case: Debugging applications inside the container.
- Allows debugging or tracing processes (e.g.,
System-Level Capabilities
- CAP_SYS_ADMIN
- One of the most powerful capabilities, granting broad administrative rights (e.g., mounting filesystems, modifying namespaces).
- Example use case: Mounting volumes inside the container.
- Avoid it if you can!
- CAP_SYS_TIME
- Changes the system clock.
- Example use case: Synchronizing time in containers (rarely needed).
- CAP_SYSLOG
- Reads/writes kernel logs (
dmesg
). - Example use case: Diagnosing low-level system issues.
- Reads/writes kernel logs (
Security and Auditing Capabilities:
- CAP_AUDIT_CONTROL
- Enables/disables kernel auditing and modifies audit rules.
- Example use case: Rarely needed in containers.
- CAP_AUDIT_WRITE
- Writes records to the kernel audit log.
- Example use case: Logging security events.
- CAP_SETFCAP
- Sets file capabilities on files.
- Example use case: Managing capabilities for executables.
- CAP_SETGID
- Changes the group ID of the process.
- Example use case: Switching between groups for access control.
- CAP_SETUID
- Changes the user ID of the process.
- Example use case: Switching between users for access control.
Read more on man capabilities.
Filesystem Access Controls
Restrict access to container filesystems or volume mounts, enforced by SCCs to protect host resources.
- Pod-level fields:
- fsGroup: Applies GID to volumes for consistent ownership (e.g., 3000); SCCs validate via MustRunAs or RunAsAny.
- Container-level fields:
- readOnlyRootFilesystem: Mounts container’s root filesystem as read-only (boolean; true prevents writes); SCCs may require this for security.
SELinux settings
Configure SELinux labels for process and file isolation, enforced by SCCs to ensure proper context.
- Pod-level fields:
- seLinuxOptions: Sets SELinux labels (e.g., level: “s0:c123,c456”, role, type, user).
- Container-level fields:
- seLinuxOptions: Overrides pod-level SELinux labels for this container (e.g., level: “s0:c789,c012”).
System Call and Kernel settings
Limit system calls or kernel parameters, restricted by SCCs to prevent unsafe configurations.
- Pod-level fields:
- sysctls: Configures kernel parameters (e.g., name: net.core.somaxconn, value: “1024”). SCCs restrict to allowedSysctls.
- Container-level fields:
- seccompProfile: Applies seccomp filter for system calls (e.g., type: RuntimeDefault or Localhost, with localhostProfile). SCCs enforce allowedSeccompProfiles.
Proc Filesystem settings
Control /proc mount behavior in containers, limited by SCCs to reduce attack surface.
- Container-level fields only:
- procMount: Sets /proc mount type (e.g., Default masks sensitive entries, Unmasked exposes all); SCCs restrict allowedProcMountTypes.
Default Security Context Constraints in OpenShift
There are a number of default Security Context Constraints (SCCs) available in OpenShift, each designed to enforce specific security policies for pods and containers. These SCCs govern critical securityContext settings listed above, ensuring workloads run securely within defined boundaries. From highly restrictive options for general use to permissive configurations for administrative tasks, the default SCCs provide a flexible framework to balance security and functionality in an OpenShift cluster.
Do not modify the default SCCs. Instead, you can create your custom ones.
Listing Available SCCs in OpenShift
You can list available SCCs in OpenShift using oc get command and specifying scc as the resource.
oc get scc
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP PRIORITY READONLYROOTFS VOLUMES
anyuid false MustRunAs RunAsAny RunAsAny RunAsAny 10 false ["configMap","csi","downwardAPI","emptyDir","ephemeral","persistentVolumeClaim","projected","secret"]
hostaccess false MustRunAs MustRunAsRange MustRunAs RunAsAny false ["configMap","csi","downwardAPI","emptyDir","ephemeral","hostPath","persistentVolumeClaim","projected","secret"]
hostmount-anyuid false MustRunAs RunAsAny RunAsAny RunAsAny false ["configMap","csi","downwardAPI","emptyDir","ephemeral","hostPath","nfs","persistentVolumeClaim","projected","secret"]
hostnetwork false MustRunAs MustRunAsRange MustRunAs MustRunAs false ["configMap","csi","downwardAPI","emptyDir","ephemeral","persistentVolumeClaim","projected","secret"]
hostnetwork-v2 false ["NET_BIND_SERVICE"] MustRunAs MustRunAsRange MustRunAs MustRunAs false ["configMap","csi","downwardAPI","emptyDir","ephemeral","persistentVolumeClaim","projected","secret"]
machine-api-termination-handler false MustRunAs RunAsAny MustRunAs MustRunAs false ["downwardAPI","hostPath"]
node-exporter true RunAsAny RunAsAny RunAsAny RunAsAny false ["*"]
nonroot false MustRunAs MustRunAsNonRoot RunAsAny RunAsAny false ["configMap","csi","downwardAPI","emptyDir","ephemeral","persistentVolumeClaim","projected","secret"]
nonroot-v2 false ["NET_BIND_SERVICE"] MustRunAs MustRunAsNonRoot RunAsAny RunAsAny false ["configMap","csi","downwardAPI","emptyDir","ephemeral","persistentVolumeClaim","projected","secret"]
privileged true ["*"] RunAsAny RunAsAny RunAsAny RunAsAny false ["*"]
restricted false MustRunAs MustRunAsRange MustRunAs RunAsAny false ["configMap","csi","downwardAPI","emptyDir","ephemeral","persistentVolumeClaim","projected","secret"]
restricted-v2 false ["NET_BIND_SERVICE"] MustRunAs MustRunAsRange MustRunAs RunAsAny false ["configMap","csi","downwardAPI","emptyDir","ephemeral","persistentVolumeClaim","projected","secret"]
To print just the names of the SCCs;
oc get scc -o name
securitycontextconstraints.security.openshift.io/anyuid
securitycontextconstraints.security.openshift.io/hostaccess
securitycontextconstraints.security.openshift.io/hostmount-anyuid
securitycontextconstraints.security.openshift.io/hostnetwork
securitycontextconstraints.security.openshift.io/hostnetwork-v2
securitycontextconstraints.security.openshift.io/machine-api-termination-handler
securitycontextconstraints.security.openshift.io/node-exporter
securitycontextconstraints.security.openshift.io/nonroot
securitycontextconstraints.security.openshift.io/nonroot-v2
securitycontextconstraints.security.openshift.io/privileged
securitycontextconstraints.security.openshift.io/restricted
securitycontextconstraints.security.openshift.io/restricted-v2
The SCCs can be grouped as follows;
Most Permissive (Least Restrictive)
privileged
- Most relaxed SCC – use only for cluster administration
- Allows access to all privileged and host features
- Allows running as any user, group, FSGroup, and SELinux context
- Allows host mounts, privileged pods, host namespaces, and any capabilities
hostaccess
- Allows access to all host namespaces
- Still requires pods to run with allocated UID and SELinux context
- Warning: Grants host access to namespaces, file systems, and PIDs – use with caution
hostmount-anyuid
- Provides all features of restricted SCC
- Allows host mounts and running as any UID and GID
- Warning: Allows host file system access as any UID (including root) – grant with caution
Moderately Permissive
hostnetwork
- Allows using host networking and host ports
- Still requires allocated UID and SELinux context
- Warning: A workload with hostnetwork on a control plane host is effectively root on the cluster
node-exporter
- Used for the Prometheus node exporter
- Warning: Allows host file system access as any UID (including root)
anyuid
- Provides all features of the restricted SCC
- Allows users to run with any UID and any GID
Restrictive
hostnetwork-v2
- Similar to hostnetwork but with these differences:
- ALL capabilities are dropped from containers
- NET_BIND_SERVICE capability can be added explicitly
- seccompProfile set to runtime/default by default
- allowPrivilegeEscalation must be false or unset
nonroot
- Provides all features of restricted SCC
- Allows users to run with any non-root UID
- User must specify the UID or it must be in the container manifest
nonroot-v2
- Like nonroot but with these differences:
- ALL capabilities are dropped
- NET_BIND_SERVICE capability can be added explicitly
- seccompProfile set to runtime/default by default
- allowPrivilegeEscalation must be false or unset
Most Restrictive
restricted
- Denies access to all host features
- Requires pods to run with allocated UID and SELinux context
- No longer available by default in OpenShift 4.11+ for new installations unless the access is explicitly granted.
restricted-v2
- Like restricted but with these differences:
- ALL capabilities are dropped
- NET_BIND_SERVICE capability can be added explicitly
- seccompProfile set to runtime/default by default
- allowPrivilegeEscalation must be false or unset
- Default SCC for authenticated users in new OpenShift 4.11+ installations
- Most restrictive of the default SCCs
Get Detailed Summary of the SCC
You can use oc get or oc describe commands to view more details of an SCC on Openshift.
The oc describe command provides a more human-readable, detailed summary of a resource, focusing on runtime information. It’s especially useful for troubleshooting and understanding what’s happening with a resource at a glance.
To get a runtime description of an SCC;
oc describe scc anyuid
Name: anyuid
Priority: 10
Access:
Users: <none>
Groups: system:cluster-admins
Settings:
Allow Privileged: false
Allow Privilege Escalation: true
Default Add Capabilities: <none>
Required Drop Capabilities: MKNOD
Allowed Capabilities: <none>
Allowed Seccomp Profiles: <none>
Allowed Volume Types: configMap,csi,downwardAPI,emptyDir,ephemeral,persistentVolumeClaim,projected,secret
Allowed Flexvolumes: <all>
Allowed Unsafe Sysctls: <none>
Forbidden Sysctls: <none>
Allow Host Network: false
Allow Host Ports: false
Allow Host PID: false
Allow Host IPC: false
Read Only Root Filesystem: false
Run As User Strategy: RunAsAny
UID: <none>
UID Range Min: <none>
UID Range Max: <none>
SELinux Context Strategy: MustRunAs
User: <none>
Role: <none>
Type: <none>
Level: <none>
FSGroup Strategy: RunAsAny
Ranges: <none>
Supplemental Groups Strategy: RunAsAny
Ranges: <none>
The oc get command with -o yaml outputs the raw YAML definition of the resource as stored in the OpenShift API. This includes all metadata, spec, and configuration fields.
Take for example, anyuid SCC.
oc get scc anyuid -o yaml
allowHostDirVolumePlugin: false
allowHostIPC: false
allowHostNetwork: false
allowHostPID: false
allowHostPorts: false
allowPrivilegeEscalation: true
allowPrivilegedContainer: false
allowedCapabilities: null
apiVersion: security.openshift.io/v1
defaultAddCapabilities: null
fsGroup:
type: RunAsAny
groups:
- system:cluster-admins
kind: SecurityContextConstraints
metadata:
annotations:
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
include.release.openshift.io/single-node-developer: "true"
kubernetes.io/description: anyuid provides all features of the restricted SCC
but allows users to run with any UID and any GID.
release.openshift.io/create-only: "true"
creationTimestamp: "2025-02-16T18:11:05Z"
generation: 1
name: anyuid
resourceVersion: "341"
uid: b4176dd2-52eb-4f3d-8c92-5d9276bd2c8a
priority: 10
readOnlyRootFilesystem: false
requiredDropCapabilities:
- MKNOD
runAsUser:
type: RunAsAny
seLinuxContext:
type: MustRunAs
supplementalGroups:
type: RunAsAny
users: []
volumes:
- configMap
- csi
- downwardAPI
- emptyDir
- ephemeral
- persistentVolumeClaim
- projected
- secret
As already mentioned above, the purpose of the anyuid SCC is to extend the restricted
SCC but allows containers to run as any UID/GID (including root). Here is a brief summary of the anyuid Security Constraint Context above:
- Key Permissions:
runAsUser
/fsGroup
/supplementalGroups
: RunAsAny (no UID/GID restrictions)- Volumes: Allows standard volume types (e.g.,
configMap
,secret...
) but blockshostPath
(allowHostDirVolumePlugin: false
) - Capabilities:
- Drops
MKNOD
(blocks creating device files) - No additional capabilities granted (
allowedCapabilities: null
,defaultAddCapabilities: null
)
- Drops
- Privilege Escalation: Allowed (
allowPrivilegeEscalation: true
)
- Security Restrictions:
- Denies privileged containers (
allowPrivilegedContainer: false
) - Blocks host access:
- No host networking (
allowHostNetwork: false
) - No host PID/IPC sharing (
allowHostPID/IPC: false
) - No host ports (
allowHostPorts: false
)
- No host networking (
- SELinux: Enforces
MustRunAs
(requires SELinux context)
- Denies privileged containers (
- Assigned To:
system:cluster-admins
group (by default)- No regular users (
users: []
)
- Priority:
10
(higher priority than default SCCs likerestricted
). See the SCC prioritization section below. - Use Case:
- Legacy applications requiring root but no other host-level privileges.
- Safer alternative to
privileged
SCC when only UID flexibility is needed.
SCC Prioritization
So, how does OpenShift determine which Security Context Constraint (SCC) to apply to a pod?
OpenShift prioritizes Security Context Constraints (SCCs) to determine which SCC is applied to a pod during admission control. The prioritization process follows these steps:
- Highest Priority First: SCCs are sorted by their Priority field. A higher value takes precedence, and a nil (none) priority is treated as 0 (lowest). For example, an SCC with Priority: 10 is evaluated before one with Priority: 5.
- Most Restrictive to Least Restrictive: If multiple SCCs have the same priority, they are then sorted from most restrictive to least restrictive based on their constraints (e.g., an SCC requiring a specific RunAsUser is more restrictive than one allowing RunAsAny).
- Name-Based Sorting: If both priority and restrictiveness are equal, SCCs are sorted alphabetically by name.
The admission controller retrieves all SCCs available to a pod based on the user, service account, and associated groups. It then evaluates them in the above order to find the first SCC that matches the pod’s requested security context (e.g., runAsUser, fsGroup, capabilities). If no SCC matches, the pod is rejected.
For example, the default anyuid SCC, often granted to cluster administrators, has a higher priority (e.g., Priority: 10) to allow running pods as any user without specifying runAsUser. Custom SCCs should use the Priority field to ensure predictable ordering, and modifying default SCCs is discouraged to avoid issues during upgrades
How Does OpenShift Use SCCs to Enforce Pod Security Policies?
So, how does SCCs enforce Pod security policies exactly?
- API Request: When a request to create a pod, via Deployment, ReplicaSet, or via oc create using a manifest file, is submitted to the API server, the system begins processing the request through a series of security and validation checks.
- Authentication: The API server authenticates the requester using the configured authentication plugins such as OAuth, X.509 certificates, or service account tokens to verify their identity. If authentication fails, the request is immediately rejected.
- RBAC Authorization: After successful authentication, the API server verifies if the authenticated entity has the necessary RBAC permissions to create pods in the specified namespace by checking against the defined Role and ClusterRole bindings. If the requester lacks appropriate permissions, the request is rejected with a permission error.
- Schema Validation: Upon passing authorization, the API server validates the pod specification against the Kubernetes schema to ensure the manifest is well-formed and includes all the required fields according to the API version. Malformed requests are rejected at this stage.
- Mutating Admission Controllers: Various mutating admission controllers process the request in sequence, potentially modifying the pod specification by adding default values, injecting sidecars, or setting resource limits. Some mutating controllers may reject the request if it violates certain policies.
- SCC Admission Control: The SCC admission controller then processes the request with the following steps:
- SCC Prioritization and Evaluation: The controller retrieves all available SCCs and sorts them in descending order of priority, with higher numerical values considered first.
- Permission Check: The controller filters the SCCs to identify which ones are available to the pod’s service account, user, or groups based on the
users
andgroups
fields in each SCC. - Requirements Match: For each available SCC, the controller evaluates whether the security context requirements specified in the pod definition are permitted by the SCC constraints.
- Priority-Based Selection: The controller selects the highest-priority SCC that satisfies all requirements, with priority determined by the numerical
priority
field in each SCC. - Pod Mutation: If the selected SCC requires modifications to the pod specification (such as adding SELinux contexts or dropping capabilities), the controller updates the pod definition accordingly.
- SCC Annotation: The controller annotates the pod with
openshift.io/scc: <scc-name>
to indicate which SCC was applied, providing an audit trail for security compliance. - Rejection: If no valid SCC can be applied to the pod, the SCC admission controller rejects the request with a detailed error explaining which security constraints were violated.
- Other Validating Admission Controllers: Additional validation checks are performed by other admission controllers, which may validate network policies, quota usage, or other cluster-specific requirements. Each controller may reject the request if its specific criteria are not met.
- Final Validation and Persistence: After successfully passing through all admission controllers, the API server performs a final validation of the modified pod specification before persisting it to etcd and making it available for scheduling.
Conclusion
Security Context Constraints (SCCs) are a critical component of OpenShift’s security model, enabling administrators to enforce fine-grained access controls over containerized workloads. By defining what pods can and cannot do, SCCs help strike a balance between application functionality and cluster security.
In our next guides, we will learn how to make SCCs available for use through service accounts as well as troubleshooting SCC-related errors.
Other Tutorials
Introduction to Role-Based Access Control (RBAC) in Kubernetes