Demystifying Identities
for Azure Kubernetes Service
真壁 徹
日本マイクロソフト株式会社
クラウドソリューションアーキテクト
2020/09/18
IDを制する者はAKSを制する
背景
なぜIDが重要か
Azure Kubernetes Service(AKS)は、それ単独で使われることは稀
各種データストア、Key Vault、Azure Container Registry(ACR)など関
連サービスと組み合わせることが多い
その際に課題となるのが、関連サービスの認証認可
認証認可を支えるIDの理解は重要
IDは「サービスを組み合わせる」時代に不可欠な要素
ゼロトラスト
とか言う前に
IDを
トール・マカベッチ (2020)
背景
最近の傾向
以前はAKSに「サブスクリプションスコープの強い権限」を割り当て
て使うユーザーが多かった
そうであれば認証認可やその権限で悩むことは少ない
しかしAKSの利用が広がる中、きめ細かい権限管理が求められるよう
になってきた
背景
この資料の目的
Kubernetes、AKS、Azure関連サービスはそれぞれ進化が速い
IDの使い方や方式もその過程で変化している
現在、サービスプリンシパルからマネージドIDへの過渡期にある
きめ細かな権限管理のためにはIDとその周辺を理解する必要がある
いい機会なので整理しよう
2020/9時点での、これまで と これから
前提知識と対象範囲
Azureリソースへのアクセス権は何に割り当てるか
• Principal: 校長、社長、主体、主
犯
• セキュリティプリンシパル = ア
クセス権の付与対象となる主体
のこと
• 主体は人だけではない (Azureリ
ソースを操作する自動化アプリ
など)
セキュリティ プリンシパル
人に
割り当て
アプリに
割り当て
https://docs.microsoft.com/ja-jp/azure/role-based-access-control/overview
Azure AD
Azure RBAC
ロールの割り当て
• セキュリティプリンシパルに
• スコープを指定して
• ロールを割り当てる
https://docs.microsoft.com/ja-jp/azure/role-based-access-control/overview
AKSクラスター作成手順に出てくるあのコマンド
事前に何者かを分かってないと やらされ感ありますよね
このコマンドでサービスプリンシ
パルを作っている
既定では、サブスクリプションス
コープの共同作成者ロールをサー
ビスプリンシパルに割り当てる
--skip-assignmentでロール割り当
てをスキップ可能
az ad sp create-for-rbac
これを
作っています
参考: 3分でわかるAzureでのService Principal
Q: サービスプリンシパルはAKSのどこで使わ
れているんですか?実感がありません
A: AKSのマスターコンポーネントやノード上
のアプリケーションなど、Azure関連サービ
スの操作を委任される要素が使っています
Q: なぜ委任が必要なのですか?
A: Kubernetesは自身のコントローラを持ち、
Azureリソースを操作することがあります。
例えばService作成時にAzureのロードバラン
サーやIPを設定します。そのたびに管理者に
「設定して」と依頼が来たら嫌ですよね
AKSにおけるIDの種類
5種類ある
az aks create …
kubectl get … 1
2
4
5
1. AKSクラスター管理者向け(*)
2. AKSクラスターユーザー向け
3. Kubernetesサービスアカウント
4. AKSマスターコンポーネント向け
5. AKSノード、アプリケーション向け
AKS
マスター
AKSノードリソース
AKS関連サービス
主にこの2つでサービス
プリンシパルが使われ
ている
(*)クラスター作成をアプリ(Terraformなど)で実施する場合
に、サービスプリンシパルを使うこともある
3
この資料の対象とするID
5種のうち 情報が少ないもの2つ
クラスター管理者/ユーザー向けのID、Kubernetesサービスアカウント
公式ドキュメントなど詳しいドキュメントが多くあるので、この資料では割愛
AKSマスターコンポーネント向けのID
AKSマスター上のコンポーネント向けID
例: Cloud Controller Managerが、KubernetesのService作成時にAzure Load Balancerを操作するためのID
AKSノード、アプリケーション向けのID
AKSノード上のAKSコンポーネントやアプリケーションが使うID
例: アプリケーションがKey Vaultからシークレットを取得するためのID
ID利用方式の変遷
1. 初期(サービスプリンシパル)
2. 現在(マネージドID)
3. 将来(Pod Identity)
サービスプリンシパル
AKS初期から現在までを支える
az aks create ¥
--service-principal <appId> ¥
--client-secret <password>
事前に分かっていないと
いきなり もやっとする
サービスプリンシパルが分かりづらい理由
IDが複数あり位置づけがピンとこない、また、表現に揺れがある
Azure AD
アプリケーション
クライアントID xxx
オブジェクトID yyy
サービスプリンシパル
オブジェクトID zzz
広義のサービスプリンシパル
例えば
Terraform
Azure ADアプリケーションの
「クライアントID」で認証する
サービスプリンシパルの
「オブジェクトID」に
スコープとロールを割り当てる
az ad sp create-
for-rbac の成果物
「アプリケーションXX」「クライアントXX」「サービスプリンシパルXX」「オブジェクトXX」
残念ながらサービスやドキュメントによって表現に揺れがあるので、惑わされないよう位置づけを理解する
認証 認可
ざっくり こう覚えておきましょう
サービスプリンシパルがらみでID指定を求められたら
Azureリソースへのロール割り当て
サービスプリンシパルの
オブジェクトID
Azure ADに対する認証
Azure ADアプリの
クライアントIDと
クライアントシークレット
AKS作成時、なぜ指定しているのか
AKSマスターコンポーネントに、AKSノードリソースの操作を委任するため
Azure AD
アプリケーション
クライアントID xxx
オブジェクトID yyy
サービスプリンシパル
オブジェクトID zzz
広義のサービスプリンシパル
Azure ADアプリケーションの
「クライアントID」で認証する
AKSノードリソースを操作可能なロールを
割り当てる
az ad sp create-
for-rbac の成果物
AKSマスター AKSノードリソース
認証 認可
az aks create ¥
--service-principal <appId> ¥
--client-secret <password>
サービスプリンシパルに紐づく
Azure AD アプリケーションの
クライアントID
サービスプリンシパルに紐づく
Azure AD アプリケーションの
クライアントシークレット
AKSマスターからAzure ADに対する認証に
必要な情報なので
AKSノードリソースを
操作可能なロールって?
az aks create […] ¥
--service-principal <appId> ¥
--client-secret <password>
サービスプリンシパル作成をAKS作成コマンドにお任せして
割り当てられるロールを確かめてみよう
AKSノードリソースグループの共同作成者です
リソースグループ内で(ほぼ)フルコントロールが可能
$ az ad sp create-for-rbac […] ¥
--skip-assignment
$ az aks create […] ¥
--service-principal <appId> ¥
--client-secret <password>
ではロールを割り当てずにサービスプリンシパルを作り
それをAKS作成時に指定してみよう
同じです
AKSノードリソースグループの共同作成者ロールが割り当てられます
つまりAKSを作成すると
こんなことが起こっています
• AKSマスターの作成
• AKSノードリソースグループの作成
• サービスプリンシパルの作成(既存を指定しない場合)
• サービスプリンシパルへAKSノードリソースグループの共同作成者
ロールを割り当て
• AKSマスターにサービスプリンシパルのAzure AD アプリ クライア
ントIDとシークレット(パスワード)を登録
• AKSノードリソースグループ内でリソースを作成
既存リソースをAKSで使う場合に注意
別途ロールを割り当てる必要がある
kubectl apply –f
azure-disk-
pod.yaml AKS
マスター
AKSノードリソースグループ ディスクのある既存リソースグループ
参考: 他の Azure リソースへのアクセスを委任する
サービスプリンシパルに
対し、このディスクを操
作できるロールを割り当
てる必要がある
Microsoft.Compute/disks/read
Microsoft.Compute/disks/write
AKSノードリソースグループの外に
ある既存ディスクをボリュームと
してマウントしたい
ディスクの他ではネットワークやAzure Container
Registry(ACR)、Key Vaultは既存の別リソースグルー
プを使うケースが多い
「ロール割り当てとか、あまり意識してない
けど動いてるな~」
という場合は、つよつよな権限を割り当てて
いる可能性があります
(az ad sp create-for-rbac は既定でサブスクリプションスコープの共同
作成者を割り当てます)
これを機にご確認を
もう少し詳しく
中身に迫ってみましょう
AKSマスター AKSノード
State store
(etcd)
Scheduler
kubelet
Container
Runtime
API Server
APIs
Controller Manager
Controllers
Azure
API
Node
Features/
Configs
kube-proxy
Developer/
Admin
(**)DaemonSetなど上位オブジェクトの表現は割愛
Admission
Webhook(*)
(*)Podに配置されるケースもある
AKS ハイレベルアーキテクチャ
Pods(**)
AKSマスター
State store
(etcd)
Scheduler
API Server
APIs
Controller Manager
Controllers
Azure
API
Developer/
Admin
Admission
Webhook
マスターは(広義の)サービスプリンシパルのクライアントIDとシークレットを持つ
IDと
シークレット
認証して
トークンを得る
トークンを使って
操作要求
AKSマスターに関してはスッキリしましたね
次はAKSノードについてです
例えばACRからのイメージプル
既存のACRからプルしたい
kubectl apply –f
pod.yaml
AKS
マスター
AKSノードリソースグループ ACRのある既存リソースグループ
ACRリソースグループにあるレジ
ストリからイメージをプルしたい
どうやって認証
認可する?
AKSノード
Container
Runtime
Node
Features/
Configs
kube-proxy
AKSノードも、サービスプリンシパルの認証情報(IDとシークレット)を持つ
Pods
IDと
シークレット
認証して
トークンを得る
トークンを使って
プル
マスターと同じ認証情報が各
ノードに配布されており、
kubeletやPodはそれを読む
(/etc/kubernetes/azure.json)
kubelet
トークン
az aks create […] ¥
--attach-acr <ACR Name or ID>
AKS作成時に、サービスプリンシパルへACRPullロールを
割り当てられます
参考: Azure Kubernetes Service から Azure Container Registry の認証を受ける
スッキリしましたね
しかし、これまで説明した方式には
課題があります
サービスプリンシパル方式の課題
マスターとノードが同じサービスプリンシパルを使っている
(マスターと同じ「強い」権限がノードに必要か?)
ノードにSSHできればシークレットが見えてしまう
(マスターは隠ぺいされているが…)
サービスプリンシパルには有効期限がある
(更新忘れによる事故の懸念)
自動作成されたサービスプリンシパルが散らかる
マネージドID
サービスプリンシパルの次を担う
マネージドIDの概要
公式ドキュメントより
マネージド ID は、本質的にサービス プリンシパルのラッパーであり、
管理がより簡単になります。 MI の資格情報のローテーションは、
Azure Active Directory の既定に従って 46 日ごとに自動的に行われま
す。
参考: Azure Kubernetes Service でマネージド ID を使用する
参考: Azure リソースのマネージド ID と Azure 仮想マシンの連携
つまり
マネージドIDを使うことで期待できる効果
マネージドIDを割り当てられたVMの中では、Instance MetaData
Service(IMDS)を通じAzure ADからトークンを取得できる
よってAKSの各コンポーネントやアプリが動くVMにマネージドIDを割
り当てれば、シークレットを管理する必要がない
マネージドIDはサービスプリンシパルの作成と維持をラップし、資格
情報も更新する
操作対象のサービスによって権限を分けたければマネージドIDを分け
れば良い
良い
az aks create ¥
--enable-managed-identity
--attach-acr <my ACR Name>
マネージドIDを有効化したクラスター作ってみましょう
(ノードでの動きも見たいのでACRをアタッチします)
AKSマスター
State store
(etcd)
Scheduler
API Server
APIs
Controller Manager
Controllers
Azure
API
Developer/
Admin
Admission
Webhook
AKSマスターでは
IMDS
認証して
トークンを得る
トークンを使って
操作要求
ワシにはクライアント
シークレットなど不要
マネージドIDがAKSマス
ターに対して割り当て
られている(不可視)
マネージドIDの割り当てを確認
AKSの”servicePrincipalProfile”属性を取得
$ az aks show -g rg-aks-sp-eval -n myaks-sp-eval-mi --query “servicePrincipalProfile”
{
"clientId": "msi"
} managed service identityが
割り当てられたことを確認
マネージドIDに割り当てられたロール
ロールはノードリソースグループの共同作成者
$ az aks show -g rg-aks-sp-eval -n myaks-sp-eval-mi --query "identity"
{
"principalId": “xxx",
"tenantId": “yyy",
"type": "SystemAssigned"
}
マネージドIDにラップされた、狭義のサービスプリンシパル
(認証用のクライアントIDやシークレットは不可視)
AKSノード
kubelet
Container
Runtime
Node
Features/
Configs
kube-proxy
AKSノードでは
Pods
認証して
トークンを得る
トークンを使って
プル
ワシにはクライアント
シークレットなど不要
IMDS
マネージドIDがAKSノードに
対して割り当てられている
トークン
ノードリソースグループに 何か出来てる
マネージドIDが見えます
マネージドIDの割り当て先
AKSノードの実体であるVMSS
マネージドIDに割り当てられたロール
AcrPullロールが割り当てられている
他のサービスにアクセスする
アドオンを入れたらどうなるんだろう?
例: Azure Monitor for Containers アドオン
ノード上のエージェントから各種監視データを書き込む権限が必要
参考: コンテナーに対する Azure Monitor の概要
az aks enable-addons […] ¥
-a monitoring ¥
--workspace-resource-id <Azure Monitor
Workspace Resource ID>
アドオンを有効化してみましょう
マネージドIDとロール割り当てが追加される
AKSノードに対し、AKSクラスターをスコープに、監視メトリック発行者ロールが割り当てられる
AKSでどのようなマネージドIDが使われるか
一覧があります
Azure Kubernetes Service でマ
ネージド ID を使用する
AKSマスター向けに
自動作成される
AKSノード向けに
自動作成される
マネージドIDを個別に作成、設定するケース
AKSアドオンの場合はAzure Resource Managerがいい感じにマネージ
ドID作成とロール割り当てをしてくれます
しかし新規マネージドIDの作成や、自動作成されるマネージドIDへの
ロール割り当てが必要なケースもあります
例: AKSノードリソースグループ外のリソースを利用する場合や、公式
アドオンではないツールを入れる場合など
ロールをIDに割り当てる、という基本的な考えはサービスプリンシパ
ルと同様
参考: 他の Azure リソースへのアクセスを委任する
マスター向けマネージドIDに割り当てる例
AKSノードが参加するVNetが別リソースグループにある場合
AKSマスター
State store
(etcd)
Scheduler
API Server
APIs
Controller Manager
Controllers
Azure
API
Admission
Webhook
IMDS
認証して
トークンを得る
トークンを使って
操作要求
マネージドIDがAKSマス
ターに対して割り当て
られている(不可視)
別リソースグループ
VNetの操作権限
が必要
ロール割り当てのためにIDを取得したい
AKSマスター(コントロールプレーン) 向けマネージドID
$ az aks show -g rg-aks-sp-eval -n myaks-sp-eval-mi --query "identity"
{
"principalId": “xxx",
"tenantId": “yyy",
"type": "SystemAssigned"
}
ロール割り当てには
principalId を
AKSノード
kubelet
Container
Runtime
Node
Features/
Configs
kube-proxy
ノード向けマネージドIDに割り当てる例
Key Vaultからシークレットを取得したい場合
Pods
認証して
トークンを得る
トークンを使って
取得
IMDS
マネージドIDがAKSノードに
対して割り当てられている
別リソースグループ
Key Vault
シークレッ
トの取得権
限が必要
実装例: Azure Key Vault
Provider for Secrets Store
CSI Driver
参考: Kubernetes 上のシークレット ストア CSI ドライバー向けに Azure Key Vault プロバイダーを構成して実行する
AKSノード
kubelet
Container
Runtime
Node
Features/
Configs
kube-proxy
必要な作業はこれだけでOK?
Key Vaultからシークレットを取得したい場合
Pods
認証して
トークンを得る
トークンを使って
取得
IMDS
マネージドIDがAKSノードに
対して割り当てられている
別リソースグループ
このマネージドIDのオブジェ
クトIDに、対象Key Vaultの
シークレット取得ロールを割
り当てればいいね!
参考: Kubernetes 上のシークレット ストア CSI ドライバー向けに Azure Key Vault プロバイダーを構成して実行する
ロール割り当てのためにIDを取得したい
AKSノード(kubelet) 向けマネージドID
$ az aks show -g rg-aks-sp-eval -n myaks-sp-eval-mi --query “identityProfile”
{
“kubeletidentity”: {
“clientId”: “xxx”,
“objectId”: “yyy”,
"resourceId": "/subscriptions/mysubsctiptionid/resourcegroups/MC_rg-aks-sp-eval_myaks-sp-
eval-mi_japaneast/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myaks-sp-eval-
mi-agentpool"
}
}
ロール割り当てには
objectId を
(ご参考) Terraform Attribute
azurerm_kubernetes_cluster
resource "azurerm_key_vault_access_policy" "aks" {
key_vault_id = azurerm_key_vault.sample.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id =
azurerm_kubernetes_cluster.sample.kubelet_identity.0.object_id
secret_permissions = [
"get",
]
}
AKSマスター(コント
ロールプレーン)
AKSノード(kubelet) AKSノードに割り当てたkubeletマネージドIDに
Key Vaultのシークレット取得権限を付与する例
apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
name: azure-tls
namespace: ingress-test
spec:
parameters:
usePodIdentity: "false"
useVMManagedIdentity: "true"
userAssignedIdentityID: “???????"
keyvaultName: “MY_KEYVAULT_NAME"
[snip]
ではSecret Store CSI Driverの設定を…
どのIDを指定すればいいの?
IMDSに向かって叫べばいい
んじゃないの?
AKSノード
マネージドIDはノードに複数割り当てられる
なので使うマネージドIDを指定しなければならない
Azure Monitor
Agent Pods
Secret Store
CSI Driver
Pods
kubelet
IMDS
apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
name: azure-tls
namespace: ingress-test
spec:
parameters:
usePodIdentity: "false"
useVMManagedIdentity: "true"
userAssignedIdentityID: “CLIENT_ID_OF_MY_MANAGED_ID_FOR_KUBELET"
keyvaultName: “MY_KEYVAULT_NAME"
[snip]
こう指定します
自動作成されるkubeletマネージドIDに、Key Vaultのロー
ルを割り当てて使う例
Azure ADに対する認証を行うIDなので、マネージドIDの
クライアントIDを指定する
なお、Key Vault向けにマネージドIDを新規作成してもOK
そのほうが権限分離の観点では望ましいが、ID作成や維持
に関する負担とのバランスを考慮し判断する
サービスプリンシパルをそのまま使うのに比
べ、格段に進歩しました
しかし、まだ課題があります
マネージドID方式の課題
Podが使うマネージドIDを直に設定したくない
常時アクセスを許可するのではなく、時間を限定したい
(平日の夜間のみ、など)
他IDコミュニティとの連携も視野に(SPIFFEなど)
Azure AD Pod Identity
将来に向けて
Pod Identity概要
参考: ポッドIDを使用する
マネージドIDを使っ
てAzure AD認証する
のはこれまでと同様
PodからIMDSへの要求はNMIへリダイレ
クトされ、NMIはバインディングの確認
とAzure ADへの代理認証を行う
Podと利用可能なマネー
ジドIDをバインドする
利用方法のイメージ
AzureIdentityとAzureIdentityBIndingを作る
apiVersion: "aadpodidentity.k8s.io/v1"
kind: AzureIdentityBinding
metadata:
name: ${IDENTITY_NAME}-binding
spec:
azureIdentity: ${IDENTITY_NAME}
selector: ${IDENTITY_NAME}
apiVersion: "aadpodidentity.k8s.io/v1"
kind: AzureIdentity
metadata:
name: ${IDENTITY_NAME}
spec:
type: 0
resourceID: ${IDENTITY_RESOURCE_ID}
clientID: ${IDENTITY_CLIENT_ID}
参考: AAD Pod Identity
マネージドID
PodからマネージドID
を指定できるセレクタ
を作る
利用方法のイメージ
Podでセレクタを指定する
apiVersion: v1
kind: Pod
metadata:
name: demo
labels:
aadpodidbinding: $IDENTITY_NAME
参考: AAD Pod Identity
AzureIdentityBinding で
作成したセレクタ
アプリ開発者はマネージドIDを直
に設定する必要がない
Pod Identityの現状
オープンソース アップストリームプロジェクトという位置づけ
Pod Identityは現状Azureテクニ
カルサポートの対象ではない
現時点ではユーザー自身での問
題解決が必要
フィードバックをお待ちしております
Pod IdentityはGitHub上でオープンに開発されています
https://github.com/Azure/aad-pod-
identity/blob/master/docs/design/concept.md
まとめ
ゼロトラスト
とか言う前に
IDを
トール・マカベッチ (2020)
© Copyright Microsoft Corporation. All rights reserved.

Demystifying Identities for Azure Kubernetes Service