Carpe Diem

備忘録

Kubernetes のRBACを理解する

概要

KubernetesではRBACという、各種リソースへのアクセス権限を管理する仕組みが用意されてます。

たとえばPrometheusのようにKubernetesAPIを叩く場合、各リソースへアクセスするための権限が必要になります。

今回はそれの基本的な仕組みや設定方法を説明します。

環境

Service Account

KubernetesにはUserAccountとServiceAccountがあります。大きな違いとしては以下です。

UserAccount ServiceAccount
対象 プロセス
権限範囲 グローバル。
GCPのアカウントや
AWSのIAMとリンクする。
namespace区切り。
Kubernetesの世界で完結する。

ref: Managing Service Accounts - Kubernetes

Pod起動時には必ずServiceAccountを1つ割り当てる必要があります。
指定しない場合はdefault ServiceAccountが割り当てられます。

RBAC

RBAC(Role-based Access Control)はロール型のリソースへのアクセス権限管理の仕組みです。

リソースへアクセスするために必要な権限をRoleとして用意し、それをUserやServiceAccountに付与することでアクセスを可能にします。

以前はABAC(Attribute-based Access Control)という仕組みを使っていましたが、今のバージョンではこちらを使っています。

検証

ServiceAccountの作成

apiVersion: v1
kind: ServiceAccount
metadata:
  name: sample-serviceaccount
  namespace: default

反映すると以下のように作成されます。

$ kubectl get sa
NAME                    SECRETS   AGE
default                 1         14d
sample-serviceaccount   1         9h

Secretsが紐付いていることが分かります。
詳細を見てみましょう。

$ kubectl get sa sample-serviceaccount -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"sample-serviceaccount","namespace":"default"}}
  creationTimestamp: "2019-08-05T15:35:23Z"
  name: sample-serviceaccount
  namespace: default
  resourceVersion: "129319"
  selfLink: /api/v1/namespaces/default/serviceaccounts/sample-serviceaccount
  uid: 4dd63807-c7ee-44ce-8b77-223270d9dd5c
secrets:
- name: sample-serviceaccount-token-t6s9p

Secretsの詳細も確認します。

$ kubectl get secret sample-serviceaccount-token-t6s9p -o yaml
apiVersion: v1
data:
  ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tL...==
  namespace: ZGVmYXVsdA==
  token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbX...==
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: sample-serviceaccount
    kubernetes.io/service-account.uid: 4dd63807-c7ee-44ce-8b77-223270d9dd5c
  creationTimestamp: "2019-08-05T15:35:23Z"
  name: sample-serviceaccount-token-t6s9p
  namespace: default
  resourceVersion: "129318"
  selfLink: /api/v1/namespaces/default/secrets/sample-serviceaccount-token-t6s9p
  uid: b3429905-ebe3-48a3-8387-7b0fa32d4657
type: kubernetes.io/service-account-token

ServiceAccountはこのトークンをKubernetesAPIへの認証情報として利用します。

Podに紐づけて起動

Podに先程のServiceAccountを紐付けて起動します。

apiVersion: v1
kind: Pod
metadata:
  name: sample-kubectl
spec:
  serviceAccountName: sample-serviceaccount
  containers:
    - name: kubectl-container
      image: lachlanevenson/k8s-kubectl:v1.10.4
      command: ["sleep", "86400"]

詳細を見ると以下のように紐付いてることが分かります。
また先程のSecretもマウントされてます。

$ kubectl get po sample-kubectl -o yaml
...
  securityContext: {}
  serviceAccount: sample-serviceaccount
  serviceAccountName: sample-serviceaccount
  terminationGracePeriodSeconds: 30
...
  volumes:
  - name: sample-serviceaccount-token-t6s9p
    secret:
      defaultMode: 420
      secretName: sample-serviceaccount-token-t6s9p
...

権限がない状態での検証

ServiceAccountを紐付けたPodの内部からkubectlを使ってAPIアクセスしてみます。

$ kubectl exec -it sample-kubectl -- kubectl get pods
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:sample-serviceaccount" cannot list resource "pods" in API group "" in the namespace "default"
command terminated with exit code 1

権限がないので予想通り怒られました。

ClusterRoleをバインド

ClusterRoleを独自で作るのもいいですし、既存のClusterRoleをバインドするのも1つです。
今回は既存のものを使います。

以下ClusterRole一覧

$ kubectl get clusterrole
NAME                                                                   AGE
admin                                                                  14d
cluster-admin                                                          14d
edit                                                                   14d
system:aggregate-to-admin                                              14d
system:aggregate-to-edit                                               14d
system:aggregate-to-view                                               14d
system:auth-delegator                                                  14d
system:basic-user                                                      14d
system:certificates.k8s.io:certificatesigningrequests:nodeclient       14d
system:certificates.k8s.io:certificatesigningrequests:selfnodeclient   14d
system:controller:attachdetach-controller                              14d
system:controller:certificate-controller                               14d
...
system:node                                                            14d
system:node-bootstrapper                                               14d
system:node-problem-detector                                           14d
system:node-proxier                                                    14d
system:persistent-volume-provisioner                                   14d
system:public-info-viewer                                              14d
system:volume-scheduler                                                14d
view                                                                   14d

使いやすいのは以下の4つです。

cluster role 説明
cluster-admin 全権限
admin リソース割当、Namespace操作以外の全権限
edit 基本的なリソースのread/write権限。
ただしrole系のread/write権限はない
view 基本的なリソースのread権限。
ただしsecretsリソースは見れない

先程のコマンドはPodの取得権限が必要なので、viewをバインドします。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: sample-clusterrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: view
subjects:
- kind: ServiceAccount
  name: sample-serviceaccount
  namespace: default
  • roleRefに付与する権限を
  • subjectsに付与対象を

