Kubernetesで利用可能なセキュリティ設定(Pod Security Context, Security Context, Pod Security Policy) について

# はじめに
この記事では、Kubernetesで利用できるセキュリティの設定(Pod Security Context, Security Context)、セキュリティポリシー (Pod Security Policy) に関する説明と検証結果をまとめています。

# Kubernetesにおけるセキュリティの設定 / ポリシーについて
## セキュリティ設定 / ポリシーの全体像
Kubernetesで適用可能なセキュリティの設定 / ポリシーとして、下記の3種類の機能が提供されています。PodSecurityPolicyに関してはv1.17時点で beta 機能として提供されています。

PodSecurityPolicyはポリシーを定義したオブジェクト(`podSecurityPolicy`)を作成する必要があります。
Pod Security ContextとSecurity Contextに関しては、podのマニュフェストファイルの中で`securityContext`を指定して設定します。
(**指定する名前は同じですがマニュフェストファイルの中で指定する箇所が異なる**ので、注意が必要です。)
<br>

- [Pod Security Policy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#podsecuritypolicy-v1beta1-policy)：**クラスタ単位**のセキュリティポリシー
    - https://kubernetes.io/docs/concepts/policy/pod-security-policy/ (example)
- [Pod Security Context](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#podsecuritycontext-v1-core)：**pod単位**のセキュリティの設定
    - `pod.spec.securityContext`でを定義
    - https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod (example)
- [Security Context](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#securitycontext-v1-core)：**コンテナ単位**のセキュリティの設定
    - `pod.spec.containers.securityContext`で定義
    - https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container (example)

## Admission Controlについて
PodSecurityPolicyの利用においては、Admission Controllが利用できることが前提となります。
（Kubernetesのドキュメントでは、[Pod security policy control is implemented as an optional (but recommended) admission controller.](https://kubernetes.io/docs/concepts/policy/pod-security-policy/#enabling-pod-security-policies)と説明されています。）

[Admission Controll](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#what-does-each-admission-controller-do)とは、**リクエストの内容をチェックした上で制御する**機能です。
任意のプラグインを有効化することで、特定の条件に該当するリクエストに対する処理 (リクエストの拒否・リクエストの変更 etc.) を有効化します。

podSecurityPolicyを利用する場合は、クラスタ作成時に[Admission Controllerのプラグイン](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#podsecuritypolicy)として`podSecurityPolicy`を指定した上で有効化します。

## Role / Rolebindingについて
KubernetesのRBACの機能を利用してpodSecurityPolicyをユーザに紐づけることも可能です。

[KubernetesのDocsで提供されている例](https://kubernetes.io/docs/concepts/policy/pod-security-policy/#example)では、SA(ServiceAccount)を作成した上でそのユーザーにRoleを紐づけています。
下記の例ではSAに対して`edit`の権限のみを付与しています。

```console
$ 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
```

ユーザーのリクエストにポリシーを適用する際には、**指定したリソース（ここでは作成したpodSecurityPolicyに）の`use`権限**をユーザーに付与する必要があります。
（`use`権限が付与されていないユーザーは、podを作成することができません。）

```console
$ kubectl create role psp:unprivileged \
    --verb=use \
    --resource=podsecuritypolicy \
    --resource-name=example \
    --as=system:serviceaccount:psp-example:fake-user \
    -n psp-example

$ kubectl create rolebinding fake-user:psp:unprivileged \
    --role=psp:unprivileged \
    --serviceaccount=psp-example:fake-user
```

`use`権限を付与したRoleをSAに紐付けた後は「ユーザーがポリシーを利用できるかどうか」を下記のコマンドで確認できます。

```console
$ kubectl auth can-i use podsecuritypolicy/example \
        --as=system:serviceaccount:psp-example:fake-user \
        -n psp-example
```


## 各マネージドサービスの対応状況
各マネージドサービスでは、基本的に上記のいずれのポリシーも利用可能となっています。
podSecurityPolicyに関しては、デフォルトでポリシーが定義されていたり、kubectl以外のCLI経由で有効/無効を設定できるサービスもあるため、各サービスの仕様を確認する必要があります。
(確認できていないサービスもあるので、必要に応じてこの部分は追記していきます)

- pod Security Policy
    - [Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/pod-security-policy.html)：デフォルトでpodSecurityPolicyが作成済
    - [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/docs/how-to/pod-security-policies?hl=ja)：CLIを利用してpodSecurityPolicyのプラグインを有効化 / 無効化することが可能

# 各機能の検証
ここからは、各ポリシーの検証を行っていきます。
バージョン情報は下記の通りです。今回は[IBM Cloud Kubernetes Service](https://www.ibm.com/jp-ja/cloud/container-service)の無料クラスタ (Master: 1、Worker: 1) を利用して検証を行います。
（EKS・GKEなど、その他のマネージドサービスを利用して検証することも可能です。）

```console
$ k version
  Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.2", GitCommit:"59603c6e503c87169aea6106f57b9f242f64df89", GitTreeState:"clean", BuildDate:"2020-01-18T23:30:10Z", GoVersion:"go1.13.5", Compiler:"gc", Platform:"darwin/amd64"}
  Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.8+IKS", GitCommit:"0a5a9d717cf2cedaf9b7ab8ce758fd3ab2638d90", GitTreeState:"clean", BuildDate:"2020-01-16T19:49:53Z", GoVersion:"go1.12.12", Compiler:"gc", Platform:"linux/amd64"}
```
    
## Pod Security Policy検証
事前準備として、Namespace, SA, Rolebindingを作成します。

- Namespaceに紐付けたSA(fake-user)を作成する
- SAに対して`edit`の権限を有するClusterRoleを紐づける
    - `kubectl create rolebinding -n psp-example fake-editor --clusterrole=edit --serviceaccount=psp-example:fake-user`

続いて、PodSecurityPolicyを作成します。
ここでは、`privileged`の部分を`false`にすることで特権コンテナの作成を許可しないというポリシーを定義します。
        
```yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: example
spec:
  privileged: false  # Don't allow privileged pods!
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  runAsUser:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  volumes:
  - '*'

```

また、クラスタ作成時に作成されているPodSecurityPolicy(`ibm-privileged-psp`)では、`PRIV=true`となっているので、検証のために削除しておきます。
PodSecurityPolicyに関しては、複数のポリシーの重ねがけの場合に**明示的なAllowが優先される**ため、このようなデフォルトのポリシーが存在する場合は注意が必要です。

```console
# デフォルトで作成されている複数のPodSecurityPolicyが作成されている
# PodSecurityPolicy(ibm-privileged-psp)では、PRIV=trueとなっている
$ k get psp
NAME                        PRIV    CAPS                                                                                                                  SELINUX    RUNASUSER          FSGROUP     SUPGROUP    READONLYROOTFS   VOLUMES
example                     false                                                                                                                         RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-anyuid-hostaccess-psp   false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-anyuid-hostpath-psp     false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-anyuid-psp              false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim
ibm-privileged-psp          true    *                                                                                                                     RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-restricted-psp          false                                                                                                                         RunAsAny   MustRunAsNonRoot   MustRunAs   MustRunAs   false            configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim

# 検証のためにibm-privileged-pspを削除する
$ k delete psp ibm-privileged-psp
podsecuritypolicy.extensions "ibm-privileged-psp" deleted
    
$ k get psp
NAME                        PRIV    CAPS                                                                                                                  SELINUX    RUNASUSER          FSGROUP     SUPGROUP    READONLYROOTFS   VOLUMES
example                     false                                                                                                                         RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-anyuid-hostaccess-psp   false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-anyuid-hostpath-psp     false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-anyuid-psp              false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim
ibm-restricted-psp          false                                                                                                                         RunAsAny   MustRunAsNonRoot   MustRunAs   MustRunAs   false            configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim
```

この状態では、ユーザー(`fake-user`)に対して`edit`の権限のみを付与しているため、特権コンテナ以外のコンテナも作成することができない状態になります。

```console
# Adminユーザーはuse権限を有しているのでコンテナは作成できる
$ kubectl apply -n psp-example -f- <<EOF
> apiVersion: v1
> kind: Pod
> metadata:
>   name:      privileged
> spec:
>   containers:
>     - name:  pause
>       image: k8s.gcr.io/pause
>       securityContext:
>         privileged: true
> EOF
pod/pause created

# edit権限しか有していないユーザーではコンテナを作成できない
$ kubectl --as=system:serviceaccount:psp-example:fake-user -n psp-example create -f- <<EOF
> apiVersion: v1
> kind: Pod
> metadata:
>   name:      privileged
> spec:
>   containers:
>     - name:  pause
>       image: k8s.gcr.io/pause
>       securityContext:
>         privileged: true
> EOF
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]
```

次に、`use`の権限を有したロールをユーザー(`fake-user`)に紐づけます。

```console
$ kubectl -n psp-example create role psp:unprivileged \
>     --verb=use \
>     --resource=podsecuritypolicy \
>     --resource-name=example
role.rbac.authorization.k8s.io/psp:unprivileged created

$ kubectl -n psp-example create rolebinding fake-user:psp:unprivileged \
>     --role=psp:unprivileged \
>     --serviceaccount=psp-example:fake-user
rolebinding.rbac.authorization.k8s.io/fake-user:psp:unprivileged created
```

`use`の権限を持つユーザーで`privileged: true`の設定をしたpodを作成しようとすると、作成時にエラーとなります。

```console
# リクエストの検証はされているが、ポリシーに準拠しているので拒否はされない
$ kubectl --as=system:serviceaccount:psp-example:fake-user -n psp-example create -f- <<EOF
> apiVersion: v1
> kind: Pod
> metadata:
>   name:      pause
> spec:
>   containers:
>     - name:  pause
>       image: k8s.gcr.io/pause
> EOF
pod/pause created

# 特権コンテナを作成しようとしているのでリクエストが拒否される
$ kubectl --as=system:serviceaccount:psp-example:fake-user -n psp-example create -f- <<EOF
> apiVersion: v1
> kind: Pod
> metadata:
>   name:      privileged
> spec:
>   containers:
>     - name:  pause
>       image: k8s.gcr.io/pause
>       securityContext:
>         privileged: true
> EOF
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]
```

## Pod Security Context検証
### RunAsUser / fsGroup
下記の2つの設定を用いて、Pod Security Contextを検証します。
`fsGroup`と似た設定項目として`runAsGroup`もありますが、`runAsGroup`はプロセスに対してGIDを指定するという設定なので**GIDを設定する対象が異なります。**

- `RunAsUser`：UIDを指定して特定のユーザーでコンテナ内のプロセスを実行する
- `fsGroup`：GIDを指定してコンテナのボリュームやボリューム内で作成されたファイルにGIDをセットする

今回は下記のマニュフェストファイルを利用します。
pod起動時に、`sleep 1h`のコマンドを実行することで、プロセスのUIDを確認します。
また、Pod用の一時的なディスク領域として`/data/demo`のパスで`emptyDir`を作成して、作成されたボリュームのGIDを確認します。 

```yaml:security-context.yaml
apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  volumes:
  - name: sec-ctx-vol
    emptyDir: {}
  containers:
  - name: sec-ctx-demo
    image: busybox
    command: [ "sh", "-c", "sleep 1h" ]
    volumeMounts:
    - name: sec-ctx-vol
      mountPath: /data/demo
```

podを作成して、コンテナのシェルを取得してプロセスのUIDを確認します。
全てのプロセスに対して、`UID=1000`がセットされていることがわかります。

```console
$ kubectl apply -f https://k8s.io/examples/pods/security/security-context.yaml
pod/security-context-demo created

$ kubectl exec -it security-context-demo -- sh

/ $ ps aux
PID   USER     TIME  COMMAND
    1 1000      0:00 sleep 1h
    7 1000      0:00 sh
   14 1000      0:00 ps aux
```

続いて、作成されたボリュームのGIDを確認します。 
作成した`data/demo`に関して、所有グループの箇所に`GID=2000`がセットされていることがわかります。（ボリュームの所有者は`root`のままです。）

```console
/ $ ls -al
total 48
drwxr-xr-x    1 root     root          4096 Feb 11 05:19 .
drwxr-xr-x    1 root     root          4096 Feb 11 05:19 ..
drwxr-xr-x    2 root     root         12288 Dec 23 19:21 bin
drwxr-xr-x    3 root     root          4096 Feb 11 05:19 data
drwxr-xr-x    5 root     root           360 Feb 11 05:19 dev
drwxr-xr-x    1 root     root          4096 Feb 11 05:19 etc
drwxr-xr-x    2 nobody   nogroup       4096 Dec 23 19:21 home
dr-xr-xr-x  218 root     root             0 Feb 11 05:19 proc
drwx------    2 root     root          4096 Dec 23 19:21 root
dr-xr-xr-x   13 root     root             0 Feb  9 06:13 sys
drwxrwxrwt    2 root     root          4096 Dec 23 19:21 tmp
drwxr-xr-x    3 root     root          4096 Dec 23 19:21 usr
drwxr-xr-x    1 root     root          4096 Feb 11 05:19 var
/ $ ls -al /data
total 12
drwxr-xr-x    3 root     root          4096 Feb 11 05:19 .
drwxr-xr-x    1 root     root          4096 Feb 11 05:19 ..
drwxrwsrwx    2 root     2000          4096 Feb 11 05:18 demo
```

また、作成したボリュームでファイルを作成して確認すると、所有者として`UID=1000`、所有グループとして`GID=2000`がセットされていることがわかります。

```console
/ $ cd data/demo
/data/demo $ echo hello > demofile
/data/demo $ ls -al
total 12
drwxrwsrwx    2 root     2000          4096 Feb 11 05:22 .
drwxr-xr-x    3 root     root          4096 Feb 11 05:19 ..
-rw-r--r--    1 1000     2000             6 Feb 11 05:22 demofile
```

## Security Context検証
### Linux Capabilities
今回はSecurity Contextとして設定できる項目の中でも、Linux Capabilitiesを設定します。
Linux Capabilitiesは、rootに紐づいた権限を分割・グループ化して必要な権限を付与する仕組みのことを指します。

参考： https://gihyo.jp/admin/serial/01/linux_containers/0042

マニュフェストファイルの中では、`pod.spec.containers.securityContext`の部分でCapabilitiesを設定します。

```yaml:security-context-demo-4
apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-4
spec:
  containers:
  - name: sec-ctx-4
    image: gcr.io/google-samples/node-hello:1.0
    securityContext:
      capabilities:
        add: ["NET_ADMIN", "SYS_TIME"]
```

コンテナに紐づく設定としてLinux Capabilitiesを設定しているため、コンテナ作成後にコンテナのシェルを起動して確認します。

コンテナ内のプロセスが持つCapabilitiesは`cat proc/1/status | grep Cap*`で確認することができます。
Kubernetesが提供しているExamples内の`security-context-3.yaml`では、Capabilitiesを設定していないため下記のようになります。

```console
$ k apply -f https://k8s.io/examples/pods/security/security-context-3.yaml
pod/security-context-demo-3 created

$ k exec security-context-demo-3 -it bash

root@security-context-demo-3:/# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   4332   764 ?        Ss   09:51   0:00 /bin/sh -c node server.js
root         6  0.1  0.5 772120 22796 ?        Sl   09:51   0:00 node server.js
root        11  0.0  0.0  20240  3220 pts/0    Ss   09:52   0:00 bash
root        16  0.0  0.0  17496  2120 pts/0    R+   09:52   0:00 ps aux

root@security-context-demo-3:/# cat proc/1/status | grep Cap*
CapInh:	00000000a80425fb
CapPrm:	00000000a80425fb
CapEff:	00000000a80425fb
CapBnd:	00000000a80425fb
CapAmb:	0000000000000000

root@security-context-demo-3:/# getpcaps 1
Capabilities for `1': = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+eip
```

注意点として、IKSでデフォルトで作成されているPodSecurityPolicyの中で今回検証したいCapabilitiesが許可されていません。
Admin権限のユーザーで検証を行う際にはデフォルトのポリシーを削除することをお勧めします。

```console
# CAPSの箇所でCapabilitiesが設定されている
$ k get psp
NAME                        PRIV    CAPS                                                                                                                  SELINUX    RUNASUSER          FSGROUP     SUPGROUP    READONLYROOTFS   VOLUMES
example                     false                                                                                                                         RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-anyuid-hostaccess-psp   false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-anyuid-hostpath-psp     false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
ibm-anyuid-psp              false   SETPCAP,AUDIT_WRITE,CHOWN,NET_RAW,DAC_OVERRIDE,FOWNER,FSETID,KILL,SETUID,SETGID,NET_BIND_SERVICE,SYS_CHROOT,SETFCAP   RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim
ibm-restricted-psp          false                                                                                                                         RunAsAny   MustRunAsNonRoot   MustRunAs   MustRunAs   false            configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim

# PodSecurityPolicyの中でCapabilitiesが設定されていないのでpodの作成自体ができない
$ k apply -f security-context-pod4.yaml
  Error from server (Forbidden): error when creating "security-context-pod4.yaml": pods "security-context-demo-4" is forbidden: unable to validate against any pod security policy: 
  [`spec.containers[0].securityContext.capabilities.add: Invalid value: "NET_ADMIN": capability may not be added
    spec.containers[0].securityContext.capabilities.add: Invalid value: "SYS_TIME": capability may not be added 
    spec.containers[0].securityContext.capabilities.add: Invalid value: "NET_ADMIN": capability may not be added 
    spec.containers[0].securityContext.capabilities.add: Invalid value: "SYS_TIME": capability may not be added 
    spec.containers[0].securityContext.capabilities.add: Invalid value: "NET_ADMIN": capability may not be added 
    spec.containers[0].securityContext.capabilities.add: Invalid value: "SYS_TIME": capability may not be added 
    spec.containers[0].securityContext.capabilities.add: Invalid value: "NET_ADMIN": capability may not be added 
    spec.containers[0].securityContext.capabilities.add: Invali`d value: "SYS_TIME": capability may not be added]
```

PodSecurityPolicy削除後に、`security-context-4.yaml`を利用してpodを作成した上で、先ほどと同様に、`proc/1/status`を確認します。

ビットが変化していることがわかりますが、どのようなCapabilitiesが付与されているかは不明です。
確認する際には、`getpcaps <PID>`コマンドを利用することでプロセスに付与されているCapabilitiesを確認できます。
これにより、プロセスに`cap_net_admin`と`cap_sys_time`がCapabilitiesとして付与されていることがわかります。
        
```console
$ k apply -f https://k8s.io/examples/pods/security/security-context-4.yaml
pod/security-context-demo-4 created

$ k exec security-context-demo-4 -it bash

$ k get po
NAME                      READY   STATUS    RESTARTS   AGE
security-context-demo-4   1/1     Running   0          9s

root@security-context-demo-4:/# cat /proc/1/status | grep Cap
CapInh:	00000000aa0435fb
CapPrm:	00000000aa0435fb
CapEff:	00000000aa0435fb
CapBnd:	00000000aa0435fb
CapAmb:	0000000000000000

root@security-context-demo-4:/# getpcaps 1
Capabilities for `1': = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_admin,cap_net_raw,cap_sys_chroot,cap_sys_time,cap_mknod,cap_audit_write,cap_setfcap+eip
```

PodSecurityPolicyのマニュフェストファイル内でCapabilitiesの許可設定をすることも可能です。
`allowedCapabilities`で指定したCapabilitiesを許可したり、`RequiredDropCapabilities`で任意のCapabilitiesを拒否することも可能です。
https://kubernetes.io/docs/concepts/policy/pod-security-policy/#capabilities

```yaml:allowAllCapabilities.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: example
spec:
  privileged: false  
  # Required to prevent escalations to root.
  allowPrivilegeEscalation: false
  # This is redundant with non-root + disallow privilege escalation,
  # but we can provide it for defense in depth.
  allowedCapabilities:
  - '*'
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  runAsUser:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  volumes:
    - '*'
```

# Pod Security Policyに関する注意点
Pod Security Policy (PSP) は、v1.17時点では beta 機能として提供されています。
ただし、2020年1月末時点で、Pod Security Policy(PSP)はGA化されない方向で進んでいます。
https://github.com/kubernetes/enhancements/issues/5

代替策として [Gatekeeper](https://github.com/open-policy-agent/gatekeeper) が挙がっており、現在も議論が続いています。
特に、ポリシーの方式の違いを踏まえてどのように移行をスムーズに進めるかという部分が議論されています。
（許可設定を追加するPSPと違い、Gatekeeper は拒否設定を追加する方式のようです）