---
title: Kubernetesハンズオン - 10. RBACによるKubernetes APIアクセス制御
tags: ["Kubernetes Handson", "Kubernetes", "PKS"]
categories: ["Dev", "CaaS", "Kubernetes"]
date: 2020-01-13T13:43:16Z
updated: 1970-01-01T00:00:00Z
---

Kubernetesに対する操作はMaster NodeのAPI Serverに対して行われます。
このAPIアクセスを制限するためにRBAC(Roll Based Access Control)の仕組みが備わっています。

KubernetesのRBACでは、どのリソース(Pod, ReplicaSet, Deployment, Serviceなど)にどの操作(get, list, create, deleteなど)を許可するかを表現する

* Role
* ClusterRole

というリソースが用意されています。
Roleは特定の名前空間配下に適用されます。一方ClusterRoleは名前空間に関係なくKuberntesクラスタ全体に適用されます。
ClusterRoleはリソース以外に、ノードなどのクラスタスコープのリソースや`/healthz`などの非リソースへのアクセスも制御対象とできます。

Role/ClusterRoleをバインドするSubject(対象)としては次の3種類があります。

* User
* Group
* ServiceAccount

UserはKubernetes APIにアクセスする人間を指します。GroupはUserをグルーピング化したものです。
一方、ServiceAccountはKubernetes APIにアクセスするコンテナ上のプロセスを想定します。ServiceAccountは名前空間に対して作成されます。

Kubernetesにはユーザーやグループの作成機能はありません。ユーザー/グループの管理は外部システムに移譲し、OpenID Connect等で連携されます。
本ドキュメントではServiceAccountのみ扱います。

RoleをSubjectにバインドするために

* RoleBinding
* ClusterRoleBinding

というリソースが用意されています。
RoleBindingは、特定の名前空間のリソースに対するRoleまたはClusterRoleをSubjectにバインドします。
ClusterRoleBindingは、任意の名前空間のリソースやクラスタスコープのリソース、`/healthz`などの非リソースに対するClusterRoleをSubjectにバインドします。

RBACは許可するルールを追加するホワイトリスト方式です。アクセスを拒否するルールは指定できません。

**目次**

<!-- toc -->

### curlコマンドでKubernetes APIにアクセス

RBACを説明するために、Kubernetes APIにアクセスする最もシンプルなクライアントとして、`curl`コマンドを利用します。

Kubernetes APIは`kubernetes`と名前のServiceとして`default`名前空間に公開されています。

```
kubectl get svc kubernetes -n default
```
出力結果
```
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.11.240.1   <none>        443/TCP   170d
```

内部DNS(KubeDNS)を使うことでHost名`kubernetes.default.svc.cluster.local`でPodのコンテナ内から次のようにアクセス可能です。

```
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
     -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://kubernetes.default.svc.cluster.local
```

`/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`にはKubernetes APIのCA証明書、
`/var/run/secrets/kubernetes.io/serviceaccount/token`にはPodにアサインされたServiceAccountのトークン(JWT)がマウントされます。

まず始めに、作業する名前空間として`demo-pks`を作成します。

`demo-pks-ns.yml`を作成して次の内容を記述してください。

```yaml
apiVersion: v1
kind: Namespace
metadata:
  name: demo-pks
```
次のコマンドで`demo-pks`名前空間を作成してください。
```
kubectl apply -f demo-pks-ns.yml
```
出力結果
```
namespace "demo-pks" created
```

次に`curl`コマンドが含まれるPodを`demo-pks`名前空間にデプロイします。

`curl.yml`を作成して次の内容を記述してください。

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: curl
  namespace: demo-pks
spec:
  replicas: 1
  selector:
    matchLabels:
      app: curl
  template:
    metadata:
      labels:
        app: curl
    spec:
      containers:
      - image: tutum/curl
        name: sleep
        command:
        - sh
        - -c
        - |
          while true;do sleep 1;done