設定します。

権限がある状態での検証

ServiceAccountを紐付けたPodの中から、あらためてkubectlを使ってAPIアクセスしてみます。

$ kubectl exec -it sample-kubectl -- kubectl get pods
NAME             READY     STATUS    RESTARTS   AGE
sample-kubectl   1/1       Running   0          29m

今度はAPIへの認証/認可が成功して取得できました。

サンプルコード

今回検証したコードは以下です。

github.com

その他

検証する上で気になった事をまとめます。

RBACを有効にするには?

Kubernetes 1.6から使えるようになったRBACですが、Kubernetes 1.8以降ではデフォルトでONになっています。

RBACが有効になってるか確認したい場合は

$ kubectl api-versions

をした時にrbac.authorization.k8s.io/v1が表示されます。

ref: kubernetes - how to check whether RBAC is enabled, using kubectl - Stack Overflow

ABACが有効か無効かを確認したい

GKEの場合はクラスタの編集で確認できます。

f:id:quoll00:20190806144855p:plain

有効の場合はlegacy-authorizationがまだ使われてます。
上記で無効にすれば完全にRBAC移行できます。

GKEでない場合は--no-enable-legacy-authorizationフラグを使ってクラスタの作成をしたり・api-serverを起動する必要があります。

ref: How to enable RBAC on existing Kubernetes Cluster - Stack Overflow

ABACからRBACへ移行した場合の確認方法は?

両方のauthorization-modeが有効の場合、最初にRBACでアクセス権限をチェックし、失敗するとABACにfallbackします。
なのでapi-serverのログにはRBAC DENY:というログが出ます。

ref: Using RBAC Authorization - Kubernetes

ログの出し方は以下です。

$ kubectl proxy

でプロキシを立て、ログを取得します。

$ curl -s http://localhost:8001/logs/kube-apiserver.log

ref: How to debug ABAC to RBAC transition in a GKE kubernetes cluster? - Stack Overflow

ServiceAccountに紐付くRoleを確認したい

kubectl get clusterrolebinding-o wideをつけるとUser, Group, ServiceAccountが表示されるので確認できます。

$ kubectl get clusterrolebinding -o wide
NAME                                                   AGE   ROLE                                                                               USERS                            GROUPS                                            SERVICEACCOUNTS
cluster-admin                                          14d   ClusterRole/cluster-admin                                                                                           system:masters
kubeadm:kubelet-bootstrap                              14d   ClusterRole/system:node-bootstrapper                                                                                system:bootstrappers:kubeadm:default-node-token
kubeadm:node-autoapprove-bootstrap                     14d   ClusterRole/system:certificates.k8s.io:certificatesigningrequests:nodeclient                                        system:bootstrappers:kubeadm:default-node-token
kubeadm:node-autoapprove-certificate-rotation          14d   ClusterRole/system:certificates.k8s.io:certificatesigningrequests:selfnodeclient                                    system:nodes
kubeadm:node-proxier                                   14d   ClusterRole/system:node-proxier                                                                                                                                       kube-system/kube-proxy
minikube-rbac                                          14d   ClusterRole/cluster-admin                                                                                                                                             kube-system/default
storage-provisioner                                    14d   ClusterRole/system:persistent-volume-provisioner                                                                                                                      kube-system/storage-provisioner
system:basic-user                                      14d   ClusterRole/system:basic-user                                                                                       system:authenticated
system:controller:attachdetach-controller              14d   ClusterRole/system:controller:attachdetach-controller                                                                                                                 kube-system/attachdetach-controller
system:controller:certificate-controller               14d   ClusterRole/system:controller:certificate-controller                                                                                                                  kube-system/certificate-controller
system:controller:clusterrole-aggregation-controller   14d   ClusterRole/system:controller:clusterrole-aggregation-controller                                                                                                      kube-system/clusterrole-aggregation-controller
system:controller:cronjob-controller                   14d   ClusterRole/system:controller:cronjob-controller                                                                                                                      kube-system/cronjob-controller
system:controller:daemon-set-controller                14d   ClusterRole/system:controller:daemon-set-controller                                                                                                                   kube-system/daemon-set-controller
system:controller:deployment-controller                14d   ClusterRole/system:controller:deployment-controller                                                                                                                   kube-system/deployment-controller
system:controller:disruption-controller                14d   ClusterRole/system:controller:disruption-controller                                                                                                                   kube-system/disruption-controller
system:controller:endpoint-controller                  14d   ClusterRole/system:controller:endpoint-controller                                                                                                                     kube-system/endpoint-controller
system:controller:expand-controller                    14d   ClusterRole/system:controller:expand-controller                                                                                                                       kube-system/expand-controller
system:controller:generic-garbage-collector            14d   ClusterRole/system:controller:generic-garbage-collector                                                                                                               kube-system/generic-garbage-collector
system:controller:horizontal-pod-autoscaler            14d   ClusterRole/system:controller:horizontal-pod-autoscaler                                                                                                               kube-system/horizontal-pod-autoscaler
...

ServiceAccountが持ってる権限確認したい

can-iで確認できます。

kubectl auth can-i <verb> <resource> \
  --as=system:serviceaccount:<namespace>:<serviceaccountname> \
  [-n <namespace>]

例えばdefaultのServiceAccountにpodの読み込み権限があるか、だと

$ kubectl auth can-i get pod --as=system:serviceaccount:default:default
no

となります。

ref: Securing your Cluster with RBAC and PSP – Giant Swarm Documentation

Docker for MacはデフォルトだとRBACの検証ができない

github.com

ここにあるようにデフォルトだと全てのservice accountにcluster-adminのcluster roleがbindされるため検証ができません。
なのでdocker-for-desktop-bindingを消すか今回のようにminikubeなど別環境で検証する必要があります。

ソース