昨日はSPIFFEとその参照実装であるSPIREについてのエントリを書きましたが、本日はSPIREのワークロードとしてKubernetesのPodを対象とする場合に利用するKubernetesのworkload attestor pluginの動きを説明します。
Kubernetes workload attestor plugin とは
SPIRE-Agentのworkload attestorのプラグインとして動作します。
Worload AttestorとはWorkload APIの呼び出し元の情報からSelector情報を生成するコンポーネントでした。
Kubernetes pluginの場合には呼び出し元Workloadのpidからそのpidで動作するPodのNamespaceとServiceAccountの情報を収集します。つまり、呼び出し元のワークロードが動作するPodに紐づくNamespaceとServiceAccount情報を収集します。
How to work this plugin?
/proc/${PID}/cgroup
KubernetesのPodを動しているpidの場合、上記ファイルを開くとこのような情報が確認できます。このプラグインはkubepodsのエントリのContainerID(一番後ろの要素)を抜き出します。(ContainerIDは全部同じ)
11:memory:/kubepods/besteffort/pod2ece296c-c5ec-11e7-858e-fa163e451acc/bc1eb339399eae78dd1115c765fda84b71ac6a954291b223820cfe775d8af778
10:freezer:/kubepods/besteffort/pod2ece296c-c5ec-11e7-858e-fa163e451acc/bc1eb339399eae78dd1115c765fda84b71ac6a954291b223820cfe775d8af778
9:perf_event:/kubepods/besteffort/pod2ece296c-c5ec-11e7-858e-fa163e451acc/bc1eb339399eae78dd1115c765fda84b71ac6a954291b223820cfe775d8af778
8:devices:/kubepods/besteffort/pod2ece296c-c5ec-11e7-858e-fa163e451acc/bc1eb339399eae78dd1115c765fda84b71ac6a954291b223820cfe775d8af778
7:pids:/kubepods/besteffort/pod2ece296c-c5ec-11e7-858e-fa163e451acc/bc1eb339399eae78dd1115c765fda84b71ac6a954291b223820cfe775d8af778
6:cpu,cpuacct:/kubepods/besteffort/pod2ece296c-c5ec-11e7-858e-fa163e451acc/bc1eb339399eae78dd1115c765fda84b71ac6a954291b223820cfe775d8af778
5:net_cls,net_prio:/kubepods/besteffort/pod2ece296c-c5ec-11e7-858e-fa163e451acc/bc1eb339399eae78dd1115c765fda84b71ac6a954291b223820cfe775d8af778
4:hugetlb:/kubepods/besteffort/pod2ece296c-c5ec-11e7-858e-fa163e451acc/bc1eb339399eae78dd1115c765fda84b71ac6a954291b223820cfe775d8af778
3:blkio:/kubepods/besteffort/pod2ece296c-c5ec-11e7-858e-fa163e451acc/bc1eb339399eae78dd1115c765fda84b71ac6a954291b223820cfe775d8af778
2:cpuset:/kubepods/besteffort/pod2ece296c-c5ec-11e7-858e-fa163e451acc/bc1eb339399eae78dd1115c765fda84b71ac6a954291b223820cfe775d8af778
1:name=systemd:/kubepods/besteffort/pod2ece296c-c5ec-11e7-858e-fa163e451acc/bc1eb339399eae78dd1115c765fda84b71ac6a954291b223820cfe775d8af778
また、kubeletのReadOnlyポートにアクセスし、自身の上で動作するPod情報の一覧をPod情報を取得します。
http://localhost:${KUBELET_READONLY_PORT}/pods
https://kubernetes.io/docs/api-reference/v1.8/#podlist-v1-core
アクセスすると上記URLにて定義されている情報が返ってきます。
Kuberentes Pluginにおいて必要な情報は各レコードの3つの情報です。
.metadata.namespace
.spec.serviceaccount
-
.status.containerStatuses[*].containerID
(e.g., docker://')
プラグインはcgroupの情報から取得したContainerIDと上記Kubeletから取得したContainer情報が一致するPod情報を探します。ちなみに、Podの情報に含まれるContainerIDは docker://...
のような文字列になっているのでURL構造と見立てた場合のホスト部とcgroupのContainerIDを比較します。
そうして、一致したPod情報に含まれるServiceAccountとNamespaceの情報をSelectorとして返却するわけです。
[]*Selector{
&Selector{
Type: "k8s",
Value: "k8s:ns:${Namespace}"
},
&Selector{
Type: "k8s",
Value: "k8s:sa:${ServiceAccount}"
},
...
}
最後にこれを受け取ったWorkload AttestorはSPIRE-Server側にこのワークロードが対象として登録済みかどうかを確かめるために、Serverから取得した自身の上で動作可能なSelector情報と、Workload Atterstorによって生成されたSelector情報を比較します。
一致するものがあれば許可されたWorkloadであると判断しSVIDを渡します。
おわりに
このようにKubernetesのPodもSPIREのワークロードとして動作させることが可能であり、PodとKubernetesクラスタ外のアプリケーションを相互認証させることができます。
自分は今後も継続してSPIFFE/SPIREの動向をウォッチしていこうと思っています。また何かあれば何らかの形でフィードバックしたいと思います。