```

プロセスが終了しないように無限に`sleep`させています。
次のコマンドでデプロイしてください。
```
kubectl apply -f curl.yml
```
出力結果
```
deployment "curl" created
```

次のコマンドで`demo-pks`名前空間のPod一覧を確認してください。

```
kubectl get pod -n demo-pks
```
出力結果
```
NAME                   READY     STATUS    RESTARTS   AGE
curl-997d489df-8lvqp   1/1       Running   0          7s
```
次のコマンドでコンテナ上のbashを実行してください。
```
kubectl exec -n demo-pks -ti $(kubectl get pod -n demo-pks -l app=curl -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}') /bin/bash
```
コンテナ上のbashから、次のコマンドを実行し、`demo-pks`名前空間のPod一覧を取得するAPIにアクセスてください。
```
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
     -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://kubernetes.default.svc.cluster.local/api/v1/namespaces/demo-pks/pods
```
出力結果
```json
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "pods is forbidden: User \"system:serviceaccount:demo-pks:default\" cannot list pods in the namespace \"demo-pks\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
}
```

`exit`を実行してコンテナ上のbashを終了してください。

デフォルトでは`default`という名前のServiceAccountが使用されます。
次のコマンドで`demo-pks`名前空間のServiceAccountを確認出来ます。
```
kubectl get serviceaccount -n demo-pks
```
出力結果
```
NAME      SECRETS   AGE
default   1         4m
```

`default` ServiceAccountは**Kubernetes APIにアクセスする権限がありません**。そのため、403エラーが返りました。

### ServiceAccount、Role、RoleBindingの作成

`demo-pks`名前空間のPod一覧を取得できるように`demo-sa`という名前のServiceAccountを作成し、`demo-reader`という名前のRoleをバインドします。

`demo-rbac.yml`を作成し、次の内容を記述してください。

```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: demo-sa
  namespace: demo-pks
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: demo-reader
  namespace: demo-pks
rules:
- apiGroups: 
  - "" # "" indicates the core API group
  resources:
  - pods
  verbs:
  - get
  - watch
  - list
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: demo-sa-binding
  namespace: demo-pks
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: demo-reader
subjects:
- kind: ServiceAccount
  name: demo-sa
  namespace: demo-pks
```

次のコマンドを実行し、ServiceAccount、RoleそしてRoleBindingを作成してください。
```
kubectl apply -f demo-rbac.yml
```
出力結果
```
serviceaccount "demo-sa" created
role "demo-reader" created
rolebinding "demo-sa-binding" created
```

Podがこの`demo-sa` ServiceAccountを使うように`curl.yml`を次のように修正してください。

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: curl
  namespace: demo-pks
spec:
  replicas: 1
  selector:
    matchLabels:
      app: curl
  template:
    metadata:
      labels:
        app: curl
    spec:
      serviceAccountName: demo-sa # 追加
      containers:
      - image: tutum/curl
        name: sleep
        command:
        - sh
        - -c
        - |
          while true;do sleep 1;done
```

次のコマンドを実行し、Podを更新してください。

```
kubectl apply -f curl.yml
```
出力結果
```
deployment "curl" configured
```

次のコマンドでコンテナ上の再度bashを実行してください。

```
kubectl exec -n demo-pks -ti $(kubectl get pod -n demo-pks -l app=curl -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}') /bin/bash
```
コンテナ上のbashから、次のコマンドを実行し、`demo-pks`名前空間のPod一覧を取得するAPIにアクセスてください。
```
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
     -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://kubernetes.default.svc.cluster.local/api/v1/namespaces/demo-pks/pods
```
出力結果
```json
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/namespaces/demo-pks/pods",
    "resourceVersion": "139492"
  },
  "items": [
    {
      ...
    }
  ]
}
```

`demo-reader` RoleにはPodの読み取り権限しかないため、例えばService一覧取得APIにはアクセスできません。

コンテナ上のbashから、次のコマンドを実行し、`demo-pks`名前空間のService一覧を取得するAPIにアクセスてください。

```
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
     -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://kubernetes.default.svc.cluster.local/api/v1/namespaces/demo-pks/services
```
出力結果
```json
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "services is forbidden: User \"system:serviceaccount:demo-pks:demo-sa\" cannot list services in the namespace \"demo-pks\"",
  "reason": "Forbidden",
  "details": {
    "kind": "services"
  },
  "code": 403
}
```
`exit`を実行してコンテナ上のbashを終了してください。



`demo-rbac.yml`を次のように修正して、Serviceリソースに対する読み取り権限を追加してください。

```yaml
# ...
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: demo-reader
rules:
- apiGroups: 
  - "" # "" indicates the core API group
  resources:
  - pods
  - services # 追加
  verbs:
  # ...
```

