ICPでNamespaceのPodSecurityPolicy設定を変更する

ICPではWebコンソールからNamespaceを作成する際、PodSecurityPolicyを設定できますが、このWebコンソールでのNamespaceへのPodSecurityPolicyの設定はNamespaceの作成時にしかできず、後から変更するとかができないようなので、コマンドで後から変更する方法を確認しました。

## 挙動の確認

Webコンソールで、`mynamespace`というNamespaceを作成し、`ibm-anyuid-psp`を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86449/f3db7b73-0101-958d-2ada-81c344b763f4.png)

Webコンソールで、NamespaceにPodSecurityPolicyが設定されたことが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86449/633782f2-417e-cd6c-71cf-a457a953eb1b.png)

各PodSecurityPolicyについては以下のリンク先に説明があります。この記事の主眼である後から変更するコマンドもこのリンク先に記載があります。

- https://github.com/IBM/cloud-pak/tree/master/spec/security/psp

Kubernetes的には、NamespaceとPodSecurityPolicyは直接関連しません。ICPでは、各PodSecuriyPolicyが利用可能なClusterRoleが事前定義されていて、ICPのWebコンソールでNamespaceにPodSecurityPolicyを設定すると、ICPが裏でそのNamespaceの全てのServiceAccountに、そのPodSecuriyPolicyが利用可能なClusterRoleをバインドするRoleBindingを作成しています。

なお、PodSecurityPolicyは[Admission Controller](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#podsecuritypolicy)です。ICPの場合、apiserverの起動引数を確認すると、`--enable-admission-plugins`引数に`PodSecurityPolicy`が含まれていることが確認できます。

```shell-session
$ ps -ef | grep -v grep | grep "hyperkube apiserver"
root     17928 17888 19 Feb12 ?        16-22:38:44 /hyperkube apiserver --secure-port=8001 --bind-address=0.0.0.0 --advertise-address=9.188.124.130 --endpoint-reconciler-type=lease --insecure-port=0 --anonymous-auth=false --etcd-servers=https://9.188.124.130:4001 --etcd-cafile=/etc/cfc/conf/etcd/ca.pem --etcd-certfile=/etc/cfc/conf/etcd/client.pem --etcd-keyfile=/etc/cfc/conf/etcd/client-key.pem --runtime-config=batch/v2alpha1,extensions/v1beta1=true,extensions/v1beta1/podsecuritypolicy=true,admissionregistration.k8s.io/v1alpha1 --enable-admission-plugins=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,PodSecurityPolicy,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,Priority,EventRateLimit,PodNodeSelector,PodTolerationRestriction --admission-control-config-file=/etc/cfc/conf/admission-control-config.yaml --repair-malformed-updates=false --oidc-issuer-url=https://mycluster.icp:9443/oidc/endpoint/OP --oidc-client-id=434dc3ba50ca1471a2e88f6ce3c027d1 --oidc-ca-file=/etc/cfc/conf/ca.crt --oidc-groups-claim=teamRoleMappings --tls-cert-file=/etc/cfc/conf/server.cert --tls-private-key-file=/etc/cfc/conf/server.key --kubelet-client-certificate=/etc/cfc/conf/kubelet-client.crt --kubelet-client-key=/etc/cfc/conf/kubelet-client.key --client-ca-file=/etc/cfc/conf/ca.crt --service-account-key-file=/etc/cfc/conf/server.key --authorization-mode=RBAC --min-request-timeout=300 --allow-privileged --requestheader-client-ca-file=/etc/cfc/conf/front/front-proxy-ca.pem --requestheader-username-headers=X-Remote-User --requestheader-group-headers=X-Remote-Group --requestheader-allowed-names=mycluster.icp,aggregator --requestheader-extra-headers-prefix=X-Remote-Extra- --proxy-client-cert-file=/etc/cfc/conf/front/front-proxy-client.pem --proxy-client-key-file=/etc/cfc/conf/front/front-proxy-client-key.pem --enable-bootstrap-token-auth --v=2 --profiling=false --service-cluster-ip-range=10.0.0.0/16
$
```

事前定義されているPodSecurityPolicyを確認します。

```shell-session
$ kubectl get psp | grep ibm-
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
$
```

事前定義されているClusterRoleを確認します。

```shell-session
$ kubectl get clusterrole | grep ibm-
ibm-anyuid-clusterrole                                                 85d
ibm-anyuid-hostaccess-clusterrole                                      85d
ibm-anyuid-hostpath-clusterrole                                        85d
ibm-cert-manager-cert-manager                                          84d
ibm-privileged-clusterrole                                             85d
ibm-restricted-clusterrole                                             85d
$
```

これらのClusterRoleではそれぞれ使用可能なPodSecurityPolicyが設定されています。例えば、`ibm-anyuid-clusterrole`の内容は以下のようになっており、`ibm-anyuid-psp`という名前の`podsecuritypolicies`というリソースを`use`できるClusterRoleになっています。

```shell
kubectl get clusterrole ibm-anyuid-clusterrole -o yaml
```

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{},"name":"ibm-anyuid-clusterrole"},"rules":[{"apiGroups":["extensions"],"resourceNames":["ibm-anyuid-psp"],"resources":["podsecuritypolicies"],"verbs":["use"]}]}
  creationTimestamp: 2019-02-12T05:22:05Z
  name: ibm-anyuid-clusterrole
  resourceVersion: "291"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/ibm-anyuid-clusterrole
  uid: 22c26a9d-2e86-11e9-97b5-fa163e2fb2ab
