Kubernetes: v1.6 の Role-Based Access Control (RBAC) を minikube で試す

Kubernetes 1.6 で Role-Based Access Control (RBAC) が beta になり、デフォルトのロールの拡充や kubectl からロールの紐付けができるようになったりと大幅にアップデートされました :tada: 。以下は v1.6 の RBAC と minikube で試す際のメモになります。

# v 1.6 での RBAC の主な変更点

- デフォルトロールの拡充。汎用的に使える読み取り専用ロール (view) や 書き込み権限ロール (edit) などが用意されました。
- kubectl のサブコマンド `create rolebinding/clusterrolebinding` が追加され簡単にロールの紐付けができるようになりました
- API Server の `--anonymous-auth`がデフォルトで有効になりました
    - 認証を通さない場合、RBAC では`system:unauthenticated`というグループとして扱われます
- API Server の `--authorization-rbac-super-user`がdeprecatedになりました。代わりに RBAC では`system:masters`が特権グループとして利用できます
- ClusterRoleBinding と RoleBinding のユーザの`*`の特別扱いがなくなりました。
    - 全てのユーザに一致させたい場合は、明示的に`system:authenticated`と`system:unauthenticated`のグループを指定します。
    - ユーザの`*`は`system:authenticated`として扱われるようになっています
- RoleBinding/ClusterRoleBinding の subject が `apiVersion` から `apiGroup` に変更されました


# minikube で RBAC を試すための設定

記載時点での minkube (v0.17.1) で v1.6.0 で RBAC を試すためには以下の指定で minikube を起動します。

```bash
$ minikube start --kubernetes-version=1.6.0 --extra-config=apiserver.Authorization.Mode=RBAC --extra-config=apiserver.Audit.Path=/var/log/kubernetes/audit.log
```

minikube での RBAC のオプション指定は v1.5 系から変更されているので注意が必要です。

`--extra-config=apiserver.Audit.Path=/var/log/kubernetes/audit.log` オプションは必須ではありませんが、権限の情報をログに落とすことができるため、RBAC の実験に便利です。ログは `minikube ssh` で ssh ログインして確認することができます。


# v1.6 の RBAC のデフォルトポリシー
v1.6 では RBAC のデフォルトポリシーが大きく拡充されました。デフォルトポリシーは大きく分けて、ユーザが使える汎用的なロールと各種コントローラーなどのコンポーネントが使う専用ロールの2つがあります。なおデフォルトのポリシーには `kubernetes.io/bootstrapping=rbac-defaults` というラベルが設定されておりユーザが定義したものと見分けられるようになっています。

## 汎用的なポリシー

汎用的に使うことができるポリシーとして、以下のものがデフォルトで定義されています。

ClusterRole | デフォルトのClusterRoleBinding(group) | 説明
--- | --- | ---
system:basic-user | system:authenticated, system:unauthenticated | 基本的なユーザ自身に関する情報の読み取り (SelfSubjectAccessReview)
system:discovery | system:authenticated, system:unauthenticated | APIのディスカバリエンドポイントに対しての読み取り (`/api`, `/apis`, `/version`など)
cluster-admin | system:masters | クラスタの全権限をもった管理者権限。RoleBinding で namespace 内にした場合はその namespace の全権限。
admin | -  | namespace 内の管理者権限。namespace や resourceQuota に関する権限を持たない
edit | - | namespace内の読み書き権限。admin との違いは role / rolebinding に関する権限を持たないこと
view | - | namespace内の読み取り権限

v1.5 までの RBAC で必要だった `--authorization-rbac-super-user` による特権ユーザの指定の代わりに、特権ユーザは "system:masters" のグループとして指定する形になりました。

