RBAC認証によるAPIサーバへのアクセス(具体例)
認証局CAのキーファイルとこのキーファイルから作成されたCA証明書は minikube
起動時に作成されています ( .minikube/
) 。
Role-based access control (RBAC)
RBACのAPIでは、次の4種のオブジェクト (kind)
を定義しています。
Role , ClusterRole , RoleBinding, ClusterRoleBinding
新規 namespace
の作成
$ kubectl create namespace auth-test
namespace/auth-test created
RBAC認証に必要な認証用ファイルを格納するディレクトリを作成し移動
$ mkdir rbac
$ cd rbac
新規作成した namespace
にアクセスできるユーザ k9s-auth
を登録
$ sudo useradd -s /bin/bash k9s-auth
$ sudo passwd k9s-auth
新しい パスワード:
新しい パスワードを再入力してください:
passwd: パスワードは正しく更新されました
クライアント(ユーザ : k9s-auth
)側のRSAキーペア k9s-auth.key
を作成
$ openssl genpkey -algorithm RSA -out k9s-auth.key -pkeyopt rsa_keygen_bits:2048
..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.......+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+..............+......+.+...
.....
.....
..+..+.......+...............+.....+..........+.....+......+..........+......+....................+.+.....+...+.......+.....+......................+.....+.+............+..+...+..........+.........+.....+....+..+...+.+.....+......+...+.+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ユーザ公開キーの証明書署名要求 k9s-auth.csr
を作成します
$ openssl req -new -key k9s-auth.key -out k9s-auth.csr -subj "/CN=k9s-auth/O=learner"
ここで kubectl
で証明書署名要求する際に必要となる設定ファイル signing-request.yaml
を作成します。
request: <assign encoded value from next cat command>
の箇所は後ほど指定します。
$ nano signing-request.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: k9s-auth-csr
spec:
groups:
- system:authenticated
request: <assign encoded value from next cat command>
signerName: kubernetes.io/kube-apiserver-client
usages:
- digital signature
- key encipherment
- client auth
証明書署名要求をBase64でエンコードし、その出力結果を上記request: <assign encoded value from next cat command>
にコピーします。
$ cat k9s-auth.csr | base64 | tr -d '\n','%'
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0..........................
..............
..............
出力結果をコピー
$ nano signing-request.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: k9s-auth-csr
spec:
groups:
- system:authenticated
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0..........................
signerName: kubernetes.io/kube-apiserver-client
usages:
- digital signature
- key encipherment
- client auth
上記設定ファイルを指定して kubectl
で証明書署名要求オブジェクトを作成します
$ kubectl create -f signing-request.yaml
certificatesigningrequest.certificates.k8s.io/k9s-auth-csr created
上記オブジェクトの状態を確認
$ kubectl get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
k9s-auth-csr 27s kubernetes.io/kube-apiserver-client minikube-user <none> Pending
上記オブジェクトを承認します。
$ kubectl certificate approve k9s-auth-csr
certificatesigningrequest.certificates.k8s.io/k9s-auth-csr approved
再度オブジェクトの状態確認
$ kubectl get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
k9s-auth-csr 111s kubernetes.io/kube-apiserver-client minikube-user <none> Approved,Issued
証明書署名要求が承認されたので、ユーザの公開キーを含むその証明書をBase64でデコードし k9s-auth.crt
として出力します
$ kubectl get csr k9s-auth-csr -o jsonpath='{.status.certificate}' | base64 -d > k9s-auth.crt
証明書の中身を確認します
$ cat k9s-auth.crt
-----BEGIN CERTIFICATE-----
MIIDGjCCAgKgAwIBAgIQP3NjqIyzzDNEMISgSMrtcjANBgkqhkiG9w0BAQsFADAV
MRMwEQYDVQQDEwptaW5pa3ViZUNBMB4XDTIyMDkwMTAyMjM1M1oXDTIzMDkwMTAy
.....
.....
.....
1UnAKWlA8ywjohwUOmo3s6v/n4B3o6phzFLBuBlI31jWVTH8AoR6BPaWpP823Cdn
QKeOO6on+JpI1RoW1nMHZEmNC+BWBiD0brS2GlpE
-----END CERTIFICATE-----
kubectl
のクライアント設定ファイルにプライベートキーとCAによる公開キーの証明書を保有するユーザ k9s-auth
を追加します
$ kubectl config set-credentials k9s-auth --client-certificate=k9s-auth.crt --client-key=k9s-auth.key
User "k9s-auth" set.
同じく上記クライアント設定ファイルにユーザ k9s-auth
向けの新しい context : k9s-auth-context
を作成します
$ kubectl config set-context k9s-auth-context --cluster=minikube --namespace=auth-test --user=k9s-auth
k9s-auth
Context "k9s-auth-context" created.
Note) 上記 k9s-auth
と k9s-auth-context
を除外する場合
$ kubectl config unset users.k9s-auth
$ kubectl config unset contexts.k9s-auth-context
上記内容を反映したクライアント設定ファイルを確認します
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority: /home/user001/.minikube/ca.crt
extensions:
- extension:
last-update: Mon, 29 Aug 2022 15:14:57 JST
provider: minikube.sigs.k8s.io
version: v1.26.1
name: cluster_info
server: https://192.168.49.2:8443
name: minikube
contexts:
- context:
cluster: minikube
namespace: auth-test
user: k9s-auth
name: k9s-auth-context
- context:
cluster: minikube
extensions:
- extension:
last-update: Mon, 29 Aug 2022 15:14:57 JST
provider: minikube.sigs.k8s.io
version: v1.26.1
name: context_info
namespace: default
user: minikube
name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: k9s-auth
user:
client-certificate: /home/use001/rbac/k9s-auth.crt
client-key: /home/user001/rbac/k9s-auth.key
- name: minikube
user:
client-certificate: /home/user001/.minikube/profiles/minikube/client.crt
client-key: /home/user001/.minikube/profiles/minikube/client.key
namespace : auth-test
に nginx
をデプロイします
$ kubectl -n auth-test create deployment nginx --image=nginx:alpine
deployment.apps/nginx created
ここで context
を k9s-auth-context
に指定してpodの確認をすると、指定した context
でのユーザ k9s-auth
にアクセス権限が設定されていないため以下のエラーが発生します。
$ kubectl --context=k9s-auth-context get pods
Error from server (Forbidden): pods is forbidden: User "k9s-auth" cannot list resource "pods" in API group "" in the namespace "auth-test"
pod-reader
というロールオブジェクトを作成するための設定ファイルを作成します。namespace : test-auth
の pod
リソースに対して get, watch, list
の権限を付与します。
$ nano role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: auth-test
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
ロールオブジェクトを作成します
$ kubectl create -f role.yaml
role.rbac.authorization.k8s.io/pod-reader created
ロールオブジェクトの確認
$ kubectl -n auth-test get roles
NAME CREATED AT
pod-reader 2022-09-01T02:47:42Z
ロールオブジェクト pod-reader
にユーザ k9s-auth
を割当てるためのロールバインディングオブジェクトを作成するための設定ファイルを作成します。
$ nano rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-read-access
namespace: auth-test
subjects:
- kind: User
name: k9s-auth
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
上記設定ファイルを指定してオブジェクトを作成
$ kubectl create -f rolebinding.yaml
rolebinding.rbac.authorization.k8s.io/pod-read-access created
context
を指定して get
コマンドにより pod
リソースがリストアップされるかどうか確認します
$ kubectl --context=k9s-auth-context get pods
NAME READY STATUS RESTARTS AGE
nginx-d7b6f6c9c-l8gfb 1/1 Running 0 6m52s
アドミッションコントローラ
以下アドミッションコントローラにイメージプルポリシーを追加することにより、ポリシー追加前と追加後で作成されるPodにそのポリシーがどのように反映されるか確認するデモです。
初めにAPIサーバでデフォルトで有効となっているアドミッションコントローラを確認します
$ kubectl -n kube-system describe pods/kube-apiserver-minikube | grep -i admission
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
アドミッションコントローラ AlwaysPullImages
を使用しないように(イメージプルポリシーを IfNotPresent
で指定)して Nginx
をデプロイ
$ kubectl run admitted --image=nginx --image-pull-policy=IfNotPresent
pod/admitted created
上記 Pod
のステータス
$ kubectl get po
NAME READY STATUS RESTARTS AGE
admitted 1/1 Running 0 5m58s
Pod
の ImagePullPolicy
の確認(yamlフォーマットで出力)
$ kubectl get pod admitted -o yaml | grep -i imagepull
imagePullPolicy: IfNotPresent
ここでアドミッションコントローラにイメージプルポリシーを指定するため minikube ssh
で minikube
のノードにアクセスします。
$ minikube ssh
以下のコマンドで kube-apiserver
で定義されているアドミッションコントローラを確認します。
$ sudo grep admission /etc/kubernetes/manifests/kube-apiserver.yaml
- --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
結果は $ kubectl -n kube-system describe pods/kube-apiserver-minikube | grep -i admission
で出力した結果と同じになります。
kube-apiserver
の設定を変更するため、変更前の設定ファイルをバックアップしておきます。
$ sudo cp /etc/kubernetes/manifests/kube-apiserver.yaml /kube-apiserver-yaml-backup
vi
で enable-admission-plugins
に AlwaysPullImages
を追加します。
$ sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
.....
.....
- --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,AlwaysPullImages
.....
.....
kube-apiserverへのssh接続を切断します。
$ exit
アドミッションコントローラに AlwaysPullImages
が追加されていることを確認
$ kubectl -n kube-system describe pods/kube-apiserver-minikube | grep -i admission
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,AlwaysPullImages
再び アドミッションコントローラ AlwaysPullImages
を使用しないように Nginx
をデプロイ
$ kubectl run mutated --image=nginx --image-pull-policy=IfNotPresent
pod/mutated created
起動Podの確認
$ kubectl get po
NAME READY STATUS RESTARTS AGE
admitted 1/1 Running 0 76m
mutated 1/1 Running 0 82s
IfNotPresent
を指定してもアドミッションコントローラで AlwaysPullImages
を指定しているので Always
が優先されます。
$ kubectl get pod mutated -o yaml | grep -i imagepull
imagePullPolicy: Always
変更前に起動したpodについてはポリシーの変更はありません。
$ kubectl get pod admitted -o yaml | grep -i imagepull
imagePullPolicy: IfNotPresent