|
|
|
@ -1,6 +1,6 @@
|
|
|
|
|
---
|
|
|
|
|
reviewers:
|
|
|
|
|
- pweil-
|
|
|
|
|
- liggitt
|
|
|
|
|
- tallclair
|
|
|
|
|
title: Pod Security Policies
|
|
|
|
|
content_type: concept
|
|
|
|
@ -11,770 +11,19 @@ weight: 30
|
|
|
|
|
|
|
|
|
|
{{< feature-state for_k8s_version="v1.21" state="deprecated" >}}
|
|
|
|
|
|
|
|
|
|
{{< caution >}}
|
|
|
|
|
PodSecurityPolicy is deprecated as of Kubernetes v1.21, and **will be removed in v1.25**. We recommend migrating to
|
|
|
|
|
[Pod Security Admission](/docs/concepts/security/pod-security-admission/), or a 3rd party admission plugin.
|
|
|
|
|
{{< note >}}
|
|
|
|
|
PodSecurityPolicy was [deprecated](/blog/2021/04/08/kubernetes-1-21-release-announcement/#podsecuritypolicy-deprecation)
|
|
|
|
|
in Kubernetes v1.21, and removed from Kubernetes in v1.25.
|
|
|
|
|
Instead of using PodSecurityPolicy, you can enforce similar restrictions on Pods using
|
|
|
|
|
either or both:
|
|
|
|
|
|
|
|
|
|
- [Pod Security Admission](/docs/concepts/security/pod-security-admission/)
|
|
|
|
|
- a 3rd party admission plugin, that you deploy and configure yourself
|
|
|
|
|
|
|
|
|
|
For a migration guide, see [Migrate from PodSecurityPolicy to the Built-In PodSecurity Admission Controller](/docs/tasks/configure-pod-container/migrate-from-psp/).
|
|
|
|
|
For more information on the deprecation,
|
|
|
|
|
For more information on the removal of this API,
|
|
|
|
|
see [PodSecurityPolicy Deprecation: Past, Present, and Future](/blog/2021/04/06/podsecuritypolicy-deprecation-past-present-and-future/).
|
|
|
|
|
{{< /caution >}}
|
|
|
|
|
|
|
|
|
|
Pod Security Policies enable fine-grained authorization of pod creation and
|
|
|
|
|
updates.
|
|
|
|
|
|
|
|
|
|
<!-- body -->
|
|
|
|
|
|
|
|
|
|
## What is a Pod Security Policy?
|
|
|
|
|
|
|
|
|
|
A _Pod Security Policy_ is a cluster-level resource that controls security
|
|
|
|
|
sensitive aspects of the pod specification. The
|
|
|
|
|
[PodSecurityPolicy](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritypolicy-v1beta1-policy) objects
|
|
|
|
|
define a set of conditions that a pod must run with in order to be accepted into
|
|
|
|
|
the system, as well as defaults for the related fields. They allow an
|
|
|
|
|
administrator to control the following:
|
|
|
|
|
|
|
|
|
|
| Control Aspect | Field Names |
|
|
|
|
|
| ----------------------------------------------------| ------------------------------------------- |
|
|
|
|
|
| Running of privileged containers | [`privileged`](#privileged) |
|
|
|
|
|
| Usage of host namespaces | [`hostPID`, `hostIPC`](#host-namespaces) |
|
|
|
|
|
| Usage of host networking and ports | [`hostNetwork`, `hostPorts`](#host-namespaces) |
|
|
|
|
|
| Usage of volume types | [`volumes`](#volumes-and-file-systems) |
|
|
|
|
|
| Usage of the host filesystem | [`allowedHostPaths`](#volumes-and-file-systems) |
|
|
|
|
|
| Allow specific FlexVolume drivers | [`allowedFlexVolumes`](#flexvolume-drivers) |
|
|
|
|
|
| Allocating an FSGroup that owns the pod's volumes | [`fsGroup`](#volumes-and-file-systems) |
|
|
|
|
|
| Requiring the use of a read only root file system | [`readOnlyRootFilesystem`](#volumes-and-file-systems) |
|
|
|
|
|
| The user and group IDs of the container | [`runAsUser`, `runAsGroup`, `supplementalGroups`](#users-and-groups) |
|
|
|
|
|
| Restricting escalation to root privileges | [`allowPrivilegeEscalation`, `defaultAllowPrivilegeEscalation`](#privilege-escalation) |
|
|
|
|
|
| Linux capabilities | [`defaultAddCapabilities`, `requiredDropCapabilities`, `allowedCapabilities`](#capabilities) |
|
|
|
|
|
| The SELinux context of the container | [`seLinux`](#selinux) |
|
|
|
|
|
| The Allowed Proc Mount types for the container | [`allowedProcMountTypes`](#allowedprocmounttypes) |
|
|
|
|
|
| The AppArmor profile used by containers | [annotations](#apparmor) |
|
|
|
|
|
| The seccomp profile used by containers | [annotations](#seccomp) |
|
|
|
|
|
| The sysctl profile used by containers | [`forbiddenSysctls`,`allowedUnsafeSysctls`](#sysctl) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Enabling Pod Security Policies
|
|
|
|
|
|
|
|
|
|
Pod security policy control is implemented as an optional
|
|
|
|
|
[admission controller](/docs/reference/access-authn-authz/admission-controllers/#podsecuritypolicy).
|
|
|
|
|
PodSecurityPolicies are enforced by
|
|
|
|
|
[enabling the admission controller](/docs/reference/access-authn-authz/admission-controllers/#how-do-i-turn-on-an-admission-control-plug-in),
|
|
|
|
|
but doing so without authorizing any policies **will prevent any pods from being created** in the
|
|
|
|
|
cluster.
|
|
|
|
|
|
|
|
|
|
Since the pod security policy API (`policy/v1beta1/podsecuritypolicy`) is
|
|
|
|
|
enabled independently of the admission controller, for existing clusters it is
|
|
|
|
|
recommended that policies are added and authorized before enabling the admission
|
|
|
|
|
controller.
|
|
|
|
|
|
|
|
|
|
## Authorizing Policies
|
|
|
|
|
|
|
|
|
|
When a PodSecurityPolicy resource is created, it does nothing. In order to use
|
|
|
|
|
it, the requesting user or target pod's
|
|
|
|
|
[service account](/docs/tasks/configure-pod-container/configure-service-account/)
|
|
|
|
|
must be authorized to use the policy, by allowing the `use` verb on the policy.
|
|
|
|
|
|
|
|
|
|
Most Kubernetes pods are not created directly by users. Instead, they are
|
|
|
|
|
typically created indirectly as part of a
|
|
|
|
|
[Deployment](/docs/concepts/workloads/controllers/deployment/),
|
|
|
|
|
[ReplicaSet](/docs/concepts/workloads/controllers/replicaset/), or other
|
|
|
|
|
templated controller via the controller manager. Granting the controller access
|
|
|
|
|
to the policy would grant access for *all* pods created by that controller,
|
|
|
|
|
so the preferred method for authorizing policies is to grant access to the
|
|
|
|
|
pod's service account (see [example](#run-another-pod)).
|
|
|
|
|
|
|
|
|
|
### Via RBAC
|
|
|
|
|
|
|
|
|
|
[RBAC](/docs/reference/access-authn-authz/rbac/) is a standard Kubernetes
|
|
|
|
|
authorization mode, and can easily be used to authorize use of policies.
|
|
|
|
|
|
|
|
|
|
First, a `Role` or `ClusterRole` needs to grant access to `use` the desired
|
|
|
|
|
policies. The rules to grant access look like this:
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
|
|
|
kind: ClusterRole
|
|
|
|
|
metadata:
|
|
|
|
|
name: <role name>
|
|
|
|
|
rules:
|
|
|
|
|
- apiGroups: ['policy']
|
|
|
|
|
resources: ['podsecuritypolicies']
|
|
|
|
|
verbs: ['use']
|
|
|
|
|
resourceNames:
|
|
|
|
|
- <list of policies to authorize>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Then the `(Cluster)Role` is bound to the authorized user(s):
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
|
|
|
kind: ClusterRoleBinding
|
|
|
|
|
metadata:
|
|
|
|
|
name: <binding name>
|
|
|
|
|
roleRef:
|
|
|
|
|
kind: ClusterRole
|
|
|
|
|
name: <role name>
|
|
|
|
|
apiGroup: rbac.authorization.k8s.io
|
|
|
|
|
subjects:
|
|
|
|
|
# Authorize all service accounts in a namespace (recommended):
|
|
|
|
|
- kind: Group
|
|
|
|
|
apiGroup: rbac.authorization.k8s.io
|
|
|
|
|
name: system:serviceaccounts:<authorized namespace>
|
|
|
|
|
# Authorize specific service accounts (not recommended):
|
|
|
|
|
- kind: ServiceAccount
|
|
|
|
|
name: <authorized service account name>
|
|
|
|
|
namespace: <authorized pod namespace>
|
|
|
|
|
# Authorize specific users (not recommended):
|
|
|
|
|
- kind: User
|
|
|
|
|
apiGroup: rbac.authorization.k8s.io
|
|
|
|
|
name: <authorized user name>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If a `RoleBinding` (not a `ClusterRoleBinding`) is used, it will only grant
|
|
|
|
|
usage for pods being run in the same namespace as the binding. This can be
|
|
|
|
|
paired with system groups to grant access to all pods run in the namespace:
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
# Authorize all service accounts in a namespace:
|
|
|
|
|
- kind: Group
|
|
|
|
|
apiGroup: rbac.authorization.k8s.io
|
|
|
|
|
name: system:serviceaccounts
|
|
|
|
|
# Or equivalently, all authenticated users in a namespace:
|
|
|
|
|
- kind: Group
|
|
|
|
|
apiGroup: rbac.authorization.k8s.io
|
|
|
|
|
name: system:authenticated
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
For more examples of RBAC bindings, see
|
|
|
|
|
[RoleBinding examples](/docs/reference/access-authn-authz/rbac#role-binding-examples).
|
|
|
|
|
For a complete example of authorizing a PodSecurityPolicy, see [below](#example).
|
|
|
|
|
|
|
|
|
|
### Recommended Practice
|
|
|
|
|
|
|
|
|
|
PodSecurityPolicy is being replaced by a new, simplified `PodSecurity`
|
|
|
|
|
{{< glossary_tooltip text="admission controller" term_id="admission-controller" >}}.
|
|
|
|
|
For more details on this change, see
|
|
|
|
|
[PodSecurityPolicy Deprecation: Past, Present, and Future](/blog/2021/04/06/podsecuritypolicy-deprecation-past-present-and-future/).
|
|
|
|
|
Follow these guidelines to simplify migration from PodSecurityPolicy to the
|
|
|
|
|
new admission controller:
|
|
|
|
|
|
|
|
|
|
1. Limit your PodSecurityPolicies to the policies defined by the
|
|
|
|
|
[Pod Security Standards](/docs/concepts/security/pod-security-standards):
|
|
|
|
|
|
|
|
|
|
- {{< example file="policy/privileged-psp.yaml" >}}Privileged{{< /example >}}
|
|
|
|
|
- {{< example file="policy/baseline-psp.yaml" >}}Baseline{{< /example >}}
|
|
|
|
|
- {{< example file="policy/restricted-psp.yaml" >}}Restricted{{< /example >}}
|
|
|
|
|
|
|
|
|
|
1. Only bind PSPs to entire namespaces, by using the `system:serviceaccounts:<namespace>` group
|
|
|
|
|
(where `<namespace>` is the target namespace). For example:
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
|
|
|
# This cluster role binding allows all pods in the "development" namespace to use the baseline PSP.
|
|
|
|
|
kind: ClusterRoleBinding
|
|
|
|
|
metadata:
|
|
|
|
|
name: psp-baseline-namespaces
|
|
|
|
|
roleRef:
|
|
|
|
|
kind: ClusterRole
|
|
|
|
|
name: psp-baseline
|
|
|
|
|
apiGroup: rbac.authorization.k8s.io
|
|
|
|
|
subjects:
|
|
|
|
|
- kind: Group
|
|
|
|
|
name: system:serviceaccounts:development
|
|
|
|
|
apiGroup: rbac.authorization.k8s.io
|
|
|
|
|
- kind: Group
|
|
|
|
|
name: system:serviceaccounts:canary
|
|
|
|
|
apiGroup: rbac.authorization.k8s.io
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Troubleshooting
|
|
|
|
|
|
|
|
|
|
- The [controller manager](/docs/reference/command-line-tools-reference/kube-controller-manager/)
|
|
|
|
|
must be run against the secured API port and must not have superuser permissions. See
|
|
|
|
|
[Controlling Access to the Kubernetes API](/docs/concepts/security/controlling-access)
|
|
|
|
|
to learn about API server access controls.
|
|
|
|
|
If the controller manager connected through the trusted API port (also known as the
|
|
|
|
|
`localhost` listener), requests would bypass authentication and authorization modules;
|
|
|
|
|
all PodSecurityPolicy objects would be allowed, and users would be able to create grant
|
|
|
|
|
themselves the ability to create privileged containers.
|
|
|
|
|
|
|
|
|
|
For more details on configuring controller manager authorization, see
|
|
|
|
|
[Controller Roles](/docs/reference/access-authn-authz/rbac/#controller-roles).
|
|
|
|
|
|
|
|
|
|
## Policy Order
|
|
|
|
|
|
|
|
|
|
In addition to restricting pod creation and update, pod security policies can
|
|
|
|
|
also be used to provide default values for many of the fields that it
|
|
|
|
|
controls. When multiple policies are available, the pod security policy
|
|
|
|
|
controller selects policies according to the following criteria:
|
|
|
|
|
|
|
|
|
|
1. PodSecurityPolicies which allow the pod as-is, without changing defaults or
|
|
|
|
|
mutating the pod, are preferred. The order of these non-mutating
|
|
|
|
|
PodSecurityPolicies doesn't matter.
|
|
|
|
|
2. If the pod must be defaulted or mutated, the first PodSecurityPolicy
|
|
|
|
|
(ordered by name) to allow the pod is selected.
|
|
|
|
|
|
|
|
|
|
When a Pod is validated against a PodSecurityPolicy, [a `kubernetes.io/psp` annotation](/docs/reference/labels-annotations-taints/#kubernetes-io-psp)
|
|
|
|
|
is added to the Pod, with the name of the PodSecurityPolicy as the annotation value.
|
|
|
|
|
|
|
|
|
|
{{< note >}}
|
|
|
|
|
During update operations (during which mutations to pod specs are disallowed)
|
|
|
|
|
only non-mutating PodSecurityPolicies are used to validate the pod.
|
|
|
|
|
If you are not running Kubernetes v{{< skew currentVersion >}}, check the documentation for
|
|
|
|
|
your version of Kubernetes.
|
|
|
|
|
{{< /note >}}
|
|
|
|
|
|
|
|
|
|
## Example
|
|
|
|
|
|
|
|
|
|
This example assumes you have a running cluster with the PodSecurityPolicy
|
|
|
|
|
admission controller enabled and you have cluster admin privileges.
|
|
|
|
|
|
|
|
|
|
### Set up
|
|
|
|
|
|
|
|
|
|
Set up a namespace and a service account to act as for this example. We'll use
|
|
|
|
|
this service account to mock a non-admin user.
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl create namespace psp-example
|
|
|
|
|
kubectl create serviceaccount -n psp-example fake-user
|
|
|
|
|
kubectl create rolebinding -n psp-example fake-editor --clusterrole=edit --serviceaccount=psp-example:fake-user
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
To make it clear which user we're acting as and save some typing, create 2
|
|
|
|
|
aliases:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
alias kubectl-admin='kubectl -n psp-example'
|
|
|
|
|
alias kubectl-user='kubectl --as=system:serviceaccount:psp-example:fake-user -n psp-example'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Create a policy and a pod
|
|
|
|
|
|
|
|
|
|
This is a policy that prevents the creation of privileged pods.
|
|
|
|
|
The name of a PodSecurityPolicy object must be a valid
|
|
|
|
|
[DNS subdomain name](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
|
|
|
|
|
|
|
|
|
|
{{< codenew file="policy/example-psp.yaml" >}}
|
|
|
|
|
|
|
|
|
|
And create it with kubectl:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-admin create -f https://k8s.io/examples/policy/example-psp.yaml
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Now, as the unprivileged user, try to create a simple pod:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-user create -f- <<EOF
|
|
|
|
|
apiVersion: v1
|
|
|
|
|
kind: Pod
|
|
|
|
|
metadata:
|
|
|
|
|
name: pause
|
|
|
|
|
spec:
|
|
|
|
|
containers:
|
|
|
|
|
- name: pause
|
|
|
|
|
image: k8s.gcr.io/pause
|
|
|
|
|
EOF
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The output is similar to this:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Error from server (Forbidden): error when creating "STDIN": pods "pause" is forbidden: unable to validate against any pod security policy: []
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**What happened?** Although the PodSecurityPolicy was created, neither the
|
|
|
|
|
pod's service account nor `fake-user` have permission to use the new policy:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-user auth can-i use podsecuritypolicy/example
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The output is similar to this:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
no
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Create the rolebinding to grant `fake-user` the `use` verb on the example
|
|
|
|
|
policy:
|
|
|
|
|
|
|
|
|
|
{{< note >}}
|
|
|
|
|
This is not the recommended way! See the [next section](#run-another-pod)
|
|
|
|
|
for the preferred approach.
|
|
|
|
|
{{< /note >}}
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-admin create role psp:unprivileged \
|
|
|
|
|
--verb=use \
|
|
|
|
|
--resource=podsecuritypolicy \
|
|
|
|
|
--resource-name=example
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
role "psp:unprivileged" created
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-admin create rolebinding fake-user:psp:unprivileged \
|
|
|
|
|
--role=psp:unprivileged \
|
|
|
|
|
--serviceaccount=psp-example:fake-user
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
rolebinding "fake-user:psp:unprivileged" created
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-user auth can-i use podsecuritypolicy/example
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
yes
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Now retry creating the pod:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-user create -f- <<EOF
|
|
|
|
|
apiVersion: v1
|
|
|
|
|
kind: Pod
|
|
|
|
|
metadata:
|
|
|
|
|
name: pause
|
|
|
|
|
spec:
|
|
|
|
|
containers:
|
|
|
|
|
- name: pause
|
|
|
|
|
image: k8s.gcr.io/pause
|
|
|
|
|
EOF
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The output is similar to this
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
pod "pause" created
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
It works as expected! You can verify that the pod was validated against the
|
|
|
|
|
newly created PodSecurityPolicy:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-user get pod pause -o yaml | grep kubernetes.io/psp
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The output is similar to this
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
kubernetes.io/psp: example
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
But any attempts to create a privileged pod should still
|
|
|
|
|
be denied:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-user create -f- <<EOF
|
|
|
|
|
apiVersion: v1
|
|
|
|
|
kind: Pod
|
|
|
|
|
metadata:
|
|
|
|
|
name: privileged
|
|
|
|
|
spec:
|
|
|
|
|
containers:
|
|
|
|
|
- name: pause
|
|
|
|
|
image: k8s.gcr.io/pause
|
|
|
|
|
securityContext:
|
|
|
|
|
privileged: true
|
|
|
|
|
EOF
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The output is similar to this:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Error from server (Forbidden): error when creating "STDIN": pods "privileged" is forbidden: unable to validate against any pod security policy: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Delete the pod before moving on:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-user delete pod pause
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Run another pod
|
|
|
|
|
|
|
|
|
|
Let's try that again, slightly differently:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-user create deployment pause --image=k8s.gcr.io/pause
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```none
|
|
|
|
|
deployment "pause" created
|
|
|
|
|
```
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-user get pods
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
No resources found.
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-user get events | head -n 2
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE
|
|
|
|
|
1m 2m 15 pause-7774d79b5 ReplicaSet Warning FailedCreate replicaset-controller Error creating: pods "pause-7774d79b5-" is forbidden: no providers available to validate pod request
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**What happened?** We already bound the `psp:unprivileged` role for our `fake-user`,
|
|
|
|
|
why are we getting the error `Error creating: pods "pause-7774d79b5-" is
|
|
|
|
|
forbidden: no providers available to validate pod request`? The answer lies in
|
|
|
|
|
the source - `replicaset-controller`. Fake-user successfully created the
|
|
|
|
|
deployment (which successfully created a replicaset), but when the replicaset
|
|
|
|
|
went to create the pod it was not authorized to use the example
|
|
|
|
|
podsecuritypolicy.
|
|
|
|
|
|
|
|
|
|
In order to fix this, bind the `psp:unprivileged` role to the pod's service
|
|
|
|
|
account instead. In this case (since we didn't specify it) the service account
|
|
|
|
|
is `default`:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-admin create rolebinding default:psp:unprivileged \
|
|
|
|
|
--role=psp:unprivileged \
|
|
|
|
|
--serviceaccount=psp-example:default
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```none
|
|
|
|
|
rolebinding "default:psp:unprivileged" created
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Now if you give it a minute to retry, the replicaset-controller should
|
|
|
|
|
eventually succeed in creating the pod:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-user get pods --watch
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```none
|
|
|
|
|
NAME READY STATUS RESTARTS AGE
|
|
|
|
|
pause-7774d79b5-qrgcb 0/1 Pending 0 1s
|
|
|
|
|
pause-7774d79b5-qrgcb 0/1 Pending 0 1s
|
|
|
|
|
pause-7774d79b5-qrgcb 0/1 ContainerCreating 0 1s
|
|
|
|
|
pause-7774d79b5-qrgcb 1/1 Running 0 2s
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Clean up
|
|
|
|
|
|
|
|
|
|
Delete the namespace to clean up most of the example resources:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-admin delete ns psp-example
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
namespace "psp-example" deleted
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note that `PodSecurityPolicy` resources are not namespaced, and must be cleaned
|
|
|
|
|
up separately:
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
kubectl-admin delete psp example
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
podsecuritypolicy "example" deleted
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Example Policies
|
|
|
|
|
|
|
|
|
|
This is the least restrictive policy you can create, equivalent to not using the
|
|
|
|
|
pod security policy admission controller:
|
|
|
|
|
|
|
|
|
|
{{< codenew file="policy/privileged-psp.yaml" >}}
|
|
|
|
|
|
|
|
|
|
This is an example of a restrictive policy that requires users to run as an
|
|
|
|
|
unprivileged user, blocks possible escalations to root, and requires use of
|
|
|
|
|
several security mechanisms.
|
|
|
|
|
|
|
|
|
|
{{< codenew file="policy/restricted-psp.yaml" >}}
|
|
|
|
|
|
|
|
|
|
See [Pod Security Standards](/docs/concepts/security/pod-security-standards/#policy-instantiation)
|
|
|
|
|
for more examples.
|
|
|
|
|
|
|
|
|
|
## Policy Reference
|
|
|
|
|
|
|
|
|
|
### Privileged
|
|
|
|
|
|
|
|
|
|
**Privileged** - determines if any container in a pod can enable privileged mode.
|
|
|
|
|
By default a container is not allowed to access any devices on the host, but a
|
|
|
|
|
"privileged" container is given access to all devices on the host. This allows
|
|
|
|
|
the container nearly all the same access as processes running on the host.
|
|
|
|
|
This is useful for containers that want to use linux capabilities like
|
|
|
|
|
manipulating the network stack and accessing devices.
|
|
|
|
|
|
|
|
|
|
### Host namespaces
|
|
|
|
|
|
|
|
|
|
**HostPID** - Controls whether the pod containers can share the host process ID
|
|
|
|
|
namespace. Note that when paired with ptrace this can be used to escalate
|
|
|
|
|
privileges outside of the container (ptrace is forbidden by default).
|
|
|
|
|
|
|
|
|
|
**HostIPC** - Controls whether the pod containers can share the host IPC
|
|
|
|
|
namespace.
|
|
|
|
|
|
|
|
|
|
**HostNetwork** - Controls whether the pod may use the node network
|
|
|
|
|
namespace. Doing so gives the pod access to the loopback device, services
|
|
|
|
|
listening on localhost, and could be used to snoop on network activity of other
|
|
|
|
|
pods on the same node.
|
|
|
|
|
|
|
|
|
|
**HostPorts** - Provides a list of ranges of allowable ports in the host
|
|
|
|
|
network namespace. Defined as a list of `HostPortRange`, with `min`(inclusive)
|
|
|
|
|
and `max`(inclusive). Defaults to no allowed host ports.
|
|
|
|
|
|
|
|
|
|
### Volumes and file systems
|
|
|
|
|
|
|
|
|
|
**Volumes** - Provides a list of allowed volume types. The allowable values
|
|
|
|
|
correspond to the volume sources that are defined when creating a volume. For
|
|
|
|
|
the complete list of volume types, see [Types of
|
|
|
|
|
Volumes](/docs/concepts/storage/volumes/#types-of-volumes). Additionally,
|
|
|
|
|
`*` may be used to allow all volume types.
|
|
|
|
|
|
|
|
|
|
The **recommended minimum set** of allowed volumes for new PSPs are:
|
|
|
|
|
|
|
|
|
|
- `configMap`
|
|
|
|
|
- `downwardAPI`
|
|
|
|
|
- `emptyDir`
|
|
|
|
|
- `persistentVolumeClaim`
|
|
|
|
|
- `secret`
|
|
|
|
|
- `projected`
|
|
|
|
|
|
|
|
|
|
{{< warning >}}
|
|
|
|
|
PodSecurityPolicy does not limit the types of `PersistentVolume` objects that
|
|
|
|
|
may be referenced by a `PersistentVolumeClaim`, and hostPath type
|
|
|
|
|
`PersistentVolumes` do not support read-only access mode. Only trusted users
|
|
|
|
|
should be granted permission to create `PersistentVolume` objects.
|
|
|
|
|
{{< /warning >}}
|
|
|
|
|
|
|
|
|
|
**FSGroup** - Controls the supplemental group applied to some volumes.
|
|
|
|
|
|
|
|
|
|
- *MustRunAs* - Requires at least one `range` to be specified. Uses the
|
|
|
|
|
minimum value of the first range as the default. Validates against all ranges.
|
|
|
|
|
- *MayRunAs* - Requires at least one `range` to be specified. Allows
|
|
|
|
|
`FSGroups` to be left unset without providing a default. Validates against
|
|
|
|
|
all ranges if `FSGroups` is set.
|
|
|
|
|
- *RunAsAny* - No default provided. Allows any `fsGroup` ID to be specified.
|
|
|
|
|
|
|
|
|
|
**AllowedHostPaths** - This specifies a list of host paths that are allowed
|
|
|
|
|
to be used by hostPath volumes. An empty list means there is no restriction on
|
|
|
|
|
host paths used. This is defined as a list of objects with a single `pathPrefix`
|
|
|
|
|
field, which allows hostPath volumes to mount a path that begins with an
|
|
|
|
|
allowed prefix, and a `readOnly` field indicating it must be mounted read-only.
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
allowedHostPaths:
|
|
|
|
|
# This allows "/foo", "/foo/", "/foo/bar" etc., but
|
|
|
|
|
# disallows "/fool", "/etc/foo" etc.
|
|
|
|
|
# "/foo/../" is never valid.
|
|
|
|
|
- pathPrefix: "/foo"
|
|
|
|
|
readOnly: true # only allow read-only mounts
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
{{< warning >}}
|
|
|
|
|
There are many ways a container with unrestricted access to the host
|
|
|
|
|
filesystem can escalate privileges, including reading data from other
|
|
|
|
|
containers, and abusing the credentials of system services, such as Kubelet.
|
|
|
|
|
|
|
|
|
|
Writeable hostPath directory volumes allow containers to write
|
|
|
|
|
to the filesystem in ways that let them traverse the host filesystem outside the `pathPrefix`.
|
|
|
|
|
`readOnly: true`, available in Kubernetes 1.11+, must be used on **all** `allowedHostPaths`
|
|
|
|
|
to effectively limit access to the specified `pathPrefix`.
|
|
|
|
|
{{< /warning >}}
|
|
|
|
|
|
|
|
|
|
**ReadOnlyRootFilesystem** - Requires that containers must run with a read-only
|
|
|
|
|
root filesystem (i.e. no writable layer).
|
|
|
|
|
|
|
|
|
|
### FlexVolume drivers
|
|
|
|
|
|
|
|
|
|
This specifies a list of FlexVolume drivers that are allowed to be used
|
|
|
|
|
by flexvolume. An empty list or nil means there is no restriction on the drivers.
|
|
|
|
|
Please make sure [`volumes`](#volumes-and-file-systems) field contains the
|
|
|
|
|
`flexVolume` volume type; no FlexVolume driver is allowed otherwise.
|
|
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
apiVersion: policy/v1beta1
|
|
|
|
|
kind: PodSecurityPolicy
|
|
|
|
|
metadata:
|
|
|
|
|
name: allow-flex-volumes
|
|
|
|
|
spec:
|
|
|
|
|
# ... other spec fields
|
|
|
|
|
volumes:
|
|
|
|
|
- flexVolume
|
|
|
|
|
allowedFlexVolumes:
|
|
|
|
|
- driver: example/lvm
|
|
|
|
|
- driver: example/cifs
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Users and groups
|
|
|
|
|
|
|
|
|
|
**RunAsUser** - Controls which user ID the containers are run with.
|
|
|
|
|
|
|
|
|
|
- *MustRunAs* - Requires at least one `range` to be specified. Uses the
|
|
|
|
|
minimum value of the first range as the default. Validates against all ranges.
|
|
|
|
|
- *MustRunAsNonRoot* - Requires that the pod be submitted with a non-zero
|
|
|
|
|
`runAsUser` or have the `USER` directive defined (using a numeric UID) in the
|
|
|
|
|
image. Pods which have specified neither `runAsNonRoot` nor `runAsUser` settings
|
|
|
|
|
will be mutated to set `runAsNonRoot=true`, thus requiring a defined non-zero
|
|
|
|
|
numeric `USER` directive in the container. No default provided. Setting
|
|
|
|
|
`allowPrivilegeEscalation=false` is strongly recommended with this strategy.
|
|
|
|
|
- *RunAsAny* - No default provided. Allows any `runAsUser` to be specified.
|
|
|
|
|
|
|
|
|
|
**RunAsGroup** - Controls which primary group ID the containers are run with.
|
|
|
|
|
|
|
|
|
|
- *MustRunAs* - Requires at least one `range` to be specified. Uses the
|
|
|
|
|
minimum value of the first range as the default. Validates against all ranges.
|
|
|
|
|
- *MayRunAs* - Does not require that RunAsGroup be specified. However, when RunAsGroup
|
|
|
|
|
is specified, they have to fall in the defined range.
|
|
|
|
|
- *RunAsAny* - No default provided. Allows any `runAsGroup` to be specified.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**SupplementalGroups** - Controls which group IDs containers add.
|
|
|
|
|
|
|
|
|
|
- *MustRunAs* - Requires at least one `range` to be specified. Uses the
|
|
|
|
|
minimum value of the first range as the default. Validates against all ranges.
|
|
|
|
|
- *MayRunAs* - Requires at least one `range` to be specified. Allows
|
|
|
|
|
`supplementalGroups` to be left unset without providing a default.
|
|
|
|
|
Validates against all ranges if `supplementalGroups` is set.
|
|
|
|
|
- *RunAsAny* - No default provided. Allows any `supplementalGroups` to be
|
|
|
|
|
specified.
|
|
|
|
|
|
|
|
|
|
### Privilege Escalation
|
|
|
|
|
|
|
|
|
|
These options control the `allowPrivilegeEscalation` container option. This bool
|
|
|
|
|
directly controls whether the
|
|
|
|
|
[`no_new_privs`](https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt)
|
|
|
|
|
flag gets set on the container process. This flag will prevent `setuid` binaries
|
|
|
|
|
from changing the effective user ID, and prevent files from enabling extra
|
|
|
|
|
capabilities (e.g. it will prevent the use of the `ping` tool). This behavior is
|
|
|
|
|
required to effectively enforce `MustRunAsNonRoot`.
|
|
|
|
|
|
|
|
|
|
**AllowPrivilegeEscalation** - Gates whether or not a user is allowed to set the
|
|
|
|
|
security context of a container to `allowPrivilegeEscalation=true`. This
|
|
|
|
|
defaults to allowed so as to not break setuid binaries. Setting it to `false`
|
|
|
|
|
ensures that no child process of a container can gain more privileges than its parent.
|
|
|
|
|
|
|
|
|
|
**DefaultAllowPrivilegeEscalation** - Sets the default for the
|
|
|
|
|
`allowPrivilegeEscalation` option. The default behavior without this is to allow
|
|
|
|
|
privilege escalation so as to not break setuid binaries. If that behavior is not
|
|
|
|
|
desired, this field can be used to default to disallow, while still permitting
|
|
|
|
|
pods to request `allowPrivilegeEscalation` explicitly.
|
|
|
|
|
|
|
|
|
|
### Capabilities
|
|
|
|
|
|
|
|
|
|
Linux capabilities provide a finer grained breakdown of the privileges
|
|
|
|
|
traditionally associated with the superuser. Some of these capabilities can be
|
|
|
|
|
used to escalate privileges or for container breakout, and may be restricted by
|
|
|
|
|
the PodSecurityPolicy. For more details on Linux capabilities, see
|
|
|
|
|
[capabilities(7)](http://man7.org/linux/man-pages/man7/capabilities.7.html).
|
|
|
|
|
|
|
|
|
|
The following fields take a list of capabilities, specified as the capability
|
|
|
|
|
name in ALL_CAPS without the `CAP_` prefix.
|
|
|
|
|
|
|
|
|
|
**AllowedCapabilities** - Provides a list of capabilities that are allowed to be added
|
|
|
|
|
to a container. The default set of capabilities are implicitly allowed. The
|
|
|
|
|
empty set means that no additional capabilities may be added beyond the default
|
|
|
|
|
set. `*` can be used to allow all capabilities.
|
|
|
|
|
|
|
|
|
|
**RequiredDropCapabilities** - The capabilities which must be dropped from
|
|
|
|
|
containers. These capabilities are removed from the default set, and must not be
|
|
|
|
|
added. Capabilities listed in `RequiredDropCapabilities` must not be included in
|
|
|
|
|
`AllowedCapabilities` or `DefaultAddCapabilities`.
|
|
|
|
|
|
|
|
|
|
**DefaultAddCapabilities** - The capabilities which are added to containers by
|
|
|
|
|
default, in addition to the runtime defaults. See the
|
|
|
|
|
documentation for your container runtime for information on working with Linux capabilities.
|
|
|
|
|
|
|
|
|
|
### SELinux
|
|
|
|
|
|
|
|
|
|
- *MustRunAs* - Requires `seLinuxOptions` to be configured. Uses
|
|
|
|
|
`seLinuxOptions` as the default. Validates against `seLinuxOptions`.
|
|
|
|
|
- *RunAsAny* - No default provided. Allows any `seLinuxOptions` to be
|
|
|
|
|
specified.
|
|
|
|
|
|
|
|
|
|
### AllowedProcMountTypes
|
|
|
|
|
|
|
|
|
|
`allowedProcMountTypes` is a list of allowed ProcMountTypes.
|
|
|
|
|
Empty or nil indicates that only the `DefaultProcMountType` may be used.
|
|
|
|
|
|
|
|
|
|
`DefaultProcMount` uses the container runtime defaults for readonly and masked
|
|
|
|
|
paths for /proc. Most container runtimes mask certain paths in /proc to avoid
|
|
|
|
|
accidental security exposure of special devices or information. This is denoted
|
|
|
|
|
as the string `Default`.
|
|
|
|
|
|
|
|
|
|
The only other ProcMountType is `UnmaskedProcMount`, which bypasses the
|
|
|
|
|
default masking behavior of the container runtime and ensures the newly
|
|
|
|
|
created /proc the container stays intact with no modifications. This is
|
|
|
|
|
denoted as the string `Unmasked`.
|
|
|
|
|
|
|
|
|
|
### AppArmor
|
|
|
|
|
|
|
|
|
|
Controlled via annotations on the PodSecurityPolicy. Refer to the
|
|
|
|
|
[AppArmor documentation](/docs/tutorials/security/apparmor/#podsecuritypolicy-annotations).
|
|
|
|
|
|
|
|
|
|
### Seccomp
|
|
|
|
|
|
|
|
|
|
As of Kubernetes v1.19, you can use the `seccompProfile` field in the
|
|
|
|
|
`securityContext` of Pods or containers to
|
|
|
|
|
[control use of seccomp profiles](/docs/tutorials/security/seccomp/).
|
|
|
|
|
In prior versions, seccomp was controlled by adding annotations to a Pod. The
|
|
|
|
|
same PodSecurityPolicies can be used with either version to enforce how these
|
|
|
|
|
fields or annotations are applied.
|
|
|
|
|
|
|
|
|
|
**seccomp.security.alpha.kubernetes.io/defaultProfileName** - Annotation that
|
|
|
|
|
specifies the default seccomp profile to apply to containers. Possible values
|
|
|
|
|
are:
|
|
|
|
|
|
|
|
|
|
- `unconfined` - Seccomp is not applied to the container processes (this is the
|
|
|
|
|
default in Kubernetes), if no alternative is provided.
|
|
|
|
|
- `runtime/default` - The default container runtime profile is used.
|
|
|
|
|
- `docker/default` - The Docker default seccomp profile is used. Deprecated as
|
|
|
|
|
of Kubernetes 1.11. Use `runtime/default` instead.
|
|
|
|
|
- `localhost/<path>` - Specify a profile as a file on the node located at
|
|
|
|
|
`<seccomp_root>/<path>`, where `<seccomp_root>` is defined via the
|
|
|
|
|
`--seccomp-profile-root` flag on the Kubelet. If the `--seccomp-profile-root`
|
|
|
|
|
flag is not defined, the default path will be used, which is
|
|
|
|
|
`<root-dir>/seccomp` where `<root-dir>` is specified by the `--root-dir` flag.
|
|
|
|
|
|
|
|
|
|
{{< note >}}
|
|
|
|
|
The `--seccomp-profile-root` flag is deprecated since Kubernetes
|
|
|
|
|
v1.19. Users are encouraged to use the default path.
|
|
|
|
|
{{< /note >}}
|
|
|
|
|
|
|
|
|
|
**seccomp.security.alpha.kubernetes.io/allowedProfileNames** - Annotation that
|
|
|
|
|
specifies which values are allowed for the pod seccomp annotations. Specified as
|
|
|
|
|
a comma-delimited list of allowed values. Possible values are those listed
|
|
|
|
|
above, plus `*` to allow all profiles. Absence of this annotation means that the
|
|
|
|
|
default cannot be changed.
|
|
|
|
|
|
|
|
|
|
### Sysctl
|
|
|
|
|
|
|
|
|
|
By default, all safe sysctls are allowed.
|
|
|
|
|
|
|
|
|
|
- `forbiddenSysctls` - excludes specific sysctls. You can forbid a combination
|
|
|
|
|
of safe and unsafe sysctls in the list. To forbid setting any sysctls, use
|
|
|
|
|
`*` on its own.
|
|
|
|
|
- `allowedUnsafeSysctls` - allows specific sysctls that had been disallowed by
|
|
|
|
|
the default list, so long as these are not listed in `forbiddenSysctls`.
|
|
|
|
|
|
|
|
|
|
Refer to the [Sysctl documentation](/docs/tasks/administer-cluster/sysctl-cluster/#podsecuritypolicy).
|
|
|
|
|
|
|
|
|
|
## {{% heading "whatsnext" %}}
|
|
|
|
|
|
|
|
|
|
- See [PodSecurityPolicy Deprecation: Past, Present, and Future](/blog/2021/04/06/podsecuritypolicy-deprecation-past-present-and-future/)
|
|
|
|
|
to learn about the future of pod security policy.
|
|
|
|
|
|
|
|
|
|
- See [Pod Security Standards](/docs/concepts/security/pod-security-standards/)
|
|
|
|
|
for policy recommendations.
|
|
|
|
|
|
|
|
|
|
- Refer to [PodSecurityPolicy reference](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritypolicy-v1beta1-policy)
|
|
|
|
|
for the API details.
|
|
|
|
|
|
|
|
|
|