---
title: Understanding and managing pod security admission
---

# Understanding and managing pod security admission {#understanding-and-managing-pod-security-admission}

You can configure pod security admission to enforce the Kubernetes pod security standards. You can apply this enforcement at both the global and namespace levels.

## About pod security admission {#security-context-constraints-psa-about_understanding-and-managing-pod-security-admission}

You can use pod security admission modes, such as `enforce`, `warn`, or `audit`, along with security profiles to restrict which pods run in your cluster. You can apply this control at both the global and namespace levels.

Globally, the `privileged` profile is enforced, and the `restricted` profile is used for warnings and audits.

You can also configure the pod security admission settings at the namespace level.

> [!IMPORTANT]
> Do not run workloads in or share access to default projects. Default projects are reserved for running core cluster components.
>
> The following default projects are considered highly privileged: `default`, `kube-public`, `kube-system`, `openshift`, `openshift-infra`, `openshift-node`, and other system-created projects that have the `openshift.io/run-level` label set to `0` or `1`. Functionality that relies on admission plugins, such as pod security admission, security context constraints, cluster resource quotas, and image reference resolution, does not work in highly privileged projects.

### Pod security admission modes {#psa-modes_understanding-and-managing-pod-security-admission}

You can configure the following pod security admission modes for a namespace:

**Pod security admission modes**

<table>
<thead>
<tr>
  <th>Mode</th>
  <th>Label</th>
  <th>Description</th>
</tr>
</thead>
<tbody>
<tr>
  <td><code>enforce</code></td>
  <td><code>pod-security.kubernetes.io/enforce</code></td>
  <td>Rejects a pod from admission if it does not comply with the set profile</td>
</tr>
<tr>
  <td><code>audit</code></td>
  <td><code>pod-security.kubernetes.io/audit</code></td>
  <td>Logs audit events if a pod does not comply with the set profile</td>
</tr>
<tr>
  <td><code>warn</code></td>
  <td><code>pod-security.kubernetes.io/warn</code></td>
  <td>Displays warnings if a pod does not comply with the set profile</td>
</tr>
</tbody>
</table>

### Pod security admission profiles {#psa-profiles_understanding-and-managing-pod-security-admission}

You can set each of the pod security admission modes to one of the following profiles:

**Pod security admission profiles**

<table>
<thead>
<tr>
  <th>Profile</th>
  <th>Description</th>
</tr>
</thead>
<tbody>
<tr>
  <td><code>privileged</code></td>
  <td>Least restrictive policy; allows for known privilege escalation</td>
</tr>
<tr>
  <td><code>baseline</code></td>
  <td>Minimally restrictive policy; prevents known privilege escalations</td>
</tr>
<tr>
  <td><code>restricted</code></td>
  <td>Most restrictive policy; follows current pod hardening best practices</td>
</tr>
</tbody>
</table>

### Privileged namespaces {#psa-privileged-namespaces_understanding-and-managing-pod-security-admission}

The following system namespaces are always set to the `privileged` pod security admission profile:

- `default`
- `kube-public`
- `kube-system`

You cannot change the pod security profile for these privileged namespaces.

```yaml {title="Example privileged namespace configuration"}
apiVersion: v1
kind: Namespace
metadata:
  labels:
    openshift.io/cluster-monitoring: "true"
    pod-security.kubernetes.io/enforce: privileged
    pod-security.kubernetes.io/audit: privileged
    pod-security.kubernetes.io/warn: privileged
  name: "<mig_namespace>"
# ...
```

### Pod security admission and security context constraints {#security-context-constraints-psa-coexistence_understanding-and-managing-pod-security-admission}

Pod security admission and security context constraints operate as two independent mechanisms in OpenShift Container Platform. You must ensure your workloads comply with both to avoid unexpected pod rejections.

The two controllers independently enforce security policies by using the following processes:

