AKSでWorkload Identityの設定と動作確認をする方法 (KeyVault編)
はじめに
Azure Kubernetes ServiceのPodに対して、Azureリソースへのアクセスに使用するマネージドIDを割り当てる方法は、現在はWorkload Identity(ワークロードID)が推奨されています。
Workload Identityを使用するAKSクラスターを構築した時、アプリケーションをデプロイする前にPodからSQL DatabaseやKeyVaultなどのAzure PaaSへの接続経路やマネージドIDによる認証が正しく構成できているかの確認を行いたいケースがあります。
今回はAKSでWorkload Identotyを設定しながら、正しく構成できているかの動作確認を行う方法をまとめてみました。
PoC環境の構成
こちらの手順をベースにAKSクラスターを展開します。
PodからWorkload IdentityでアクセスするAzure PaaSとしてKeyVaultも展開していきます。
PoC環境の準備
手元にクラスターがあるよという方はスキップして読み替えてください。
Azure CLIで使用する環境変数の設定
Azure CLIでAKSクラスターやWorkload Identityの設定を行なっていきます。
作成するリソース名などを環境変数に設定するので、必要に応じて書き換えてください。
export LOCATION="westus"
export RESOURCE_GROUP_NAME="azpoc-aks-usw-rg"
export AKS_CLUSTER_NAME="azpoc-aks-usw-aks"
export MANAGED_IDENTITY_NAME="azpoc-aks-usw-mi-wi"
export SERVICE_ACCOUNT_NAMESPACE="default"
export SERVICE_ACCOUNT_NAME="azpoc-aks-usw-mi-wi"
export KEYVAULT_NAME="azpoc-aks-usw-vault"
export KEYVAULT_SECRET_NAME="secret01"
AKSクラスターの準備
リソースグループの作成
今回の構成一式を格納するリソースグループを作ります。
不要になったらリソースグループごと削除すればOKです。
az group create \
--name "${RESOURCE_GROUP_NAME}" \
--location "${LOCATION}"
AKSクラスターの展開
--enable-oidc-issuer
と--enable-workload-identity
オプションを指定し、OIDC IssuerとWorkload Identityを有効化したAKSクラスターを展開します。
az aks create \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${AKS_CLUSTER_NAME}" \
--enable-oidc-issuer \
--enable-workload-identity \
--generate-ssh-keys
AKSクラスターへログイン
kubectlコマンドでAKSクラスターに接続するための認証情報を取得します。
az aks get-credentials \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${AKS_CLUSTER_NAME}"
kubectlは以下コマンドでインストールできます。
az aks install-cli
kubectlでクラスター情報が表示できることを確認しておきます。
kubectl cluster-info
Workload Identityの設定
PodがAzureリソースへのアクセスに使用するマネージドIDを作成し、サービスアカウントの登録とフェデレーションID資格情報の設定を行います。
マネージドIDの作成
Workload Identityで使用するマネージドIDを作成します。
このマネージドIDを使ってKeyVaultにアクセスします。
az identity create \
--name "${MANAGED_IDENTITY_NAME}" \
--resource-group "${RESOURCE_GROUP_NAME}" \
--location "${LOCATION}"
ServiceAccountの作成
先ほど作成したマネージドIDのクライアントIDを取得しおきます。
export APPLICATION_CLIENT_ID=$(az identity show \
--name "${MANAGED_IDENTITY_NAME}" \
--resource-group "${RESOURCE_GROUP_NAME}" \
--query "clientId" --output tsv)
サービスアカウントのマニュフェストをデプロイします。
作成したマネージドIDのクライアントIDをannotations
で指定しています。
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
azure.workload.identity/client-id: ${APPLICATION_CLIENT_ID}
name: "${SERVICE_ACCOUNT_NAME}"
namespace: "${SERVICE_ACCOUNT_NAMESPACE}"
EOF
フェデレーションID資格情報の設定
AKSクラスターのOIDC Issuer Endpoint URLを取得しておきます。
export AKS_OIDC_ISSUER="$(az aks show \
--name "${AKS_CLUSTER_NAME}" \
--resource-group "${RESOURCE_GROUP_NAME}" \
--query "oidcIssuerProfile.issuerUrl" \
--output tsv)"
Workload Identityで使用するマネージドIDにフェデレーションID資格情報を設定します。
az identity federated-credential create \
--name fed-identity \
--identity-name "${MANAGED_IDENTITY_NAME}" \
--resource-group "${RESOURCE_GROUP_NAME}" \
--issuer "${AKS_OIDC_ISSUER}" \
--subject system:serviceaccount:"${SERVICE_ACCOUNT_NAMESPACE}":"${SERVICE_ACCOUNT_NAME}" \
--audience api://AzureADTokenExchange
これでWorkload Identityを使うための事前設定が完了です。
KeyVaultの準備
KeyVaultの作成
PodからアクセスさせるKeyVaultを作成します。
az keyvault create \
--name "${KEYVAULT_NAME}" \
--resource-group "${RESOURCE_GROUP_NAME}" \
--location "${LOCATION}" \
--enable-rbac-authorization
KeyVaultのアクセス権設定
作成したKeyVaultのリソースIDを取得しておきます。
export KEYVAULT_RESOURCE_ID=$(az keyvault show \
--resource-group "${RESOURCE_GROUP_NAME}" \
--name "${KEYVAULT_NAME}" \
--query id \
--output tsv)
自分のEntraオブジェクトIDを取得しておきます。
export CURRENT_USER_OBJECT_ID=$(az ad signed-in-user show --query id --output tsv)
KeyVaultのシークレット作成ができるようにキー コンテナー シークレット責任者
ロールを自分に割り当てておきます。
az role assignment create \
--assignee "${CURRENT_USER_OBJECT_ID}" \
--role "Key Vault Secrets Officer" \
--scope "${KEYVAULT_RESOURCE_ID}"
Workload Identityで使用するマネージドIDのオブジェクトIDを取得しおきます。
export APPLICATION_OBJECT_ID=$(az identity show \
--name "${MANAGED_IDENTITY_NAME}" \
--resource-group "${RESOURCE_GROUP_NAME}" \
--query "principalId" \
--output tsv)
KeyVaultのシークレットをPodから参照できるようにマネージドIDへキー コンテナー シークレット ユーザー
ロールを割り当てておきます。
az role assignment create \
--assignee-object-id "${APPLICATION_OBJECT_ID}" \
--role "Key Vault Secrets User" \
--scope "${KEYVAULT_RESOURCE_ID}" \
--assignee-principal-type ServicePrincipal
KeyVaultのシークレット登録
Podが参照するシークレットををKeyVaultに登録しておきます。
az keyvault secret set \
--vault-name "${KEYVAULT_NAME}" \
--name "${KEYVAULT_SECRET_NAME}" \
--value "Hello\!"
Workload Identityの動作確認
動作確認用Podの準備
Microsoft Container Registry (MCR)はAzure FirewallのFQDNタグに含まれているので、使い勝手の良いMCRのAzure PowerShellコンテナイメージで動作確認を行います。
Azure CLIで使用する環境変数の設定
PoC環境の準備の手順でAKSクラスターを立てた方はそのままコピペしてください。ご自身の環境をがある方は適宜打ち替えてください。
export SERVICE_ACCOUNT_NAMESPACE="default"
export SERVICE_ACCOUNT_NAME="azpoc-aks-usw-mi-wi"
Workload Identityを使用するPodをデプロイ
このPodでWorkload Identityを使用するので、azure.workload.identity/use: "true"
ラベルを記述し、spec\serviceAccountName
でマネージドIDを紐づけたサービスアカウントを指定しておきます。
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: powershell
namespace: ${SERVICE_ACCOUNT_NAMESPACE}
labels:
azure.workload.identity/use: "true"
spec:
serviceAccountName: ${SERVICE_ACCOUNT_NAME}
containers:
- image: mcr.microsoft.com/azure-powershell:latest
name: powershell
command: ["sleep", "infinity"]
EOF
Podに接続
ここから先はPodの内部でコマンドを実行するので、Podのシェルに接続します。
初回はコンテナイメージのPullが実行されるので、Podが起動するまで数分かかることがあります。
kubectl exec -it powershell -- /bin/bash
Podの環境変数確認
Workload Identityを使用するPodでは、以下の環境変数が展開されます。
環境変数 | 説明 |
---|---|
AZURE_AUTHORITY_HOST | Microsoft Entra IDエンドポイントhttps://login.microsoftonline.com/ このエンドポイントに対してAzureリソースアクセス用のアクセストークンを要求する。 |
AZURE_FEDERATED_TOKEN_FILE | サービスアカウントのトークンファイルのパス。/var/run/secrets/azure/tokens/azure-identity-token このサービスアカウントトークンを添えてMicrosoft Entra IDエンドポイントにAzureリソースアクセス用のアクセストークンを要求すると、Microsoft Entra IDはAKSのOIDC Issuerでサービスアカウントトークンを検証し、Azureリソースアクセスに使用するアクセストークンを発行する。 |
AZURE_TENANT_ID | マネージドIDが登録されているEntraのテナントID |
AZURE_CLIENT_ID | マネージドIDのクライアントID |
Podに展開されている環境変数も確認してみます。
env | grep AZURE_
KeyVaultへ接続してみる
アクセストークンを発行し、KeyVaultのシークレット値を参照してみます。
冒頭の構成図に記載している①〜④のフローでアクセストークンを発行し、Azureリソースにアクセスします。
①Azureリソースアクセス用のアクセストークンを要求
サービスアカウントトークン(AZURE_FEDERATED_TOKEN_FILE
)を添えて
Microsoft Entra IDエンドポイント(AZURE_AUTHORITY_HOST
)に
Azureリソースアクセス用のアクセストークンを要求します。
②サービスアカウントのトークンを検証
Microsoft Entra IDはAKSのOIDC Issuerでサービスアカウントトークンを検証します。
③Azureリソースアクセス用のアクセストークンを発行
サービスアカウントトークンの検証に成功したら、
Microsoft Entra IDはAzureリソースアクセスに使用するアクセストークンを発行します。
④アクセストークンでAzureリソースにアクセス
Podのアプリケーションはアクセストークンを用いてAzureリソースにアクセスします。
PodでPowerShellを実行
アクセストークンの発行とKeyVaultのシークレット取得はREST APIで行います。
APIへのHTTPリクエストの送信には、今回はPowerShellのInvoke-webRequest
コマンドを使用するので、pwsh
コマンドでPowerShellを実行します。
pwsh
アクセストークンを発行する
Microsoft Entra IDエンドポイントに対してAzureリソースアクセス用のアクセストークンを要求します。
scopeはhttps://vault.azure.net/.default
を指定します。
発行されたアクセストークンを$AccessToken
に格納しておきます。
$scope="https://vault.azure.net/.default"
$jwt=$(cat ${Env:AZURE_FEDERATED_TOKEN_FILE})
$AccessToken=( `
Invoke-webRequest `
-Method "POST" `
-Body "scope=$scope&grant_type=client_credentials&client_id=${Env:AZURE_CLIENT_ID}&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=$jwt" `
"https://login.microsoftonline.com/${Env:AZURE_TENANT_ID}/oauth2/v2.0/token" `
| ConvertFrom-Json).access_token
アクセストークンを用いてKey Vaultへ接続する
PowerShellにもKeyVault名とシークレット名を環境変数で設定しておきます。
$Env:KEYVAULT_NAME="azpoc-aks-usw-vault"
$Env:KEYVAULT_SECRET_NAME="secret01"
発行されたアクセストークンを使用してKeyVaultのシークレット値を参照することができます。
(Invoke-webRequest `
-Headers @{Authorization="Bearer $AccessToken"} `
"https://${Env:KEYVAULT_NAME}.vault.azure.net/secrets/${Env:KEYVAULT_SECRET_NAME}?api-version=2016-10-01" `
| ConvertFrom-Json).value
最後に
AKSクラスターでWorkload Identityを構成し、PowerShellのみでアクセストークンの発行と動作確認を試してみました。
REST APIをコールすればアクセストークンを発行でき、アプリケーションデプロイしなくてもAKSクラスター構築時のAzure PaaSへの接続確認・RBACの認証確認ができるので、構築作業時の動作確認に便利そうです。
参考
- https://learn.microsoft.com/ja-jp/azure/aks/workload-identity-deploy-cluster
- https://learn.microsoft.com/ja-jp/azure/aks/workload-identity-deploy-cluster#create-the-federated-identity-credential
- https://azure.github.io/AKS-DevSecOps-Workshop/modules/Module1/lab-workloadidentity.html
- https://medium.com/@rakeshkumarb08/workload-identity-in-aks-5c593307bbd0
Discussion