KubernethesにX509 Client CertsのUserAccountを追加する

開発環境がローカルではそろそろつらくなってきたので、複数人でノードを共有して開発をするようにしたいと思いました。
namespaceで分けるのかな？とか漠然と考えていますが、まずはk8sのユーザーを作成せねばならんということで、手順です。

k8sにはUserAccountとServiceAccountと2種類アカウントの種類があるようです。UserAccountは人間用、ServiceAccountはPod等で実行されるプロセス用だそうです。
また方式もX509 Client Certs, Token, Password, OpenID Connectなどいろいろあるみたいです。

TL;DR

X509 Client CertsでUserAccountを作成し、ClusterRoleBindingに追加しています。

https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/
公式Documents: https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs

今回は、Linuxユーザーのmurataユーザーが管理者、deroriがUserAccountを作るユーザーとします。


# 秘密鍵を作る

追加したいユーザーで秘密鍵を作ります。

```
[derori@murata ~]$ openssl genrsa -out derori-tester.pem 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
.................................+++++
........+++++
e is 65537 (0x010001)
```


# CSRを作る

CNにユーザ名を付けてCSRを作成します。
RoleBindingやRoleについては別途ググってください。
OにはGroup名が入れられるみたいです。


```
[derori@murata ~]$ openssl req -new -key derori-tester.pem -out derori-tester.csr -subj "/CN=derori-tester"
[derori@murata ~]$ openssl req -noout -text -in derori-tester.csr
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: CN = derori-tester
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:cc:69:23:97:07:9e:f8:54:79:f4:a0:48:c7:5f:
                    d5:44:63:23:8e:2f:0b:80:8c:ac:ac:7e:a4:7e:bc:
~~snip;

```

# base64にしてk8sにマニフェスト食わせる

k8sに証明書をリクエストします。

```
[derori@murata ~]$ cat derori-tester.csr | base64 | tr -d '\n'
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFV~~SNIP;
```