rules:
- apiGroups:
  - extensions
  resourceNames:
  - ibm-anyuid-psp
  resources:
  - podsecuritypolicies
  verbs:
  - use
```

Webコンソールから作成した`mynamespace`というNamespace内のRoleBindingを確認すると、RoleBindingが作成されていることが確認できます。

```shell-session
$ kubectl get rolebinding -n mynamespace
NAME                                 AGE
ibm-anyuid-clusterrole-rolebinding   84m
$
```

このRoleBinddingが、このNamespace内の全てのServiceAccount（`system:serviceaccounts:mynamespace`というグループ）に、事前定義された`ibm-anyuid-clusterrole`というClusterRoleをバインドしています。

```shell
kubectl get rolebinding -n mynamespace -o yaml
```

```yaml
apiVersion: v1
items:
- apiVersion: rbac.authorization.k8s.io/v1
  kind: RoleBinding
  metadata:
    creationTimestamp: 2019-05-08T05:35:34Z
    name: ibm-anyuid-clusterrole-rolebinding
    namespace: mynamespace
    resourceVersion: "14354108"
    selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/mynamespace/rolebindings/ibm-anyuid-clusterrole-rolebinding
    uid: 19d161f0-7153-11e9-95d2-fa163e2fb2ab
  roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: ClusterRole
    name: ibm-anyuid-clusterrole
  subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: Group
    name: system:serviceaccounts:mynamespace
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""
```

## コマンドによるNamespaceへのPodSecurityPolicyの設定

例えば、`mynamespace`というNamespaceに`ibm-privileged-psp`を追加で割り当てたい場合、以下のようなyamlを`kubectl apply -f`します。

```yaml:ibm-privileged-clusterrole-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ibm-privileged-clusterrole-rolebinding
  namespace: mynamespace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: ibm-privileged-clusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:serviceaccounts:mynamespace
```

あるいは、yamlを作成せずコマンドで直接作成する場合は以下のようにします。

```shell
kubectl create rolebinding -n mynamespace ibm-privileged-clusterrole-rolebinding \
  --clusterrole=ibm-privileged-clusterrole \
  --group=system:serviceaccounts:mynamespace
```

Webコンソールからも`ibm-privileged-psp`のPodSecurityPolicyが追加されたことが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86449/8e326c34-e44d-b79b-5b21-b2e102b647ea.png)

もしPodSecurityPolicyの割り当てを削除したい場合はRoleBindingを削除すればよいです。

```shell
kubectl delete rolebinding ibm-privileged-clusterrole-rolebinding -n mynamespace
```