次のコマンドを実行し、Roleを更新してください。
```
kubectl apply -f demo-rbac.yml
```
出力結果
```
serviceaccount "demo-sa" unchanged
role "demo-reader" configured
rolebinding "demo-sa-binding" unchanged
```

次のコマンドでコンテナ上の再度bashを実行してください。

```
kubectl exec -n demo-pks -ti $(kubectl get pod -n demo-pks -l app=curl -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}') /bin/bash
```
コンテナ上のbashから、次のコマンドを実行し、`demo-pks`名前空間のService一覧を取得するAPIにアクセスてください。
```
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
     -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://kubernetes.default.svc.cluster.local/api/v1/namespaces/demo-pks/services
```
出力結果
```json
{
  "kind": "ServiceList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/namespaces/demo-pks/services",
    "resourceVersion": "140006"
  },
  "items": []
}
```

Roleが拡張されたことを確認できました。

### ClusterRoleの利用

Roleは名前空間毎に作成する必要があります。各リソースに対するアクセス制御を名前空間毎に作成するのは手間がかかります。
同一クラスタ内であればどの名前空間でも利用できるRoleがClusterRoleです。
ClusterRoleはRole同様に自分で作成しても良いですし、予め用意されているものを使用しても良いです。

次のコマンドを実行して、作成ずみのClusterRole一覧を確認してください。
```
kubectl get clusterrole
```
出力結果
``` 
NAME                                                                   AGE
admin                                                                  2d
cluster-admin                                                          2d
edit                                                                   2d
kubo:internal:kubelet-drain                                            2d
kubo:route-sync                                                        2d
nginx-ingress-clusterrole                                              22h
system:aggregate-to-admin                                              2d
system:aggregate-to-edit                                               2d
system:aggregate-to-view                                               2d
system:auth-delegator                                                  2d
system:aws-cloud-provider                                              2d
system:basic-user                                                      2d
system:certificates.k8s.io:certificatesigningrequests:nodeclient       2d
system:certificates.k8s.io:certificatesigningrequests:selfnodeclient   2d
system:controller:attachdetach-controller                              2d
system:controller:certificate-controller                               2d
system:controller:clusterrole-aggregation-controller                   2d
system:controller:cronjob-controller                                   2d
system:controller:daemon-set-controller                                2d
system:controller:deployment-controller                                2d
system:controller:disruption-controller                                2d
system:controller:endpoint-controller                                  2d
system:controller:generic-garbage-collector                            2d
system:controller:horizontal-pod-autoscaler                            2d
system:controller:job-controller                                       2d
system:controller:namespace-controller                                 2d
system:controller:node-controller                                      2d
system:controller:persistent-volume-binder                             2d
system:controller:pod-garbage-collector                                2d
system:controller:pv-protection-controller                             2d
system:controller:pvc-protection-controller                            2d
system:controller:replicaset-controller                                2d
system:controller:replication-controller                               2d
system:controller:resourcequota-controller                             2d
system:controller:route-controller                                     2d
system:controller:service-account-controller                           2d
system:controller:service-controller                                   2d
system:controller:statefulset-controller                               2d
system:controller:ttl-controller                                       2d
system:discovery                                                       2d
system:heapster                                                        2d
system:kube-aggregator                                                 2d
system:kube-controller-manager                                         2d
system:kube-dns                                                        2d
system:kube-scheduler                                                  2d
system:node                                                            2d
system:node-bootstrapper                                               2d
system:node-problem-detector                                           2d
system:node-proxier                                                    2d
system:persistent-volume-provisioner                                   2d
view 
```

`system:`から始まるものは特定のコンポーネントで利用されるClusterRoleです。
次の4つが汎用的に利用可能なClusterRoleです。

* `cluster-admin`
* `admin`
* `edit`
* `view`