1. The security context constraint controller may mutate some security context fields per the pod’s assigned SCC. For example, if the seccomp profile is empty or not set and if the pod’s assigned SCC enforces `seccompProfiles` field to be `runtime/default`, the controller sets the default type to `RuntimeDefault`.
2. The security context constraint controller validates the pod’s security context against the matching SCC.
3. The pod security admission controller validates the pod’s security context against the pod security standard assigned to the namespace.

## About pod security admission synchronization {#security-context-constraints-psa-synchronization_understanding-and-managing-pod-security-admission}

Pod security admission `warn` and `audit` labels are automatically synchronized on your namespaces. This synchronization maps security context constraints to pod security profiles based on the service account permissions in each namespace.

The controller examines `ServiceAccount` object permissions to use security context constraints in each namespace. Security context constraints (SCCs) are mapped to pod security profiles based on their field values; the controller uses these translated profiles. Pod security admission `warn` and `audit` labels are set to the most privileged pod security profile in the namespace to prevent displaying warnings and logging audit events when pods are created.

Namespace labeling is based on consideration of namespace-local service account privileges.

Applying pods directly might use the SCC privileges of the user who runs the pod. However, user privileges are not considered during automatic labeling.

### Pod security admission synchronization namespace exclusions {#security-context-constraints-psa-sync-exclusions_understanding-and-managing-pod-security-admission}

If you use pod security admission synchronization, the system-created namespaces are permanently disabled from synchronization.

User-created `openshift-*` prefixed namespaces are also initially disabled, but you can enable synchronization on them later.

> [!IMPORTANT]
> If a pod security admission label (`pod-security.kubernetes.io/<mode>`) is manually modified from the automatically labeled value on a label-synchronized namespace, synchronization is disabled for that label.
>
> If necessary, you can enable synchronization again by using one of the following methods:
>
> - By removing the modified pod security admission label from the namespace
> - By setting the `security.openshift.io/scc.podSecurityLabelSync` label to `true`
>
>   If you force synchronization by adding this label, then any modified pod security admission labels will be overwritten.

#### Permanently disabled namespaces {#_permanently_disabled_namespaces}

Namespaces that are defined as part of the cluster payload have pod security admission synchronization disabled permanently. The following namespaces are permanently disabled:

- `default`
- `kube-node-lease`
- `kube-system`
- `kube-public`
- `openshift`
- All system-created namespaces that are prefixed with `openshift-` , except for `openshift-operators`

#### Initially disabled namespaces {#_initially_disabled_namespaces}

By default, all namespaces that have an `openshift-` prefix have pod security admission synchronization disabled initially. You can enable synchronization for user-created `openshift-*` namespaces and for the `openshift-operators` namespace.

> [!NOTE]
> You cannot enable synchronization for any system-created `openshift-*` namespaces, except for `openshift-operators`.

If an Operator is installed in a user-created `openshift-*` namespace, synchronization is enabled automatically after a cluster service version (CSV) is created in the namespace. The synchronized label is derived from the permissions of the service accounts in the namespace.

## Controlling pod security admission synchronization {#security-context-constraints-psa-opting_understanding-and-managing-pod-security-admission}

To customize which namespaces have their pod security admission labels automatically updated, you can enable or disable synchronization for most namespaces.

> [!IMPORTANT]
> You cannot enable pod security admission synchronization on some system-created namespaces. For more information, see *Pod security admission synchronization namespace exclusions*.

**Procedure**

- For each namespace that you want to configure, set a value for the `security.openshift.io/scc.podSecurityLabelSync` label:

  - To disable pod security admission label synchronization in a namespace, set the value of the `security.openshift.io/scc.podSecurityLabelSync` label to `false`.

    Run the following command:

    ```terminal
    $ oc label namespace <namespace> security.openshift.io/scc.podSecurityLabelSync=false
    ```
  - To enable pod security admission label synchronization in a namespace, set the value of the `security.openshift.io/scc.podSecurityLabelSync` label to `true`.

    Run the following command:

    ```terminal
    $ oc label namespace <namespace> security.openshift.io/scc.podSecurityLabelSync=true
    ```

  > [!NOTE]
  > Use the `--overwrite` flag to overwrite the value if this label is already set on the namespace.