minikube では 内部的に発行される [TLS証明書で RBAC のマスターのグループ "system:masters" として指定](https://github.com/kubernetes/minikube/blob/62ae35c9de6a8c19110187afd6bf960b6caa452a/pkg/util/crypto.go#L93)されているため、minikube のデフォルトユーザ ("minikube") であれば管理者権限 (cluster-admin) を使うことができます。

## 各コンポーネント用のロール

kube-scheduler や kube-proxy、各種コントローラーごとに必要なロールも定義されています。以下のようにデフォルトで多くの clusterrole が定義されていることがわかります。詳細は `-o yaml` オプションでご覧ください。

```bash
$ kubectl get clusterrole
NAME                                           AGE
admin                                          15m
cluster-admin                                  15m
edit                                           15m
system:auth-delegator                          15m
system:basic-user                              15m
system:controller:attachdetach-controller      15m
system:controller:certificate-controller       15m
system:controller:cronjob-controller           15m
system:controller:daemon-set-controller        15m
system:controller:deployment-controller        15m
system:controller:disruption-controller        15m
system:controller:endpoint-controller          15m
system:controller:generic-garbage-collector    15m
system:controller:horizontal-pod-autoscaler    15m
system:controller:job-controller               15m
system:controller:namespace-controller         15m
system:controller:node-controller              15m
system:controller:persistent-volume-binder     15m
system:controller:pod-garbage-collector        15m
system:controller:replicaset-controller        15m
system:controller:replication-controller       15m
system:controller:resourcequota-controller     15m
system:controller:route-controller             15m
system:controller:service-account-controller   15m
system:controller:service-controller           15m
system:controller:statefulset-controller       15m
system:controller:ttl-controller               15m
system:discovery                               15m
system:heapster                                15m
system:kube-aggregator                         15m
system:kube-controller-manager                 15m
system:kube-dns                                15m
system:kube-scheduler                          15m
system:node                                    15m
system:node-bootstrapper                       15m
system:node-problem-detector                   15m
system:node-proxier                            15m
system:persistent-volume-provisioner           15m
view                                           15m
```

# minikube で RBAC を試してみる
minikube で実際に RBAC を試してみます。RBAC の実験には簡単にユーザを追加できる  [ServiceAccount](https://kubernetes.io/docs/user-guide/service-accounts/) を使うのが便利です。

## view 権限の付与
`alice` という名前の ServiceAccount を作成してみます。(namespace は defaultです)

```bash
$ kubectl create sa alice
serviceaccount "alice" created
```

kubectl から権限を試すために、ServiceAccount の接続情報 (kubeconfig) を作成します。kubeconfig を手動で書くのは面倒なため、ここでは Z Lab (自分の所属会社です) が公開している [create-kubeconfig](https://github.com/zlabjp/kubernetes-scripts/blob/master/create-kubeconfig) というスクリプトを使います。

```bash
$ create-kubeconfig alice > /tmp/alice.cfg
```

ServiceAccount の kubeconfig ができたので、これを使って RBAC の権限を確認してみます。kubectl では `KUBECONFIG` という環境変数で kubeconfig を指定できるので、その機能を使って alice としてアクセスします。ServiceAccount を作っただけなので何の権限も持っていません。

```bash
# alice の接続情報を使って pod と service の参照をしてみる
$ KUBECONFIG=/tmp/alice.cfg kubectl get pods,svc
Error from server (Forbidden): User "system:serviceaccount:default:alice" cannot list pods in the namespace "default". (get pods)
Error from server (Forbidden): User "system:serviceaccount:default:alice" cannot list services in the namespace "default". (get services)
```

alice に読み取り権限を持ったロール view を設定してみます。ここでは 1.6 で新しく追加された `create rolebinding` というサブコマンドを使って namespace 単位のロールの紐付けを行ってみます。

```bash
# alice に namespae default の view ロールを付与する
$ kubectl create rolebinding alice-view --clusterrole=view --serviceaccount=default:alice --namespace=default
```

読み取り権限がついたか確認してみます。

```bash
# 読み取りができるようになった！
$ KUBECONFIG=/tmp/alice.cfg kubectl get pods,svc
NAME                          READY     STATUS              RESTARTS   AGE
po/mynginx-1396894033-7bmkg   0/1       ContainerCreating   0          2s

NAME             CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
svc/kubernetes   10.0.0.1     <none>        443/TCP   41m
```

default namespace の読み取りができたので default 以外の namespace に権限がないことも確認してみます。

```bash
# 別の namespace (kube-system) なので読み取り権限がない
$ KUBECONFIG=/tmp/alice.cfg kubectl get pods,svc -n kube-system
Error from server (Forbidden): User "system:serviceaccount:default:alice" cannot list pods in the namespace "kube-system". (get pods)
Error from server (Forbidden): User "system:serviceaccount:default:alice" cannot list services in the namespace "kube-system". (get services)
```

また default への書き込み権限がないことも確認してみます。

```bash
# 書き込みに失敗する
$ KUBECONFIG=/tmp/alice.cfg kubectl run dummy --image nginx
Error from server (Forbidden): User "system:serviceaccount:default:alice" cannot create deployments.extensions in the namespace "default". (post deployments.extensions)
```

## edit 権限の付与
新しい ServiceAccount として bob を作成して edit 権限を与えてみます。

```bash
# bob 作成
$ kubectl create sa bob
serviceaccount "bob" created

# kubeconfig 作成
$ create-kubeconfig bob > /tmp/bob.cfg

# edit 権限付与
$ kubectl create rolebinding bob-edit --clusterrole=edit --serviceaccount=default:bob --namespace=default
rolebinding "bob-edit" created
```

まずは読み取り権限があることを確認します。

```bash
$ KUBECONFIG=/tmp/bob.cfg kubectl get pods,svc

NAME                          READY     STATUS    RESTARTS   AGE
po/mynginx-1396894033-7bmkg   1/1       Running   0          14m

NAME             CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
svc/kubernetes   10.0.0.1     <none>        443/TCP   55m
```

更新権限があることを確認します。

```bash
# deployment が作成できた
$ KUBECONFIG=/tmp/bob.cfg kubectl run dummy --image nginx
deployment "dummy" created
```

他の namespade には権限がないことを確認します。

```
# 他の namesapce (kube-system) なので権限がない
$  KUBECONFIG=/tmp/bob.cfg kubectl run dummy --image nginx -n kube-system
Error from server (Forbidden): User "system:serviceaccount:default:bob" cannot create deployments.extensions in the namespace "kube-system". (post deployments.extensions)
```

## `auth can-i` サブコマンド
1.6 `auth can-i` というサブコマンドも追加されており自分の権限を簡単に確認することができます。

```bash
# pod に対する get の権限はある (yes)
$ KUBECONFIG=/tmp/alice.cfg kubectl auth can-i get pods
yes

# pod に対する create 権限はない (no)
$ KUBECONFIG=/tmp/alice.cfg kubectl auth can-i create pods
no

# 他の namespace への pod の get 権限はない (no)
$ KUBECONFIG=/tmp/alice.cfg kubectl auth can-i get pods -n kube-system
no
```

# まとめ

1.6 では RBAC の機能が大幅にアップデートされ基本的なロールであればデフォルトのポリシーとサブコマンドだけで簡単にロール管理が行えるようになりました。また kubectl のサブコマンドによって使い勝手も着実に進化しています。

# 参考
- https://kubernetes.io/docs/admin/authorization/rbac/
- https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md#v160