OpenShiftでSCCやroleの追加設定をしたら確認しようという話

## 背景
- あるソフトウェアをOpenShiftクラスターで稼働させる際に、以下のようなコマンドでService AccountへのSCCの追加を行なった。しかし設定後の確認方法を理解していなかったため、設定ミスがあったことに気づかなかった。その結果、他のpodを起動するユーザーまで変わってしまい、podが起動できなかったり、うまく動作しない問題が発生した・・・。

    ```
    oc adm policy add-scc-to-user <scc_name> -z <serviceaccount_name>
    ``` 
- 同様に、ユーザーへのロールの設定を行った際にも確認方法がよく分からなかった。
- そもそもSCCやロールについて十分理解して設定すべきだが、最低限設定した内容が想定通りになっているかを確認する必要があると痛感した。ただ、意外とSCCやロールの確認方法が分かりづらかったので手順を残しておく。
- 本記事はOpenShift Container Platform 4.7を前提としています。

## 参考にさせていただいた情報
- [OpenShift 4.7マニュアル - SCC (Security Context Constraints) の管理](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/authentication_and_authorization/managing-pod-security-policies)
- [【OpenShift】oc adm policy add-scc-to-userでの変更とClusterRoleBindingの関係](https://www.mtioutput.com/entry/openshift-scc-adduser)
- [OpenShift 4.7マニュアル - RBAC の使用によるパーミッションの定義および適用](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/authentication_and_authorization/using-rbac)
- [Security Context Constrains(SCC)の適用プロセス on OpenShift](https://rheb.hatenablog.com/entry/scc-process-on-openshift-202008)

## SCCやRoleの設定について理解したこと
- `oc adm policy add-scc-to-user`コマンドや `oc policy add-role-to-user`コマンドでユーザーへSCCやRoleの追加を行なった場合、RoleBindingやClustomerRoleBindingというRoleとユーザーとの結び付けを行うリソースが作成される。（[参考情報](https://www.mtioutput.com/entry/openshift-scc-adduser)）
- CustomerRoleBindingとRoleBindingの違いは、CustomerRoleBindingはクラスター全体の権限設定を行うのに対し、RoleBindingはネームスペース内の権限設定を行う点にある。([参考情報](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/authentication_and_authorization/using-rbac#authorization-overview_using-rbac))

## 学んだこと（教訓)
- `oc adm policy add-scc-to-user`コマンドや `oc policy add-role-to-user`コマンドなどでSCCやRoleの追加を行なったら、その設定が想定通りにRoleBindingやClustomerRoleBindingに反映されているか（設定ミスがないか）確認が必要だということ。


## SCCやロールの追加と確認方法
### パターン1. `oc adm policy add-scc-to-user`コマンドでService AccountへのSCC追加を行なう場合

- 設定コマンド

```
oc adm policy add-scc-to-user <scc_name> -z <serviceaccount_name>
```

- 確認コマンド

```
oc describe clusterrolebinding system:openshift:scc:<scc_name>
```
または

```
oc get clusterrolebinding system:openshift:scc:<scc_name> -o wide
```

実際に実行した例は以下のとおり。

- 設定コマンド例

```
oc adm policy add-scc-to-user anyuid -z gitlab-runner-sa
```
   - このコマンドは、「現在のプロジェクトのService Account `gitlab-runner-sa`にSCC `anyuid` を追加する」という意味。
   - `-z`オプションについては[OpenShiftバージョン3.9のマニュアル](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/3.9/html/cluster_administration/admin-guide-manage-scc#add-scc-to-user-group-project)に記載がある。

>重要  
>上記の -z フラグについては、誤字を防ぎ、アクセスが指定されたサービスアカウントのみに付与されるため、その使用をを強く推奨します。プロジェクトにいない場合は、-n オプションを使用して、それが適用されるプロジェクトの namespace を指定します。 

- 確認コマンドと出力の例
  - Role:以下にSCCの情報が、Subjects:以下に設定対象のService Account情報が表示される。
  - 以下の場合、namespace `gitlab-system` のService Accout `gitlab-runner-sa`にSCC `anyuid`が設定されていることがわかる。
  - うまく設定されていない場合は、このclusterrolebindingのSublects:が正しくなかったり、clusterrolebinding自体が存在しなかったりする。

```
$ oc describe clusterrolebinding system:openshift:scc:anyuid
Name:         system:openshift:scc:anyuid
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  system:openshift:scc:anyuid
Subjects:
  Kind            Name              Namespace
  ----            ----              ---------
  ServiceAccount  gitlab-runner-sa  gitlab-system
```
または

```
oc get clusterrolebinding system:openshift:scc:anyuid -o wide
NAME                          ROLE                                      AGE    USERS   GROUPS   SERVICEACCOUNTS
system:openshift:scc:anyuid   ClusterRole/system:openshift:scc:anyuid   105d                    gitlab-system/gitlab-runner-sa
```
  - このコマンドの場合は、表示がシンプルだがROLEとSERVICEACCOUNTSの内容を確認すればよい。

### パターン2.  `oc policy add-role-to-user`コマンドで特定のプロジェクトでService Accountへのロールの追加を行なう場合

- 設定コマンド

```
oc policy add-role-to-user <role_name> "system:serviceaccount:<namespace_name>:<serviceaccount_name>" --namespace=<namespace_name>
```

- 確認コマンド

```
oc describe rolebinding <role_name> -n <namespace_name>
```
または

```
oc get rolebinding <role_name> -n <namespace_name> -o wide
```

実際に実行した例は以下のとおり。

- 設定コマンド例

```
oc policy add-role-to-user system:image-puller "system:serviceaccount:sample-stg:default" --namespace=sample-dev
```
   - このコマンドは、「sample-devプロジェクトにて、sample-stgプロジェクトのService Account `default`にロール `system:image-puller` を追加する」という意味。

- 確認コマンドと出力の例
  - Role:以下にロールの情報が、Subjects:以下に設定対象のService Account情報が表示される。
  - 以下の場合、namespace`sample-stg`のService Accout `default`にClusterRole `system:image-puller`が設定されていることがわかる。
  - うまく設定されていない場合は、このrolebindingのSublects:が正しくなかったり、rolebinding自体が存在しなかったりする。

```
$ oc describe rolebinding system:image-puller -n sample-dev
Name:         system:image-puller
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  system:image-puller
Subjects:
  Kind            Name     Namespace
  ----            ----     ---------
  ServiceAccount  default  sample-stg
```
または

```
$ oc get rolebinding system:image-puller -o wide -n sample-dev
NAME                  ROLE                              AGE   USERS   GROUPS   SERVICEACCOUNTS
system:image-puller   ClusterRole/system:image-puller   14h                    sample-stg/default
```
  - このコマンドの場合は、表示がシンプルだがROLEとSERVICEACCOUNTSの内容を確認すればよい。

## おまけ. `oc adm policy`コマンドと`oc policy`コマンドの違いは？
- 上記の内容では`oc adm policy`コマンドと`oc policy`コマンドを例に説明をしたが、そもそも両者がどう違うのかよくわからなかった。
- [CLIリファレンス](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/cli_tools/index)を調べたところ、[oc policyコマンド](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/cli_tools/_policy)は「上級開発者のCLIコマンド」に分類されており、[oc adm policyコマンド](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.7/html/cli_tools/_policy-2)は「OpenShift CLI 管理者コマンド」に分類されていることがわかった。
- それぞれの説明は以下のとおり。　　
    - `oc adm policy`コマンド　「クラスター上のロールおよびポリシーを管理します。」
    - `oc policy`コマンド　「認可ポリシーを管理します。」
        - 例: edit ロールの現在のプロジェクトの user1 への追加
- つまり両者の違いは以下のように理解した。
    - `oc adm policy`コマンドは管理者向けでクラスター全体のロールやポリシーを管理する。
    - `oc policy`コマンドは開発者向けでネームスペース内のロールやポリシーを管理する。