**Additional resources**
{._additional-resources}

- [Pod security admission synchronization namespace exclusions](/openshift-docs-markdown/authentication/understanding-and-managing-pod-security-admission#security-context-constraints-psa-sync-exclusions_understanding-and-managing-pod-security-admission)

## Configuring pod security admission for a namespace {#security-context-constraints-psa-label_understanding-and-managing-pod-security-admission}

You can configure pod security admission modes and profiles at the namespace level to control the security standards that pods must meet in a specific namespace.

**Procedure**

- For each pod security admission mode that you want to set on a namespace, run the following command:

  ```terminal
  $ oc label namespace <namespace> \
      pod-security.kubernetes.io/<mode>=<profile> \
      --overwrite
  ```

  where:

  `<namespace>`
  :   Specifies the namespace to configure.

  `<mode>`
  :   Specifies the pod security admission mode. Valid values are `enforce`, `warn`, or `audit`.

  `<profile>`
  :   Specifies the pod security profile. Valid values are `restricted`, `baseline`, or `privileged`.

## About pod security admission alerts {#security-context-constraints-psa-rectifying_understanding-and-managing-pod-security-admission}

If your pods violate the configured pod security standards, you receive a `PodSecurityViolation` alert. This alert persists for one day so that you can investigate and resolve compliance issues.

You can view the Kubernetes API server audit logs to investigate alerts that were triggered. As an example, a workload is likely to fail admission if global enforcement is set to the `restricted` pod security level.

To identify pod security admission violation audit events, see "Audit annotations" in the Kubernetes documentation.

### Identifying pod security violations {#security-context-constraints-psa-alert-eval_understanding-and-managing-pod-security-admission}

To identify which workloads are causing pod security violations, you can review the Kubernetes API server audit logs by using the `must-gather` tool.

The `PodSecurityViolation` alert does not provide details on which workloads are causing pod security violations.

**Prerequisites**

- You have installed `jq`.
- You have access to the cluster as a user with the `cluster-admin` role.

**Procedure**

1. To gather the audit logs, enter the following command:

   ```terminal
   $ oc adm must-gather -- /usr/bin/gather_audit_logs
   ```
2. To output the affected workload details, enter the following command:

   ```terminal
   $ zgrep -h pod-security.kubernetes.io/audit-violations must-gather.local.<archive_id>/<image_digest_id>/audit_logs/kube-apiserver/*log.gz \
     | jq -r 'select((.annotations["pod-security.kubernetes.io/audit-violations"] != null) and (.objectRef.resource=="pods")) | .objectRef.namespace + " " + .objectRef.name' \
     | sort | uniq -c
   ```

   Replace `<archive_id>` and `<image_digest_id>` with the actual path names.

   ```text {title="Example output"}
   1 test-namespace my-pod
   ```

**Additional resources**
{._additional-resources}

- [Pod Security Admission (Kubernetes documentation)](https://kubernetes.io/docs/concepts/security/pod-security-admission)
- [Pod Security Standards (Kubernetes documentation)](https://kubernetes.io/docs/concepts/security/pod-security-standards/)
- [Audit Annotations (Kubernetes documentation)](https://kubernetes.io/docs/reference/labels-annotations-taints/audit-annotations/#pod-security-kubernetes-io-audit-violations)
- [Viewing audit logs](/openshift-docs-markdown/security/audit-log-view#nodes-nodes-audit-log-basic-viewing_audit-log-view)
- [Managing security context constraints](/openshift-docs-markdown/authentication/managing-security-context-constraints#managing-pod-security-policies)
