Merge pull request #28903 from sejr/feat/podsecurity
Add Pod Security Standards documentation
This commit is contained in:
commit
f92e3ec2ba
|
|
@ -2,8 +2,10 @@
|
|||
reviewers:
|
||||
- zparnold
|
||||
title: Overview of Cloud Native Security
|
||||
description: >
|
||||
A model for thinking about Kubernetes security in the context of Cloud Native security.
|
||||
content_type: concept
|
||||
weight: 10
|
||||
weight: 1
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,129 @@
|
|||
---
|
||||
reviewers:
|
||||
- tallclair
|
||||
- liggitt
|
||||
title: Pod Security Admission
|
||||
description: >
|
||||
An overview of the Pod Security Admission Controller, which can enforce the Pod Security
|
||||
Standards.
|
||||
content_type: concept
|
||||
weight: 20
|
||||
min-kubernetes-server-version: v1.22
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
{{< feature-state for_k8s_version="v1.22" state="alpha" >}}
|
||||
|
||||
The Kubernetes [Pod Security Standards](/docs/concepts/security/pod-security-standards/) define
|
||||
different isolation levels for Pods. These standards let you define how you want to restrict the
|
||||
behavior of pods in a clear, consistent fashion.
|
||||
|
||||
As an Alpha feature, Kubernetes offers a built-in _Pod Security_ admission plugin, the successor
|
||||
to [PodSecurityPolicies](/docs/concepts/policy/pod-security-policy/). Pod security restrictions
|
||||
are applied at the {{< glossary_tooltip text="namespace" term_id="namespace" >}} level when pods
|
||||
are created.
|
||||
|
||||
{{< note >}}
|
||||
The PodSecurityPolicy API is deprecated and will be
|
||||
[removed](/docs/reference/using-api/deprecation-guide/#v1-25) from Kubernetes in v1.25.
|
||||
{{< /note >}}
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Enabling the Alpha feature
|
||||
|
||||
Setting pod security controls by namespace is an alpha feature. You must enable the `PodSecurity`
|
||||
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) in order to use it.
|
||||
|
||||
```shell
|
||||
--feature-gates="...,PodSecurity=true"
|
||||
```
|
||||
|
||||
## Pod Security Admission configuration for pods
|
||||
|
||||
Different policy levels (e.g. `baseline`, `restricted`) have different requirements for
|
||||
[Security Context](/docs/tasks/configure-pod-container/security-context/) objects and other related
|
||||
fields. Check out the [Pod Security Standards](/docs/concepts/security/pod-security-standards) page
|
||||
for an in-depth look at those requirements.
|
||||
|
||||
## Pod Security Admission labels for namespaces
|
||||
|
||||
Provided that you have enabled this feature, you can configure namespaces to define the admission
|
||||
control mode you want to use for pod security in each namespace. Kubernetes defines a set of
|
||||
{{< glossary_tooltip term_id="label" text="labels" >}} that you can set to define which of the
|
||||
predefined Pod Security Standard levels you want to use for a namespace. The label you select
|
||||
defines what action the {{< glossary_tooltip text="control plane" term_id="control-plane" >}}
|
||||
takes if a potential violation is detected:
|
||||
|
||||
{{< table caption="Pod Security Admission modes" >}}
|
||||
Mode | Description
|
||||
:---------|:------------
|
||||
**`enforce`** | Policy violations will cause the pod to be rejected.
|
||||
**`audit`** | Policy violations will trigger the addition of an audit annotation, but are otherwise allowed.
|
||||
**`warn`** | Policy violations will trigger a user-facing warning, but are otherwise allowed.
|
||||
{{< /table >}}
|
||||
|
||||
For each mode, there are two labels that you can use:
|
||||
|
||||
```yaml
|
||||
# The per-mode level label indicates which policy level to apply for the mode.
|
||||
#
|
||||
# MODE must be one of `enforce`, `audit`, or `warn`.
|
||||
# LEVEL must be one of `privileged`, `baseline`, or `restricted`.
|
||||
pod-security.kubernetes.io/<MODE>: <LEVEL>
|
||||
|
||||
# Optional: per-mode version label that can be used to pin the policy to the
|
||||
# version that shipped with a given Kubernetes minor version (e.g. v{{< skew latestVersion >}}).
|
||||
#
|
||||
# MODE must be one of `enforce`, `audit`, or `warn`.
|
||||
# VERSION must be a valid Kubernetes version label.
|
||||
pod-security.kubernetes.io/<MODE>-version: <VERSION>
|
||||
```
|
||||
|
||||
Check out [Enforce Pod Security Standards with Namespace Labels](/docs/tasks/configure-pod-container/enforce-standards-namespace-labels) to see example usage.
|
||||
|
||||
## Exemptions
|
||||
|
||||
You can define _exemptions_ from pod security enforcement in order allow the creation of pods that
|
||||
would have otherwise been prohibited due to the policy associated with a given namespace.
|
||||
Exemptions can be statically configured in the
|
||||
[Admission Controller configuration](#configuring-the-admission-controller).
|
||||
|
||||
Exemptions must be explicitly enumerated, and do not support indirection such as label or group
|
||||
selectors. Requests meeting exemption criteria are _ignored_ by the Admission Controller (all
|
||||
`enforce`, `audit` and `warn` behaviors), except to record an audit annotation. Exemption
|
||||
dimensions include:
|
||||
|
||||
- **Usernames:** requests from users with an exempt authenticated (or impersonated) username are
|
||||
ignored.
|
||||
- **RuntimeClassNames:** pods and templated pods specifying an exempt runtime class name are
|
||||
ignored.
|
||||
- **Namespaces:** pods and templated pods in an exempt namespace are ignored.
|
||||
|
||||
The username exemption is special in that the creating user is not persisted on the Pod object,
|
||||
and the Pod may be modified by different non-exempt users in the future. Use cases for username
|
||||
exemptions include:
|
||||
|
||||
- Trusted {{< glossary_tooltip term_id="controller" text="controllers" >}} that create pods.
|
||||
- Usernames that represent break-glass operations roles, for example for debugging workloads
|
||||
in a namespace that has restrictions configured. This mechanism only works with a username
|
||||
match; you cannot grant exemptions based on group membership.
|
||||
|
||||
Updates to the following pod fields are exempt from policy checks, meaning that if a pod update request only changes these fields, it will not be denied even if the pod is in violation of the current policy level:
|
||||
|
||||
- Any metadata updates EXCEPT changes to the seccomp or apparmor annotations:
|
||||
- `seccomp.security.alpha.kubernetes.io/pod` (deprecated)
|
||||
- `container.seccomp.security.alpha.kubernetes.io/*` (deprecated)
|
||||
- `container.apparmor.security.beta.kubernetes.io/*`
|
||||
- Valid updates to `.spec.activeDeadlineSeconds`
|
||||
- Valid updates to `.spec.tolerations`
|
||||
- Valid updates to Pod resources
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
- [Pod Security Standards](/docs/concepts/security/pod-security-standards)
|
||||
- [Enforcing Pod Security Standards](/docs/setup/best-practices/enforcing-pod-security-standards)
|
||||
- [Enforce Pod Security Standards by Configuring the Built-in Admission Controller](/docs/tasks/configure-pod-container/enforce-standards-admission-controller)
|
||||
- [Enforce Pod Security Standards with Namespace Labels](/docs/tasks/configure-pod-container/enforce-standards-namespace-labels)
|
||||
- [Migrating from PodSecurityPolicy to PodSecurity](/docs/tasks/secure-pods/migrate-from-psp)
|
||||
|
|
@ -2,59 +2,52 @@
|
|||
reviewers:
|
||||
- tallclair
|
||||
title: Pod Security Standards
|
||||
description: >
|
||||
A detailed look at the different policy levels defined in the Pod Security Standards.
|
||||
content_type: concept
|
||||
weight: 10
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
Security settings for Pods are typically applied by using [security
|
||||
contexts](/docs/tasks/configure-pod-container/security-context/). Security Contexts allow for the
|
||||
definition of privilege and access controls on a per-Pod basis.
|
||||
|
||||
The enforcement and policy-based definition of cluster requirements of security contexts has
|
||||
previously been achieved using [Pod Security Policy](/docs/concepts/policy/pod-security-policy/). A
|
||||
_Pod Security Policy_ is a cluster-level resource that controls security sensitive aspects of the
|
||||
Pod specification.
|
||||
|
||||
However, numerous means of policy enforcement have arisen that augment or replace the use of
|
||||
PodSecurityPolicy. The intent of this page is to detail recommended Pod security profiles, decoupled
|
||||
from any specific instantiation.
|
||||
|
||||
The Pod Security Standards define three different _policies_ to broadly cover the security
|
||||
spectrum. These policies are _cumulative_ and range from highly-permissive to highly-restrictive.
|
||||
This guide outlines the requirements of each policy.
|
||||
|
||||
| Profile | Description |
|
||||
| ------ | ----------- |
|
||||
| <strong style="white-space: nowrap">Privileged</strong> | Unrestricted policy, providing the widest possible level of permissions. This policy allows for known privilege escalations. |
|
||||
| <strong style="white-space: nowrap">Baseline</strong> | Minimally restrictive policy which prevents known privilege escalations. Allows the default (minimally specified) Pod configuration. |
|
||||
| <strong style="white-space: nowrap">Restricted</strong> | Heavily restricted policy, following current Pod hardening best practices. |
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Policy Types
|
||||
|
||||
There is an immediate need for base policy definitions to broadly cover the security spectrum. These
|
||||
should range from highly restricted to highly flexible:
|
||||
|
||||
- **_Privileged_** - Unrestricted policy, providing the widest possible level of permissions. This
|
||||
policy allows for known privilege escalations.
|
||||
- **_Baseline_** - Minimally restrictive policy while preventing known privilege
|
||||
escalations. Allows the default (minimally specified) Pod configuration.
|
||||
- **_Restricted_** - Heavily restricted policy, following current Pod hardening best practices.
|
||||
|
||||
## Policies
|
||||
## Profile Details
|
||||
|
||||
### Privileged
|
||||
|
||||
The Privileged policy is purposely-open, and entirely unrestricted. This type of policy is typically
|
||||
aimed at system- and infrastructure-level workloads managed by privileged, trusted users.
|
||||
**The _Privileged_ policy is purposely-open, and entirely unrestricted.** This type of policy is
|
||||
typically aimed at system- and infrastructure-level workloads managed by privileged, trusted users.
|
||||
|
||||
The privileged policy is defined by an absence of restrictions. For allow-by-default enforcement
|
||||
mechanisms (such as gatekeeper), the privileged profile may be an absence of applied constraints
|
||||
rather than an instantiated policy. In contrast, for a deny-by-default mechanism (such as Pod
|
||||
Security Policy) the privileged policy should enable all controls (disable all restrictions).
|
||||
The Privileged policy is defined by an absence of restrictions. For allow-by-default enforcement
|
||||
mechanisms (such as gatekeeper), the Privileged policy may be an absence of applied constraints
|
||||
rather than an instantiated profile. In contrast, for a deny-by-default mechanism (such as Pod
|
||||
Security Policy) the Privileged policy should enable all controls (disable all restrictions).
|
||||
|
||||
### Baseline
|
||||
|
||||
The Baseline policy is aimed at ease of adoption for common containerized workloads while
|
||||
preventing known privilege escalations. This policy is targeted at application operators and
|
||||
**The _Baseline_ policy is aimed at ease of adoption for common containerized workloads while
|
||||
preventing known privilege escalations.** This policy is targeted at application operators and
|
||||
developers of non-critical applications. The following listed controls should be
|
||||
enforced/disallowed:
|
||||
|
||||
{{< note >}}
|
||||
In this table, wildcards (`*`) indicate all elements in a list. For example,
|
||||
`spec.containers[*].securityContext` refers to the Security Context object for _all defined
|
||||
containers_. If any of the listed containers fails to meet the requirements, the entire pod will
|
||||
fail validation.
|
||||
{{< /note >}}
|
||||
|
||||
<table>
|
||||
<caption style="display:none">Baseline policy specification</caption>
|
||||
<tbody>
|
||||
|
|
@ -63,112 +56,205 @@ enforced/disallowed:
|
|||
<td><strong>Policy</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Host Namespaces</td>
|
||||
<td style="white-space: nowrap">Host Namespaces</td>
|
||||
<td>
|
||||
Sharing the host namespaces must be disallowed.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.hostNetwork<br>
|
||||
spec.hostPID<br>
|
||||
spec.hostIPC<br>
|
||||
<br><b>Allowed Values:</b> false<br>
|
||||
<p>Sharing the host namespaces must be disallowed.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.hostNetwork</code></li>
|
||||
<li><code>spec.hostPID</code></li>
|
||||
<li><code>spec.hostIPC</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil</li>
|
||||
<li><code>false</code></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Privileged Containers</td>
|
||||
<td style="white-space: nowrap">Privileged Containers</td>
|
||||
<td>
|
||||
Privileged Pods disable most security mechanisms and must be disallowed.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.containers[*].securityContext.privileged<br>
|
||||
spec.initContainers[*].securityContext.privileged<br>
|
||||
<br><b>Allowed Values:</b> false, undefined/nil<br>
|
||||
<p>Privileged Pods disable most security mechanisms and must be disallowed.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.containers[*].securityContext.privileged</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.privileged</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.privileged</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil</li>
|
||||
<li><code>false</code></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Capabilities</td>
|
||||
<td style="white-space: nowrap">Capabilities</td>
|
||||
<td>
|
||||
Adding <tt>NET_RAW</tt> or capabilities beyond the <a href="https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities">default set</a> must be disallowed.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.containers[*].securityContext.capabilities.add<br>
|
||||
spec.initContainers[*].securityContext.capabilities.add<br>
|
||||
<br><b>Allowed Values:</b> empty (or restricted to a known list)<br>
|
||||
<p>Adding additional capabilities beyond those listed below must be disallowed.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.containers[*].securityContext.capabilities.add</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.capabilities.add</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.capabilities.add</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil</li>
|
||||
<li><code>AUDIT_WRITE</code></li>
|
||||
<li><code>CHOWN</code></li>
|
||||
<li><code>DAC_OVERRIDE</code></li>
|
||||
<li><code>FOWNER</code></li>
|
||||
<li><code>FSETID</code></li>
|
||||
<li><code>KILL</code></li>
|
||||
<li><code>MKNOD</code></li>
|
||||
<li><code>NET_BIND_SERVICE</code></li>
|
||||
<li><code>SETFCAP</code></li>
|
||||
<li><code>SETGID</code></li>
|
||||
<li><code>SETPCAP</code></li>
|
||||
<li><code>SETUID</code></li>
|
||||
<li><code>SYS_CHROOT</code></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HostPath Volumes</td>
|
||||
<td style="white-space: nowrap">HostPath Volumes</td>
|
||||
<td>
|
||||
HostPath volumes must be forbidden.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.volumes[*].hostPath<br>
|
||||
<br><b>Allowed Values:</b> undefined/nil<br>
|
||||
<p>HostPath volumes must be forbidden.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.volumes[*].hostPath</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Host Ports</td>
|
||||
<td style="white-space: nowrap">Host Ports</td>
|
||||
<td>
|
||||
HostPorts should be disallowed, or at minimum restricted to a known list.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.containers[*].ports[*].hostPort<br>
|
||||
spec.initContainers[*].ports[*].hostPort<br>
|
||||
<br><b>Allowed Values:</b> 0, undefined (or restricted to a known list)<br>
|
||||
<p>HostPorts should be disallowed, or at minimum restricted to a known list.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.containers[*].ports[*].hostPort</code></li>
|
||||
<li><code>spec.initContainers[*].ports[*].hostPort</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].ports[*].hostPort</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil</li>
|
||||
<li>Known list</li>
|
||||
<li><code>0</code></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AppArmor</td>
|
||||
<td style="white-space: nowrap">AppArmor</td>
|
||||
<td>
|
||||
On supported hosts, the 'runtime/default' AppArmor profile is applied by default.
|
||||
The baseline policy should prevent overriding or disabling the default AppArmor
|
||||
profile, or restrict overrides to an allowed set of profiles.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
metadata.annotations['container.apparmor.security.beta.kubernetes.io/*']<br>
|
||||
<br><b>Allowed Values:</b> 'runtime/default', undefined<br>
|
||||
<p>On supported hosts, the <code>runtime/default</code> AppArmor profile is applied by default. The baseline policy should prevent overriding or disabling the default AppArmor profile, or restrict overrides to an allowed set of profiles.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>metadata.annotations["container.apparmor.security.beta.kubernetes.io/*"]</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil</li>
|
||||
<li><code>runtime/default</code></li>
|
||||
<li><code>localhost/*</code></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SELinux</td>
|
||||
<td style="white-space: nowrap">SELinux</td>
|
||||
<td>
|
||||
Setting the SELinux type is restricted, and setting a custom SELinux user or role option is forbidden.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.securityContext.seLinuxOptions.type<br>
|
||||
spec.containers[*].securityContext.seLinuxOptions.type<br>
|
||||
spec.initContainers[*].securityContext.seLinuxOptions.type<br>
|
||||
<br><b>Allowed Values:</b><br>
|
||||
undefined/empty<br>
|
||||
container_t<br>
|
||||
container_init_t<br>
|
||||
container_kvm_t<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.securityContext.seLinuxOptions.user<br>
|
||||
spec.containers[*].securityContext.seLinuxOptions.user<br>
|
||||
spec.initContainers[*].securityContext.seLinuxOptions.user<br>
|
||||
spec.securityContext.seLinuxOptions.role<br>
|
||||
spec.containers[*].securityContext.seLinuxOptions.role<br>
|
||||
spec.initContainers[*].securityContext.seLinuxOptions.role<br>
|
||||
<br><b>Allowed Values:</b> undefined/empty<br>
|
||||
<p>Setting the SELinux type is restricted, and setting a custom SELinux user or role option is forbidden.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.securityContext.seLinuxOptions.type</code></li>
|
||||
<li><code>spec.containers[*].securityContext.seLinuxOptions.type</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.seLinuxOptions.type</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.seLinuxOptions.type</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/""</li>
|
||||
<li><code>container_t</code></li>
|
||||
<li><code>container_init_t</code></li>
|
||||
<li><code>container_kvm_t</code></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.securityContext.seLinuxOptions.user</code></li>
|
||||
<li><code>spec.containers[*].securityContext.seLinuxOptions.user</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.seLinuxOptions.user</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.seLinuxOptions.user</code></li>
|
||||
<li><code>spec.securityContext.seLinuxOptions.role</code></li>
|
||||
<li><code>spec.containers[*].securityContext.seLinuxOptions.role</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.seLinuxOptions.role</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.seLinuxOptions.role</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/""</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>/proc Mount Type</td>
|
||||
<td style="white-space: nowrap"><code>/proc</code> Mount Type</td>
|
||||
<td>
|
||||
The default /proc masks are set up to reduce attack surface, and should be required.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.containers[*].securityContext.procMount<br>
|
||||
spec.initContainers[*].securityContext.procMount<br>
|
||||
<br><b>Allowed Values:</b> undefined/nil, 'Default'<br>
|
||||
<p>The default <code>/proc</code> masks are set up to reduce attack surface, and should be required.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.containers[*].securityContext.procMount</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.procMount</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.procMount</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil</li>
|
||||
<li><code>Default</code></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sysctls</td>
|
||||
<td>Seccomp</td>
|
||||
<td>
|
||||
<p>Seccomp profile must not be explicitly set to <code>Unconfined</code>.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.securityContext.seccompProfile.type</code></li>
|
||||
<li><code>spec.containers[*].securityContext.seccompProfile.type</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.seccompProfile.type</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.seccompProfile.type</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil</li>
|
||||
<li><code>RuntimeDefault</code></li>
|
||||
<li><code>Localhost</code></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap">Sysctls</td>
|
||||
<td>
|
||||
Sysctls can disable security mechanisms or affect all containers on a host, and should be disallowed except for an allowed "safe" subset.
|
||||
A sysctl is considered safe if it is namespaced in the container or the Pod, and it is isolated from other Pods or processes on the same Node.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.securityContext.sysctls<br>
|
||||
<br><b>Allowed Values:</b><br>
|
||||
kernel.shm_rmid_forced<br>
|
||||
net.ipv4.ip_local_port_range<br>
|
||||
net.ipv4.tcp_syncookies<br>
|
||||
net.ipv4.ping_group_range<br>
|
||||
undefined/empty<br>
|
||||
<p>Sysctls can disable security mechanisms or affect all containers on a host, and should be disallowed except for an allowed "safe" subset. A sysctl is considered safe if it is namespaced in the container or the Pod, and it is isolated from other Pods or processes on the same Node.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.securityContext.sysctls[*].name</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil</li>
|
||||
<li><code>kernel.shm_rmid_forced</code></li>
|
||||
<li><code>net.ipv4.ip_local_port_range</code></li>
|
||||
<li><code>net.ipv4.ip_unprivileged_port_start</code></li>
|
||||
<li><code>net.ipv4.tcp_syncookies</code></li>
|
||||
<li><code>net.ipv4.ping_group_range</code></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
@ -176,10 +262,17 @@ enforced/disallowed:
|
|||
|
||||
### Restricted
|
||||
|
||||
The Restricted policy is aimed at enforcing current Pod hardening best practices, at the expense of
|
||||
some compatibility. It is targeted at operators and developers of security-critical applications, as
|
||||
well as lower-trust users.The following listed controls should be enforced/disallowed:
|
||||
**The _Restricted_ policy is aimed at enforcing current Pod hardening best practices, at the
|
||||
expense of some compatibility.** It is targeted at operators and developers of security-critical
|
||||
applications, as well as lower-trust users. The following listed controls should be
|
||||
enforced/disallowed:
|
||||
|
||||
{{< note >}}
|
||||
In this table, wildcards (`*`) indicate all elements in a list. For example,
|
||||
`spec.containers[*].securityContext` refers to the Security Context object for _all defined
|
||||
containers_. If any of the listed containers fails to meet the requirements, the entire pod will
|
||||
fail validation.
|
||||
{{< /note >}}
|
||||
|
||||
<table>
|
||||
<caption style="display:none">Restricted policy specification</caption>
|
||||
|
|
@ -192,80 +285,149 @@ well as lower-trust users.The following listed controls should be enforced/disal
|
|||
<td colspan="2"><em>Everything from the baseline profile.</em></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Volume Types</td>
|
||||
<td style="white-space: nowrap">Volume Types</td>
|
||||
<td>
|
||||
In addition to restricting HostPath volumes, the restricted profile limits usage of non-ephemeral volume types to those defined through PersistentVolumes.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.volumes[*].hostPath<br>
|
||||
spec.volumes[*].gcePersistentDisk<br>
|
||||
spec.volumes[*].awsElasticBlockStore<br>
|
||||
spec.volumes[*].gitRepo<br>
|
||||
spec.volumes[*].nfs<br>
|
||||
spec.volumes[*].iscsi<br>
|
||||
spec.volumes[*].glusterfs<br>
|
||||
spec.volumes[*].rbd<br>
|
||||
spec.volumes[*].flexVolume<br>
|
||||
spec.volumes[*].cinder<br>
|
||||
spec.volumes[*].cephFS<br>
|
||||
spec.volumes[*].flocker<br>
|
||||
spec.volumes[*].fc<br>
|
||||
spec.volumes[*].azureFile<br>
|
||||
spec.volumes[*].vsphereVolume<br>
|
||||
spec.volumes[*].quobyte<br>
|
||||
spec.volumes[*].azureDisk<br>
|
||||
spec.volumes[*].portworxVolume<br>
|
||||
spec.volumes[*].scaleIO<br>
|
||||
spec.volumes[*].storageos<br>
|
||||
<br><b>Allowed Values:</b> undefined/nil<br>
|
||||
<p>In addition to restricting HostPath volumes, the restricted policy limits usage of non-core volume types to those defined through PersistentVolumes.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.volumes[*].hostPath</code></li>
|
||||
<li><code>spec.volumes[*].gcePersistentDisk</code></li>
|
||||
<li><code>spec.volumes[*].awsElasticBlockStore</code></li>
|
||||
<li><code>spec.volumes[*].gitRepo</code></li>
|
||||
<li><code>spec.volumes[*].nfs</code></li>
|
||||
<li><code>spec.volumes[*].iscsi</code></li>
|
||||
<li><code>spec.volumes[*].glusterfs</code></li>
|
||||
<li><code>spec.volumes[*].rbd</code></li>
|
||||
<li><code>spec.volumes[*].flexVolume</code></li>
|
||||
<li><code>spec.volumes[*].cinder</code></li>
|
||||
<li><code>spec.volumes[*].cephfs</code></li>
|
||||
<li><code>spec.volumes[*].flocker</code></li>
|
||||
<li><code>spec.volumes[*].fc</code></li>
|
||||
<li><code>spec.volumes[*].azureFile</code></li>
|
||||
<li><code>spec.volumes[*].vsphereVolume</code></li>
|
||||
<li><code>spec.volumes[*].quobyte</code></li>
|
||||
<li><code>spec.volumes[*].azureDisk</code></li>
|
||||
<li><code>spec.volumes[*].portworxVolume</code></li>
|
||||
<li><code>spec.volumes[*].scaleIO</code></li>
|
||||
<li><code>spec.volumes[*].storageos</code></li>
|
||||
<li><code>spec.volumes[*].photonPersistentDisk</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Privilege Escalation</td>
|
||||
<td style="white-space: nowrap">Privilege Escalation (v1.8+)</td>
|
||||
<td>
|
||||
Privilege escalation (such as via set-user-ID or set-group-ID file mode) should not be allowed.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.containers[*].securityContext.allowPrivilegeEscalation<br>
|
||||
spec.initContainers[*].securityContext.allowPrivilegeEscalation<br>
|
||||
<br><b>Allowed Values:</b> false<br>
|
||||
<p>Privilege escalation (such as via set-user-ID or set-group-ID file mode) should not be allowed.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.containers[*].securityContext.allowPrivilegeEscalation</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.allowPrivilegeEscalation</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.allowPrivilegeEscalation</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li><code>false</code></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Running as Non-root</td>
|
||||
<td style="white-space: nowrap">Running as Non-root</td>
|
||||
<td>
|
||||
Containers must be required to run as non-root users.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.securityContext.runAsNonRoot<br>
|
||||
spec.containers[*].securityContext.runAsNonRoot<br>
|
||||
spec.initContainers[*].securityContext.runAsNonRoot<br>
|
||||
<br><b>Allowed Values:</b> true<br>
|
||||
<p>Containers must be required to run as non-root users.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.securityContext.runAsNonRoot</code></li>
|
||||
<li><code>spec.containers[*].securityContext.runAsNonRoot</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.runAsNonRoot</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.runAsNonRoot</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li><code>true</code></li>
|
||||
</ul>
|
||||
<small>
|
||||
The container fields may be undefined/<code>nil</code> if the pod-level
|
||||
<code>spec.securityContext.runAsNonRoot</code> is set to <code>true</code>.
|
||||
</small>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Non-root groups <em>(optional)</em></td>
|
||||
<td style="white-space: nowrap">Non-root groups <em>(optional)</em></td>
|
||||
<td>
|
||||
Containers should be forbidden from running with a root primary or supplementary GID.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.securityContext.runAsGroup<br>
|
||||
spec.securityContext.supplementalGroups[*]<br>
|
||||
spec.securityContext.fsGroup<br>
|
||||
spec.containers[*].securityContext.runAsGroup<br>
|
||||
spec.initContainers[*].securityContext.runAsGroup<br>
|
||||
<br><b>Allowed Values:</b><br>
|
||||
non-zero<br>
|
||||
undefined / nil (except for `*.runAsGroup`)<br>
|
||||
<p>Containers should be forbidden from running with a root primary or supplementary GID.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.securityContext.runAsGroup</code></li>
|
||||
<li><code>spec.securityContext.supplementalGroups[*]</code></li>
|
||||
<li><code>spec.securityContext.fsGroup</code></li>
|
||||
<li><code>spec.containers[*].securityContext.runAsGroup</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.runAsGroup</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.runAsGroup</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil (except for <code>*.runAsGroup</code>)</li>
|
||||
<li>Non-zero</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Seccomp</td>
|
||||
<td style="white-space: nowrap">Seccomp (v1.19+)</td>
|
||||
<td>
|
||||
<p>Seccomp profile must be explicitly set to one of the allowed values. Both the <code>Unconfined</code> profile and the <em>absence</em> of a profile are prohibited.</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.securityContext.seccompProfile.type</code></li>
|
||||
<li><code>spec.containers[*].securityContext.seccompProfile.type</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.seccompProfile.type</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.seccompProfile.type</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li><code>RuntimeDefault</code></li>
|
||||
<li><code>Localhost</code></li>
|
||||
</ul>
|
||||
<small>
|
||||
The container fields may be undefined/<code>nil</code> if the pod-level
|
||||
<code>spec.securityContext.seccompProfile.type</code> field is set appropriately.
|
||||
Conversely, the pod-level field may be undefined/<code>nil</code> if _all_ container-
|
||||
level fields are set.
|
||||
</small>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="white-space: nowrap">Capabilities (v1.22+)</td>
|
||||
<td>
|
||||
The RuntimeDefault seccomp profile must be required, or allow specific additional profiles.<br>
|
||||
<br><b>Restricted Fields:</b><br>
|
||||
spec.securityContext.seccompProfile.type<br>
|
||||
spec.containers[*].securityContext.seccompProfile<br>
|
||||
spec.initContainers[*].securityContext.seccompProfile<br>
|
||||
<br><b>Allowed Values:</b><br>
|
||||
'runtime/default'<br>
|
||||
undefined / nil<br>
|
||||
<p>
|
||||
Containers must drop <code>ALL</code> capabilities, and are only permitted to add back
|
||||
the <code>NET_BIND_SERVICE</code> capability.
|
||||
</p>
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.containers[*].securityContext.capabilities.drop</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.capabilities.drop</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.capabilities.drop</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Any list of capabilities that includes <code>ALL</code></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<p><strong>Restricted Fields</strong></p>
|
||||
<ul>
|
||||
<li><code>spec.containers[*].securityContext.capabilities.add</code></li>
|
||||
<li><code>spec.initContainers[*].securityContext.capabilities.add</code></li>
|
||||
<li><code>spec.ephemeralContainers[*].securityContext.capabilities.add</code></li>
|
||||
</ul>
|
||||
<p><strong>Allowed Values</strong></p>
|
||||
<ul>
|
||||
<li>Undefined/nil</li>
|
||||
<li><code>NET_BIND_SERVICE</code></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
@ -280,7 +442,13 @@ mechanism.
|
|||
As mechanisms mature, they will be defined below on a per-policy basis. The methods of enforcement
|
||||
of individual policies are not defined here.
|
||||
|
||||
[**PodSecurityPolicy**](/docs/concepts/policy/pod-security-policy/)
|
||||
[**Pod Security Admission Controller**](/docs/concepts/security/pod-security-admission/)
|
||||
|
||||
- {{< example file="security/podsecurity-privileged.yaml" >}}Privileged namespace{{< /example >}}
|
||||
- {{< example file="security/podsecurity-baseline.yaml" >}}Baseline namespace{{< /example >}}
|
||||
- {{< example file="security/podsecurity-restricted.yaml" >}}Restricted namespace{{< /example >}}
|
||||
|
||||
[**PodSecurityPolicy**](/docs/concepts/profile/pod-security-profile/) (Deprecated)
|
||||
|
||||
- {{< example file="policy/privileged-psp.yaml" >}}Privileged{{< /example >}}
|
||||
- {{< example file="policy/baseline-psp.yaml" >}}Baseline{{< /example >}}
|
||||
|
|
@ -298,26 +466,26 @@ policies in this space need to be defined on a case-by-case basis.
|
|||
|
||||
SIG Auth may reconsider this position in the future, should a clear need for other profiles arise.
|
||||
|
||||
### What's the difference between a security policy and a security context?
|
||||
### What's the difference between a security profile and a security context?
|
||||
|
||||
[Security Contexts](/docs/tasks/configure-pod-container/security-context/) configure Pods and
|
||||
Containers at runtime. Security contexts are defined as part of the Pod and container specifications
|
||||
in the Pod manifest, and represent parameters to the container runtime.
|
||||
|
||||
Security policies are control plane mechanisms to enforce specific settings in the Security Context,
|
||||
as well as other parameters outside the Security Context. As of February 2020, the current native
|
||||
solution for enforcing these security policies is [Pod Security
|
||||
Policy](/docs/concepts/policy/pod-security-policy/) - a mechanism for centrally enforcing security
|
||||
policy on Pods across a cluster. Other alternatives for enforcing security policy are being
|
||||
developed in the Kubernetes ecosystem, such as [OPA
|
||||
Gatekeeper](https://github.com/open-policy-agent/gatekeeper).
|
||||
Security profiles are control plane mechanisms to enforce specific settings in the Security Context,
|
||||
as well as other related parameters outside the Security Context. As of July 2021,
|
||||
[Pod Security Policies](/docs/concepts/profile/pod-security-profile/) are deprecated in favor of the
|
||||
built-in [Pod Security Admission Controller](/docs/concepts/security/pod-security-admission/).
|
||||
|
||||
Other alternatives for enforcing security profiles are being developed in the Kubernetes
|
||||
ecosystem, such as [OPA Gatekeeper](https://github.com/open-profile-agent/gatekeeper).
|
||||
|
||||
### What profiles should I apply to my Windows Pods?
|
||||
|
||||
Windows in Kubernetes has some limitations and differentiators from standard Linux-based
|
||||
workloads. Specifically, the Pod SecurityContext fields [have no effect on
|
||||
Windows](/docs/setup/production-environment/windows/intro-windows-in-kubernetes/#v1-podsecuritycontext). As
|
||||
such, no standardized Pod Security profiles currently exists.
|
||||
such, no standardized Pod Security profiles currently exist.
|
||||
|
||||
### What about sandboxed Pods?
|
||||
|
||||
|
|
@ -330,6 +498,6 @@ restrict privileged permissions is lessened when the workload is isolated from t
|
|||
kernel. This allows for workloads requiring heightened permissions to still be isolated.
|
||||
|
||||
Additionally, the protection of sandboxed workloads is highly dependent on the method of
|
||||
sandboxing. As such, no single recommended policy is recommended for all sandboxed workloads.
|
||||
sandboxing. As such, no single recommended profile is recommended for all sandboxed workloads.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -696,6 +696,18 @@ PodNodeSelector allows forcing pods to run on specifically labeled nodes. Also s
|
|||
admission plugin, which allows preventing pods from running on specifically tainted nodes.
|
||||
{{< /note >}}
|
||||
|
||||
### PodSecurity {#podsecurity}
|
||||
|
||||
{{< feature-state for_k8s_version="v1.22" state="alpha" >}}
|
||||
|
||||
This is the replacement for the deprecated [PodSecurityPolicy](#podsecuritypolicy) admission controller
|
||||
defined in the next section. This admission controller acts on creation and modification of the pod and
|
||||
determines if it should be admitted based on the requested security context and the
|
||||
[Pod Security Standards](/docs/concepts/security/pod-security-standards/).
|
||||
|
||||
See the [Pod Security Admission documentation](/docs/concepts/security/pod-security-admission/)
|
||||
for more information.
|
||||
|
||||
### PodSecurityPolicy {#podsecuritypolicy}
|
||||
|
||||
{{< feature-state for_k8s_version="v1.21" state="deprecated" >}}
|
||||
|
|
|
|||
|
|
@ -341,3 +341,87 @@ Sets this taint on a node to mark it as unusable, when kubelet is started with t
|
|||
Example: `node.cloudprovider.kubernetes.io/shutdown:NoSchedule`
|
||||
|
||||
If a Node is in a cloud provider specified shutdown state, the Node gets tainted accordingly with `node.cloudprovider.kubernetes.io/shutdown` and the taint effect of `NoSchedule`.
|
||||
|
||||
## pod-security.kubernetes.io/enforce
|
||||
|
||||
Example: `pod-security.kubernetes.io/enforce: baseline`
|
||||
|
||||
Used on: Namespace
|
||||
|
||||
Value **must** be one of `privileged`, `baseline`, or `restricted` which correspond to
|
||||
[Pod Security Standard](/docs/concepts/security/pod-security-standards) levels. Specifically,
|
||||
the `enforce` label _prohibits_ the creation of any Pod in the labeled Namespace which does not meet
|
||||
the requirements outlined in the indicated level.
|
||||
|
||||
See [Enforcing Pod Security at the Namespace Level](/docs/concepts/security/pod-security-admission)
|
||||
for more information.
|
||||
|
||||
## pod-security.kubernetes.io/enforce-version
|
||||
|
||||
Example: `pod-security.kubernetes.io/enforce-version: {{< skew latestVersion >}}`
|
||||
|
||||
Used on: Namespace
|
||||
|
||||
Value **must** be `latest` or a valid Kubernetes version in the format `v<MAJOR>.<MINOR>`.
|
||||
This determines the version of the [Pod Security Standard](/docs/concepts/security/pod-security-standards)
|
||||
policies to apply when validating a submitted Pod.
|
||||
|
||||
See [Enforcing Pod Security at the Namespace Level](/docs/concepts/security/pod-security-admission)
|
||||
for more information.
|
||||
|
||||
## pod-security.kubernetes.io/audit
|
||||
|
||||
Example: `pod-security.kubernetes.io/audit: baseline`
|
||||
|
||||
Used on: Namespace
|
||||
|
||||
Value **must** be one of `privileged`, `baseline`, or `restricted` which correspond to
|
||||
[Pod Security Standard](/docs/concepts/security/pod-security-standards) levels. Specifically,
|
||||
the `audit` label does not prevent the creation of a Pod in the labeled Namespace which does not meet
|
||||
the requirements outlined in the indicated level, but adds an audit annotation to that Pod.
|
||||
|
||||
See [Enforcing Pod Security at the Namespace Level](/docs/concepts/security/pod-security-admission)
|
||||
for more information.
|
||||
|
||||
## pod-security.kubernetes.io/audit-version
|
||||
|
||||
Example: `pod-security.kubernetes.io/audit-version: {{< skew latestVersion >}}`
|
||||
|
||||
Used on: Namespace
|
||||
|
||||
Value **must** be `latest` or a valid Kubernetes version in the format `v<MAJOR>.<MINOR>`.
|
||||
This determines the version of the [Pod Security Standard](/docs/concepts/security/pod-security-standards)
|
||||
policies to apply when validating a submitted Pod.
|
||||
|
||||
See [Enforcing Pod Security at the Namespace Level](/docs/concepts/security/pod-security-admission)
|
||||
for more information.
|
||||
|
||||
## pod-security.kubernetes.io/warn
|
||||
|
||||
Example: `pod-security.kubernetes.io/warn: baseline`
|
||||
|
||||
Used on: Namespace
|
||||
|
||||
Value **must** be one of `privileged`, `baseline`, or `restricted` which correspond to
|
||||
[Pod Security Standard](/docs/concepts/security/pod-security-standards) levels. Specifically,
|
||||
the `warn` label does not prevent the creation of a Pod in the labeled Namespace which does not meet the
|
||||
requirements outlined in the indicated level, but returns a warning to the user after doing so.
|
||||
Note that warnings are also displayed when creating or updating objects that contain Pod templates,
|
||||
such as Deployments, Jobs, StatefulSets, etc.
|
||||
|
||||
See [Enforcing Pod Security at the Namespace Level](/docs/concepts/security/pod-security-admission)
|
||||
for more information.
|
||||
|
||||
## pod-security.kubernetes.io/warn-version
|
||||
|
||||
Example: `pod-security.kubernetes.io/warn-version: {{< skew latestVersion >}}`
|
||||
|
||||
Used on: Namespace
|
||||
|
||||
Value **must** be `latest` or a valid Kubernetes version in the format `v<MAJOR>.<MINOR>`.
|
||||
This determines the version of the [Pod Security Standard](/docs/concepts/security/pod-security-standards)
|
||||
policies to apply when validating a submitted Pod. Note that warnings are also displayed when creating
|
||||
or updating objects that contain Pod templates, such as Deployments, Jobs, StatefulSets, etc.
|
||||
|
||||
See [Enforcing Pod Security at the Namespace Level](/docs/concepts/security/pod-security-admission)
|
||||
for more information.
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
reviewers:
|
||||
- tallclair
|
||||
- liggitt
|
||||
title: Enforcing Pod Security Standards
|
||||
weight: 40
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
This page provides an overview of best practices when it comes to enforcing
|
||||
[Pod Security Standards](/docs/concepts/security/pod-security-standards).
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Using the built-in Pod Security Admission Controller
|
||||
|
||||
{{< feature-state for_k8s_version="v1.22" state="alpha" >}}
|
||||
|
||||
The [Pod Security Admission Controller](/docs/reference/access-authn-authz/admission-controllers/#podsecurity)
|
||||
intends to replace the deprecated PodSecurityPolicies.
|
||||
|
||||
### Configure all cluster namespaces
|
||||
|
||||
Namespaces that lack any configuration at all should be considered significant gaps in your cluster
|
||||
security model. We recommend taking the time to analyze the types of workloads occurring in each
|
||||
namespace, and by referencing the Pod Security Standards, decide on an appropriate level for
|
||||
each of them. Unlabeled namespaces should only indicate that they've yet to be evaluated.
|
||||
|
||||
In the scenario that all workloads in all namespaces have the same security requirements,
|
||||
we provide an [example](/docs/concepts/security/pod-security-admission/#applying-to-all-namespaces)
|
||||
that illustrates how the PodSecurity labels can be applied in bulk.
|
||||
|
||||
### Embrace the principle of least privilege
|
||||
|
||||
In an ideal world, every pod in every namespace would meet the requirements of the `restricted`
|
||||
policy. However, this is not possible nor practical, as some workloads will require elevated
|
||||
privileges for legitimate reasons.
|
||||
|
||||
- Namespaces allowing `privileged` workloads should establish and enforce appropriate access controls.
|
||||
- For workloads running in those permissive namespaces, maintain documentation about their unique
|
||||
security requirements. If at all possible, consider how those requirements could be further
|
||||
constrained.
|
||||
|
||||
### Adopt a multi-mode strategy
|
||||
|
||||
The `audit` and `warn` modes of the Pod Security Standards admission controller make it easy to
|
||||
collect important security insights about your pods without breaking existing workloads.
|
||||
|
||||
It is good practice to enable these modes for all namespaces, setting them to the _desired_ level
|
||||
and version you would eventually like to `enforce`. The warnings and audit annotations generated in
|
||||
this phase can guide you toward that state. If you expect workload authors to make changes to fit
|
||||
within the desired level, enable the `warn` mode. If you expect to use audit logs to monitor/drive
|
||||
changes to fit within the desired level, enable the `audit` mode.
|
||||
|
||||
When you have the `enforce` mode set to your desired value, these modes can still be useful in a
|
||||
few different ways:
|
||||
|
||||
- By setting `warn` to the same level as `enforce`, clients will receive warnings when attempting
|
||||
to create Pods (or resources that have Pod templates) that do not pass validation. This will help
|
||||
them update those resources to become compliant.
|
||||
- In Namespaces that pin `enforce` to a specific non-latest version, setting the `audit` and `warn`
|
||||
modes to the same level as `enforce`, but to the `latest` version, gives visibility into settings
|
||||
that were allowed by previous versions but are not allowed per current best practices.
|
||||
|
||||
## Third-party alternatives
|
||||
|
||||
{{% thirdparty-content %}}
|
||||
|
||||
Other alternatives for enforcing security profiles are being developed in the Kubernetes
|
||||
ecosystem:
|
||||
|
||||
- [OPA Gatekeeper](https://github.com/open-policy-agent/gatekeeper).
|
||||
|
||||
The decision to go with a _built-in_ solution (e.g. PodSecurity admission controller) versus a
|
||||
third-party tool is entirely dependent on your own situation. When evaluating any solution,
|
||||
trust of your supply chain is crucial. Ultimately, using _any_ of the aforementioned approaches
|
||||
will be better than doing nothing.
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
title: Enforce Pod Security Standards by Configuring the Built-in Admission Controller
|
||||
reviewers:
|
||||
- tallclair
|
||||
- liggitt
|
||||
content_type: task
|
||||
min-kubernetes-server-version: v1.22
|
||||
---
|
||||
|
||||
As of v1.22, Kubernetes provides a built-in [admission controller](/docs/reference/access-authn-authz/admission-controllers/#podsecurity)
|
||||
to enforce the [Pod Security Standards](/docs/concepts/security/pod-security-standards).
|
||||
You can configure this admission controller to set cluster-wide defaults and [exemptions](#exemptions).
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
{{% version-check %}}
|
||||
|
||||
- Enable the `PodSecurity` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features).
|
||||
|
||||
## Configure the Admission Controller
|
||||
|
||||
```yaml
|
||||
apiVersion: apiserver.config.k8s.io/v1
|
||||
kind: AdmissionConfiguration
|
||||
plugins:
|
||||
- name: PodSecurity
|
||||
configuration:
|
||||
apiVersion: pod-security.admission.config.k8s.io/v1alpha1
|
||||
kind: PodSecurityConfiguration
|
||||
# Defaults applied when a mode label is not set.
|
||||
#
|
||||
# Level label values must be one of:
|
||||
# - "privileged" (default)
|
||||
# - "baseline"
|
||||
# - "restricted"
|
||||
#
|
||||
# Version label values must be one of:
|
||||
# - "latest" (default)
|
||||
# - specific version like "v{{< skew latestVersion >}}"
|
||||
defaults:
|
||||
enforce: "privileged"
|
||||
enforce-version: "latest"
|
||||
audit: "privileged"
|
||||
audit-version: "latest"
|
||||
warn: "privileged"
|
||||
warn-version: "latest"
|
||||
exemptions:
|
||||
# Array of authenticated usernames to exempt.
|
||||
usernames: []
|
||||
# Array of runtime class names to exempt.
|
||||
runtimeClassNames: []
|
||||
# Array of namespaces to exempt.
|
||||
namespaces: []
|
||||
```
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
title: Enforce Pod Security Standards with Namespace Labels
|
||||
reviewers:
|
||||
- tallclair
|
||||
- liggitt
|
||||
content_type: task
|
||||
min-kubernetes-server-version: v1.22
|
||||
---
|
||||
|
||||
Namespaces can be labeled to enforce the [Pod Security Standards](/docs/concepts/security/pod-security-standards).
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
{{% version-check %}}
|
||||
|
||||
- Enable the `PodSecurity` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features).
|
||||
|
||||
## Requiring the `baseline` Pod Security Standard with namespace labels
|
||||
|
||||
This manifest defines a Namespace `my-baseline-namespace` that:
|
||||
|
||||
- _Blocks_ any pods that don't satisfy the `baseline` policy requirements.
|
||||
- Generates a user-facing warning and adds an audit annotation to any created pod that does not
|
||||
meet the `restricted` policy requirements.
|
||||
- Pins the versions of the `baseline` and `restricted` policies to v{{< skew latestVersion >}}.
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: my-baseline-namespace
|
||||
labels:
|
||||
pod-security.kubernetes.io/enforce: baseline
|
||||
pod-security.kubernetes.io/enforce-version: v{{< skew latestVersion >}}
|
||||
|
||||
# We are setting these to our _desired_ `enforce` level.
|
||||
pod-security.kubernetes.io/audit: restricted
|
||||
pod-security.kubernetes.io/audit-version: v{{< skew latestVersion >}}
|
||||
pod-security.kubernetes.io/warn: restricted
|
||||
pod-security.kubernetes.io/warn-version: v{{< skew latestVersion >}}
|
||||
```
|
||||
|
||||
## Add labels to existing namespaces with `kubectl label`
|
||||
|
||||
{{< note >}}
|
||||
When an `enforce` policy (or version) label is added or changed, the admission plugin will test
|
||||
each pod in the namespace against the new policy. Violations are returned to the user as warnings.
|
||||
{{< /note >}}
|
||||
|
||||
It is helpful to apply the `--dry-run` flag when initially evaluating security profile changes for
|
||||
namespaces. The Pod Security Standard checks will still be run in _dry run_ mode, giving you
|
||||
information about how the new policy would treat existing pods, without actually updating a policy.
|
||||
|
||||
```shell
|
||||
kubectl label --dry-run=server --overwrite ns --all \
|
||||
pod-security.kubernetes.io/enforce=baseline
|
||||
```
|
||||
|
||||
### Applying to all namespaces
|
||||
|
||||
If you're just getting started with the Pod Security Standards, a suitable first step would be to
|
||||
configure all namespaces as `privileged` but set up audit annotations for a stricter level such as
|
||||
`baseline`:
|
||||
|
||||
```shell
|
||||
kubectl label --overwrite ns --all \
|
||||
pod-security.kubernetes.io/enforce=privileged \
|
||||
pod-security.kubernetes.io/audit=baseline \
|
||||
pod-security.kubernetes.io/warn=baseline
|
||||
```
|
||||
|
||||
### Applying to a single namespace
|
||||
|
||||
You can update a specific namespace as well. This command adds the `enforce=restricted`
|
||||
policy to `my-existing-namespace`, pinning the restricted policy version to v{{< skew latestVersion >}}.
|
||||
|
||||
```shell
|
||||
kubectl label --overwrite ns my-existing-namespace \
|
||||
pod-security.kubernetes.io/enforce=restricted \
|
||||
pod-security.kubernetes.io/enforce-version=v{{< skew latestVersion >}}
|
||||
```
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
title: Migrate from PodSecurityPolicy to the Built-In PodSecurity Admission Controller
|
||||
reviewers:
|
||||
- tallclair
|
||||
- liggitt
|
||||
content_type: task
|
||||
min-kubernetes-server-version: v1.22
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
This page describes the process of migrating from PodSecurityPolicies to the built-in PodSecurity
|
||||
admission controller. This can be done effectively using a combination of dry-run and `audit` and
|
||||
`warn` modes, although this becomes harder if mutating PSPs are used.
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
{{% version-check %}}
|
||||
|
||||
- Enable the `PodSecurity` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features).
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Steps
|
||||
|
||||
- **Eliminate mutating PodSecurityPolicies, if your cluster has any set up.**
|
||||
- Clone all mutating PSPs into a non-mutating version.
|
||||
- Update all ClusterRoles authorizing use of those mutating PSPs to also authorize use of the
|
||||
non-mutating variant.
|
||||
- Watch for Pods using the mutating PSPs and work with code owners to migrate to valid,
|
||||
non-mutating resources.
|
||||
- Delete mutating PSPs.
|
||||
- **Select a compatible policy level for each namespace.** Analyze existing resources in the
|
||||
namespace to drive this decision.
|
||||
- Review the requirements of the different [Pod Security Standards](/docs/concepts/security/pod-security-standards).
|
||||
- Evaluate the difference in privileges that would come from disabling the PSP controller.
|
||||
- In the event that a PodSecurityPolicy falls between two levels, consider:
|
||||
- Selecting a _less_ permissive PodSecurity level prioritizes security, and may require adjusting
|
||||
workloads to fit within the stricter policy.
|
||||
- Selecting a _more_ permissive PodSecurity level prioritizes avoiding disrupting or
|
||||
changing workloads, but may allow workload authors in the namespace greater permissions
|
||||
than desired.
|
||||
- **Apply the selected profiles in `warn` and `audit` mode.** This will give you an idea of how
|
||||
your Pods will respond to the new policies, without breaking existing workloads. Iterate on your
|
||||
[Pods' configuration](/docs/concepts/security/pod-security-admission#configuring-pods) until
|
||||
they are in compliance with the selected profiles.
|
||||
- Apply the profiles in `enforce` mode.
|
||||
- Stop including `PodSecurityPolicy` in the `--enable-admission-plugins` flag.
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: my-baseline-namespace
|
||||
labels:
|
||||
pod-security.kubernetes.io/enforce: baseline
|
||||
pod-security.kubernetes.io/enforce-version: latest
|
||||
pod-security.kubernetes.io/warn: baseline
|
||||
pod-security.kubernetes.io/warn-version: latest
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: my-privileged-namespace
|
||||
labels:
|
||||
pod-security.kubernetes.io/enforce: privileged
|
||||
pod-security.kubernetes.io/enforce-version: latest
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: my-restricted-namespace
|
||||
labels:
|
||||
pod-security.kubernetes.io/enforce: restricted
|
||||
pod-security.kubernetes.io/enforce-version: latest
|
||||
pod-security.kubernetes.io/warn: restricted
|
||||
pod-security.kubernetes.io/warn-version: latest
|
||||
Loading…
Reference in New Issue