それぞれの説明は[ドキュメント](https://kubernetes.io/docs/admin/authorization/rbac/#user-facing-roles)を確認してください。

ここでは多くのリソースの読み取り権限をもつ`view` ClusterRoleを`demo-sa` ServiceAccountにバインドします。

`demo-sa-edit-binding.yml`を作成して、次の内容を記述してください。

```yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: demo-sa-edit-binding
  namespace: demo-pks
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: view
subjects:
- kind: ServiceAccount
  name: demo-sa
  namespace: demo-pks
```

次のコマンドでRoleBindingを作成してください。

```
kubectl apply -f demo-sa-edit-binding.yml 
```
出力結果
```
rolebinding "demo-sa-edit-binding" created
```

次のコマンドでコンテナ上の再度bashを実行してください。

```
kubectl exec -n demo-pks -ti $(kubectl get pod -n demo-pks -l app=curl -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}') /bin/bash
```

コンテナ上のbashから、次のコマンドを実行し、`demo-pks`名前空間のDeployment一覧を取得するAPIにアクセスてください。

```
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
     -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://kubernetes.default.svc.cluster.local/apis/extensions/v1beta1/namespaces/demo-pks/deployments
```
出力結果
```json
{
  "kind": "DeploymentList",
  "apiVersion": "extensions/v1beta1",
  "metadata": {
    "selfLink": "/apis/extensions/v1beta1/namespaces/demo-pks/deployments",
    "resourceVersion": "142427"
  },
  "items": [
    {
      ...
    }
  ]
}
```
アクセスできるAPIが増えたことが分かります。

ただし、ClusterRoleを使っても、RoleBindingの範囲は依然として特定の名前空間に限られます。
例えば同じPod一覧取得でも名前空間が異なる場合はアクセスできません。次のコマンドで`kube-system`名前空間のPod一覧を取得するAPIにアクセスてください。

```
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
     -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://kubernetes.default.svc.cluster.local/api/v1/namespaces/kube-system/pods
```
出力結果
```json
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "pods is forbidden: User \"system:serviceaccount:demo-pks:demo-sa\" cannot list pods in the namespace \"kube-system\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
}
```

`demo-sa-edit-binding`は削除してください。

```
kubectl delete -f demo-sa-edit-binding.yml 
```
出力
```
rolebinding "demo-sa-edit-binding" deleted
```

### ClusterRoleBindingの作成

名前空間に限定せずにAPIアクセスを許可するにはRoleBindingではなく、ClusterRoleBindingを作成する必要があります。

`demo-sa-clusterrole-binding.yml`を作成して、次の内容を記述してください。

```yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: demo-sa-clusterrole-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: view
subjects:
- kind: ServiceAccount
  name: demo-sa
  namespace: demo-pks
```

次のコマンドでClusterRoleBindingを作成してください。

```
kubectl apply -f demo-sa-clusterrole-binding.yml
```
出力結果
```
clusterrolebinding "demo-sa-clusterrole-binding" created
```

次のコマンドでコンテナ上の再度bashを実行してください。

```
kubectl exec -n demo-pks -ti $(kubectl get pod -n demo-pks -l app=curl -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}') /bin/bash
```

コンテナ上のbashから、次のコマンドを実行し、`kube-system`名前空間のPod一覧を取得するAPIにアクセスてください。

```
curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
     -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://kubernetes.default.svc.cluster.local/apis/extensions/v1beta1/namespaces/demo-pks/deployments
```
出力結果
```json
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/namespaces/kube-system/pods",
    "resourceVersion": "143487"
  },
  "items": [
    {
      ...
    }
  ]
}
```

ClusterRoleBindingを使うことで、外の名前空間に対してもアクセスできました。
ClusterRoleBindingは影響範囲が大きいため、基本的にはシステムコンポーネントに対してのみ利用してください。

`demo-sa-clusterrole-binding`は削除してください。

```
kubectl delete -f demo-sa-clusterrole-binding.yml 
```
出力結果
```
clusterrolebinding "demo-sa-clusterrole-binding" deleted
```
### kubectlコマンドのRBAC

`kubectl`コマンド自体もAPI Serverに対するアクセスであるため、
ServiceAccountを使って`kubectl`コマンドのRBACを行えます。

ServiceAccountを作成するとSecretにTokenが作成されます。
このTokenを使うことで`kubectl`がアクセスできるAPIを、ServiceAccountにバインドされているClusterRoleおよびRoleが許可されているもののみに制限できます。

PKS 1.0ではOpenID Connectによるユーザー認証がサポートされておらず、`pks get-credentials`で取得した認証情報を使うと
管理者権限が与えられます。
一つのKubernetesクラスタを複数のプロジェクトで共有する場合で、**名前空間毎にユーザーのアクセスを制限したい**場合は、
`pks get-credentials`で取得した認証情報を共有するのではなく、ServiceAccountのTokenを使ってください。

特定のServiceAccountに対するKubernetesのConfigファイルは次のスクリプトで作成できます。
`create-sa-kubeconfig.sh`を作成して、次の内容を記述してください。

```bash
#!/bin/bash
set -e

NAMESPACE=$1
SERVICE_ACCOUNT=$2
SECRET_NAME=${SERVICE_ACCOUNT}-token
cat <<EOF | kubectl apply -n ${NAMESPACE} -f - > /dev/null
apiVersion: v1
kind: Secret
metadata:
  name: ${SECRET_NAME}
  annotations:
    kubernetes.io/service-account.name: "${SERVICE_ACCOUNT}"
type: kubernetes.io/service-account-token
EOF

TOKEN=`kubectl get secret ${SECRET_NAME} -n ${NAMESPACE} -o 'jsonpath={.data.token}' | base64 --decode`
CREDENTIALS_NAME="${NAMESPACE}:${SERVICE_ACCOUNT}"
kubectl config set-credentials ${CREDENTIALS_NAME} --token=${TOKEN} > /dev/null

CURRENT_CLUSTER=`kubectl config view --minify=true -o jsonpath='{.clusters[0].name}'`
CONTEXT_NAME="${CURRENT_CLUSTER}:${CREDENTIALS_NAME}"

kubectl config set-context ${CONTEXT_NAME} \
    --cluster=${CURRENT_CLUSTER} \
    --namespace=${NAMESPACE} \
    --user=${CREDENTIALS_NAME} > /dev/null

CURRENT_CONTEXT=`kubectl config current-context`
kubectl config use-context ${CONTEXT_NAME} > /dev/null
kubectl config view --minify=true --raw=true 
kubectl config use-context ${CURRENT_CONTEXT} > /dev/null
if [ "$3" != "--keep" ];then
  kubectl config delete-context ${CONTEXT_NAME} > /dev/null
  kubectl config unset "users.${CREDENTIALS_NAME}" > /dev/null
fi
```

`demo-pks`名前空間の`demo-sa` ServiceAccountでログインするConfigファイルは次のコマンドで作成できます。

```
chmod +x create-sa-kubeconfig.sh

./create-sa-kubeconfig.sh demo-pks demo-sa
```
出力結果(例)
```yaml
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKRENDQWd5Z0F3SUJBZ0lVSVEwb1hTMllLanpBZVJqU0RHUVZ5NU4xSEEwd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0RURUxNQWtHQTFVRUF4TUNZMkV3SGhjTk1UZ3dOVEV5TURZMU5UUTNXaGNOTVRrd05URXlNRFkxTlRRMwpXakFOTVFzd0NRWURWUVFERXdKallUQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCCkFNRGRvczI1ZjBSMVVtVGttQ0hQYXhKdFlFUXc4Tjhia1IwRVVNcktPUkQ3U0Q3bzFxbnh3NmM1Ujg3VURmLzgKc1Q3RFZsMzkxL1c2T0IySlgyUFU1YzY0Ymt1Mll6Zmt4Yk1qdGxCeTRQd1VVODlia1JQUnluTjFNTU9icFc2cQpWTTgrUGZDV1Z1OWNaUEV3K3dSL0dGQjc3Rzg4RXlKQnVmYjJmT0p6Z1hCemllaTB3Tk5ydTR1T21QaE5CZ2VQCkhONVBReDlsaE5HZ1BhcGV1UGthalR4cUd6NzBEN0pQRDRKSUljdkFSdWs0cnhZbDVGbHZNN05GRU9ZR3dFb2wKeDdxeDMrWUJsZnB2STFNSVdtcHFyZGR0SUd3aDhJK0UrOElkM2ZOUWNyZHpRUU5JdlVDT1d4MWVHRStEUndqQwpCbHRPTnp3dEh2dXNHNDZ2TWFDNDUwOENBd0VBQWFOOE1Ib3dIUVlEVlIwT0JCWUVGTlVTOWhuU0ZLZWtoZmcwClZKYVMyUnpwd0xBSU1FZ0dBMVVkSXdSQk1EK0FGTlVTOWhuU0ZLZWtoZmcwVkphUzJSenB3TEFJb1JHa0R6QU4KTVFzd0NRWURWUVFERXdKallZSVVJUTBvWFMyWUtqekFlUmpTREdRVnk1TjFIQTB3RHdZRFZSMFRBUUgvQkFVdwpBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQVY4dnhOS2xxQUp4SThBYmt3aitWVWpQaGh6RCt1a0dwCm80Z2k3T2VzL3BwKytjOEV3UXJpVkswRDZhQU9UNlFzZlRsRi9PQ0tEd3Z6QnNRN3Z6N3hob2t1KzNDRk12TnAKbzZWYjlWVDk4c3ZBYTNsOXI4bEtBT3ZqVjh5U1E3MnlJMDI3c0xjb0kwb3V6VkVaVk1RdlJQa0M5R3VZZTRhZApTVC8wK1R5OWtFQ0psajlxRkNaNlFsdHpkcmV1emMyc3cwYzZHTFNucXJaTk1pZzRkL2RPQU5YTjBGZGVWc2FzCjVvMjg4R2VmUk1oTFVSTnNQK1MrSkw5MnhndTc3NjRDWU1FZkltai9FdCthRUpHU0RkQm1QQXNneWM5YVhtQ2YKTGRZWE5wYTVKQ1pqeWhieHl3OVVMZ2Z1RU1maWFKdkoyYTAvek16N01pc04rVkRtY3lpRFNRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQoK
    server: https://10.244.1.92:8443
  name: cfcr
contexts:
- context:
    cluster: cfcr
    namespace: demo-pks
    user: demo-pks:demo-sa
  name: cfcr:demo-pks:demo-sa
current-context: cfcr:demo-pks:demo-sa
kind: Config
preferences: {}
users:
- name: demo-pks:demo-sa
  user:
    token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZW1vLXBrcyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZW1vLXNhLXRva2VuLWZoem5nIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlbW8tc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI0ZjU2ZjAyMy01ODU2LTExZTgtODNhYy05YTc3OWNjODlkNGUiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVtby1wa3M6ZGVtby1zYSJ9.dEBjSabWlIda27uIEUd8YWYdaDA6azuHYke5tDkEL0Hoin0vNu32TWzy0-3PBt8qNvNzQgbd-dVhkAojtpCjnqlcYz0RyAWVgTTnoJ6lLThajZEK-MI--yG9DUNiD1cbFCLca52g7BNriXbV3RKnHTvrvf8Y_jAx35heESXZLmI7cEkZ7BUTPwLGiHCKmY287orVep2Z0-JvNnUartxOHvf6WgG_POru-66uoo3uKXEcrAX7rKzTVJDRidAaNv2mmIJJezJbV6kgH2bgY5xXIzN9La6bmDOuWYdI6jsw2fWmlzsx-SuxVLZCD475oJjKxugcCv9Qo1mNimwNOxwj2w
```

このファイルを`~/.kube/config`にコピーするか、別のパスに保存し、環境変数`KUBECONFIG`にそのパスを設定した上で`kubectl`コマンドを使用すれば、
ServiceAccountのTokenで認証されます。
`demo-sa` ServiceAccountには`demo-pks`名前空間のPod読み取り権限は与えられているので、次のようにPod一覧は確認できます。

```
./create-sa-kubeconfig.sh demo-pks demo-sa > /tmp/demo-sa.yml

KUBECONFIG=/tmp/demo-sa.yml kubectl get pod
```
出力結果
```
NAME                    READY     STATUS    RESTARTS   AGE
curl-5b5b789f7f-dgjbx   1/1       Running   0          3m
```

ただし、削除はできません。
```
KUBECONFIG=/tmp/demo-sa.yml kubectl delete pod --all
```
出力結果
```
Error from server (Forbidden): pods "curl-5b5b789f7f-dgjbx" is forbidden: User "system:serviceaccount:demo-pks:demo-sa" cannot delete pods in the namespace "demo-pks"
```

その他、`kubectl get node`等も制限されています。

```
KUBECONFIG=/tmp/demo-sa.yml kubectl get node
```
出力結果
```
Error from server (Forbidden): nodes is forbidden: User "system:serviceaccount:demo-pks:demo-sa" cannot list nodes at the cluster scope
```

プロジェクト毎に名前空間を作る場合は、例えばServiceAccountに`edit` ClusterRoleをバインドし、
Configファイルを作成してプロジェクト内の開発者に配布すればプロジェクト毎のアクセスを制限できます。

また、CIツールでKubernetesにアプリケーションをデプロイしたい場合に、CIツールに設定するConfigファイルも同様に作成可能です。
