[Kubernetes]ユーザ管理とRBACについて確認する

#はじめに
今回はRBACの動作を確認していたら、ユーザ管理の話になってきました。

詳しく知りたい方は、この記事よりも以下のさくらインターネットさんの記事の方が詳しく解説されていますので、こちらをご覧になった方がよいです。

[Kubernetesのユーザー管理と認証・権限確認機構を理解しよう](https://knowledge.sakura.ad.jp/21129/)

#ユーザ認証の設定
Kubernetesではauthenticationモジュールが標準でいくつか提供されているのですが、今回は「X509 Client Certs」を使用します。

##秘密鍵の作成
秘密鍵「user01.key」を作成し、署名リクエストファイル「user01.csr」を作成します。

```
$ openssl genrsa -out user01.key 2048
Generating RSA private key, 2048 bit long modulus
.....................................+++
.......................................................................+++
e is 65537 (0x10001)
$ openssl req -new -key user01.key -out user01.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:user01
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:user01
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
```

##署名ファイルの作成
署名ファイル「user01.crt」を作成します。

```
$ sudo openssl x509 -req -in user01.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out user01.crt -days 10000

Signature ok
subject=/C=XX/L=Default City/O=user01/CN=user01
Getting CA Private Key

$ ls
user01.crt  user01.csr  user01.key
```

##証明書のAPIサーバへの追加
作成した証明書をAPIサーバに追加します。

```
$ kubectl config set-credentials user01 --client-certificate=user01.crt --client-key=user01.key --embed-certs=true
User "user01" set.
```

#Contextの設定

##クラスタ名と既存Contextの確認

```
$ kubectl config get-clusters
NAME
kubernetes
$ kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin
```

##Contextの作成
user01用のContextを作成します。

```
$ kubectl config set-context user01-context --user=user01 --cluster=kubernetes
Context "user01-context" created.
$ kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin
          user01-context                kubernetes   user01
```
##Contextの切り替え

```
$ kubectl config use-context user01-context
Switched to context "user01-context".
$ kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
          kubernetes-admin@kubernetes   kubernetes   kubernetes-admin
*         user01-context                kubernetes   user01
```

##確認
現時点ではuser01に権限が設定されていないため、kubectlコマンドでエラーになることを確認します。

```
$ kubectl get pod
Error from server (Forbidden): pods is forbidden: User "user01" cannot list resource "pods" in API group "" in the namespace "default"
```

確認できたら、元のContextに戻します。

```
$ kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
```

#RBACの設定
これまで作成したuser01に対して権限を設定するために、RBACを使用します。
RBACにはRole/RoleBindingとClusterRole/ClusterRoleBindingの2通りがあります。Role/RoleBindingはNamespaceレベル、ClusterRole/ClusterRoleBindingはClusterレベルと設定範囲が異なります。

[Using RBAC Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#referring-to-resources)

##ClusterRole/ClusterRoleBindingの設定
以下のマニフェストですべてのAPI Groupのすべてのリソースでget/list/watchができる設定にします。

```clusterRole.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: readonly-for-all
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["*"]
  verbs: ["get", "list", "watch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: readonly-for-test
subjects:
- kind: User
  name: user01
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: readonly-for-all
  apiGroup: rbac.authorization.k8s.io
```

```
$ kubectl apply -f clusterRole.yaml
clusterrole.rbac.authorization.k8s.io/readonly-for-all created
clusterrolebinding.rbac.authorization.k8s.io/readonly-for-test created
```

設定内容を確認します。

```
$ kubectl describe clusterrole readonly-for-all
Name:         readonly-for-all
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{},"name":"readonly-for-all"},"rules":[{"apiGr...
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  *.*        []                 []              [get list watch]
             [*]                []              [get]
             [*]                []              [list]
             [*]                []              [watch]
$ kubectl describe clusterrolebinding readonly-for-test
Name:         readonly-for-test
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"readonly-for-test"},"roleRef...
Role:
  Kind:  ClusterRole
  Name:  readonly-for-all
Subjects:
  Kind  Name    Namespace
  ----  ----    ---------
  User  user01
```

##動作確認
Contextを切り替えて、RBACの動作を確認します。

```
$ kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin
          user01-context                kubernetes   user01
$ kubectl config use-context user01-context
Switched to context "user01-context".
$ kubectl config current-context
user01-context
```

```
$ kubectl get pod
No resources found in default namespace.
$ kubectl apply -f nginx.yaml
Error from server (Forbidden): error when creating "nginx.yaml": pods is forbidden: User "user01" cannot create resource "pods" in API group "" in the namespace "example"
```

Podがないのですが、RBACを設定する前はエラーになっていた kubectl get pod コマンドが正常に返ってきています。
また、Podの作成は権限がないので失敗していますね。

#まとめ
ユーザ認証の流れは以下のようになります。今回の検証環境はオンプレ環境のため、APIサーバとクライアントが同一ノードになります。
なので、ユーザの切り替えがContextの切り替えだけになってしまっていて、OSのユーザは変わっていないです。おそらくクラウド上のクラスタに対して、クラスタ外からアクセスする際にこの設定が活きてくるのだと思います。


>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/510ff76e-a21a-d8bc-de01-4e16742b2051.png)
>引用： [Kubernetesのユーザー管理と認証・権限確認機構を理解しよう](https://knowledge.sakura.ad.jp/21129/) 

RBAC自体はリソースを紐づけていけばよいですし、RoleやClusterRoleもデフォルトで用意されているものもありますので、わかりやすいかなと思います。

P.S.
さくらインターネットさんの記事がとても勉強になりました。ありがとうございました。