↓ここからk8sにアクセスできるユーザーでやる。(murataユーザー

```
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
  name: request-user-account-derori
spec:
  groups:
  - system:authenticated
  request: <上のbase64化したCSRを貼り付ける。>
usages:
  - digital signature
  - key encipherment
  - client auth
EOF
```

```
murata:~ $ cat <<EOF | kubectl apply -f -
> apiVersion: certificates.k8s.io/v1beta1
> kind: CertificateSigningRequest
> metadata:
>   name: request-user-account-derori
> spec:
>   groups:
>   - system:authenticated
>   request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ2RqQ0NBVjRDQVFB
khYOVZFWXlPT0x3dUFqS3lzZnFSK3ZQYVZjejB1d01qRW4ydmxqQ3liZUhFTDJzTHcKVmtpUEZoV2lMcn
6Ti9HcnpmWENWSno5aS9hd0swMnNGMHNPc3pZUGNqRExDVDl1ZWRFMUh6b3NrU21KSlF5RUMKektnT3Zm
UhqUGthUHhaVTZIT2s3R2FCc25KaEpTRUxmelZxVkVTblZ0akxzUGFzOGNvZ1pqVFRDWjBpVHRMdWYKQj
xUGFsVkgzcDBwRkRRR3Z0TlVzMTJUeE5DTU05YktwMXNzSkZic2d2RXB0M3h5MVpNajczWnlMYWJYZ0F2
>   usages:
>   - digital signature
>   - key encipherment
>   - client auth
> EOF
certificatesigningrequest.certificates.k8s.io/request-user-account-derori created
```

Pendingなcsrが追加されている。

```
murata:~ $ kubectl get csr
NAME                          AGE   REQUESTOR          CONDITION
request-user-account-derori   66s   kubernetes-admin   Pending
```


# k8s側で承認する


```
murata:~ $ kubectl certificate approve request-user-account-derori
certificatesigningrequest.certificates.k8s.io/request-user-account-derori approved
murata:~ $ kubectl get csr
NAME                          AGE     REQUESTOR          CONDITION
request-user-account-derori   7m31s   kubernetes-admin   Approved,Issued
```


# できた証明書を取得する

CRTをファイルに保存

```
murata:~ $ kubectl get csr request-user-account-derori -o jsonpath='{.status.certificate}' | base64 -d > derori-tester.crt
```

crtをderoriユーザーに渡す。(今回は同じサーバなのでcpで)


`murata:~ $ sudo cp derori-tester.crt /home/derori/`


# kubectlの設定をする

deroriユーザーのkubectlの設定をします。

test-uaというcontextを作成します。`--server=https://172.16.203.33:6443` には `$ kubectl describe configmap/cluster-info -n kube-public` のserverセクションを見れば書いてあります。


```
[derori@murata ~]$ kubectl config set-cluster test-ua --insecure-skip-tls-verify=true --server=https://172.16.203.33:6443
Cluster "test-ua" set.
```

derori-testerユーザーの証明書を設定します。

```
[derori@murata ~]$ kubectl config set-credentials derori-tester --client-certificate=derori-tester.crt --client-key=derori-tester.pem --embed-certs=true
User "derori-tester" set.
```

contextをderori-testerユーザーに紐づけて作成します。

```
[derori@murata ~]$ kubectl config set-context test-ua --cluster=test-ua --user=derori-tester
Context "test-ua" created.
```

contextをtest-uaに切り替えます。

```
[derori@murata ~]$ kubectl config use-context test-ua
Switched to context "test-ua".
```


~/.kube/configファイルがこんな感じに作成されます。

```
[derori@murata ~]$ cat ~/.kube/config
apiVersion: v1
clusters:
- cluster:
    insecure-skip-tls-verify: true
    server: https://172.16.203.33:6443
  name: test-ua
contexts:
- context:
    cluster: test-ua
    user: derori-tester
  name: test-ua
current-context: test-ua
kind: Config
preferences: {}
users:
- name: derori-tester
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FUR
mFNREV4RnpBVkJnTlZCQW9URG5ONWMzUmxiVHB0WVhOMFpYSnpNUll3RkF
2N3kvVmk0bWwvWWkrTXJUdnlHTEd0OUtaYVZWTXg4aWhKME5IdXcwbUxvM
jN6TVBzSDk5WFlBblQ3K0ZVYzNYYWg3S3NkS243dndsRGl5NWI4TDRJV0t
WZgpQbm5qc2JQZkpOOHdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBSlJnY
3VEMnJvKwpMRUdjTXduUmU2b2VhcXlJYXZsZXBBeXhURFU5UGRpUDcyd0F
waGxjU289Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktL
DlZK21uVWNHU1gxYURSMXFON2dNUXZtdWhiemZtRmYraU1BWXFrdVRqV1N
zazcyOXdRdWJ0RXdrcURtOHFaWU8rYmRCMkE5Z1FJREFRQUJBb0gvQU14b
01HL21nNWZkeUJ4YTVBZkZKb2tQQ2JqNGgzNGRhdEkydlU5VlpLN0dNZ2N
KTFNveEFvR0JBT1VkTU9KbTlMbWNyakpoYTZNMlFSYVRvQ3ZaVnVRdUNXN
DFnTUUKNmFTM2RYTWRZaUZocFJwTnNEd0duYm9ab1BOU0JKSS9ZWGlzYnV
PUDBBVUtqT0oKcWZoUHlLVUc1VEVnQjM0ellTU08vS1Vubytjbnl6azl4Y
TlTajI2NFp6Mnk0UCsKNDRKQWZJQVFVeE5ZQ2l4L01NeElHZzR2NitlVW5
6TWUyK2tNYkJRZFU1Q3BGZmoKN2pRdjJxdVJiMStENGJ4aWZCTlJtU21EK
```

まだロールを与えていないので拒否されます。

```
[derori@murata ~]$ kubectl get all
Error from server (Forbidden): pods is forbidden: User "derori-test
Error from server (Forbidden): replicationcontrollers is forbidden:
Error from server (Forbidden): services is forbidden: User "derori-
Error from server (Forbidden): daemonsets.apps is forbidden: User "
Error from server (Forbidden): deployments.apps is forbidden: User
Error from server (Forbidden): replicasets.apps is forbidden: User
Error from server (Forbidden): statefulsets.apps is forbidden: User
Error from server (Forbidden): horizontalpodautoscalers.autoscaling
Error from server (Forbidden): jobs.batch is forbidden: User "deror
Error from server (Forbidden): cronjobs.batch is forbidden: User "d
```


# ClusterRoleBinding編集

ClusterRoleBindingのcluster-adminに作ったユーザーを追加します。

参考: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-binding-examples

```
murata:~ $ kubectl edit clusterrolebinding cluster-admin
```

subjectにkind:userで追加します。

```
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: derori-tester
```


こんな感じ。

```
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2019-11-13T11:36:43Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: cluster-admin
  resourceVersion: "13568718"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/cluster-admin
  uid: dbc698e6-4aff-4b24-a2db-05fd1cf90d63
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:masters
- kind: ServiceAccount
  name: derorisan
  namespace: default
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: derori-tester
```



とれるようになりました。

```
[derori@murata ~]$ kubectl get pod -n kube-system
NAME                                               READY   STATUS             RESTARTS   AGE
canal-lvw4h                                        1/2     CrashLoopBackOff   255        73d
coredns-5644d7b6d9-z5ql9                           1/1     Running            1          73d
coredns-5644d7b6d9-z9kxf                           1/1     Running            1          73d
etcd-murata.dev.mercury.local                      1/1     Running            1          88d
kube-apiserver-murata.dev.mercury.local            1/1     Running            1          88d
kube-controller-manager-murata.dev.mercury.local   1/1     Running            1          88d
kube-proxy-g6cnt                                   1/1     Running            1          73d
kube-scheduler-murata.dev.mercury.local            1/1     Running            1          88d
metrics-server-f6d856bdf-29cwl                     1/1     Running            1          12d
```

# ユーザーの消し方

csrを消しても無駄です。
ClusterRoleBindingのsubject: Kind: Userを消せばおｋみたいです。(ユーザー自体を消す方法はあるのか？)


# まとめ

ServiceAccountを追加する方法はよく出てくるのだが、UserAccountを追加するドキュメントがいまいちないなと思いました。
正解なのか不安なところがあるので何かあれば気軽にコメントください。


# 参考

公式Documents: https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs
[ユーザアカウント用に証明書を設定する](https://kubernetes.io/ja/docs/setup/best-practices/certificates/#%e3%83%a6%e3%83%bc%e3%82%b6%e3%82%a2%e3%82%ab%e3%82%a6%e3%83%b3%e3%83%88%e7%94%a8%e3%81%ab%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%82%92%e8%a8%ad%e5%ae%9a%e3%81%99%e3%82%8b)
https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/