㊙️
Azure VMからマネージドIDを利用してAzure Key Vault内のシークレットを参照する
対象:★★☆
モチベ
- 「マネージドIDを利用することで、アプリにシークレット埋め込まなくてもよくなります」という話はよく耳にする
- けど、VMからAzure Key Vaultの認証通す際のイメージが湧いてなかった
- ので試す。
リソース
VM
- 適当に作成
- RDP用に3389は開けておく
マネージドIDの作成
- VM管理画面からマネージドIDを有効化
- 今回は「システム割り当て」を選択
- VM台数が多数ある場合は「ユーザ割り当て」で同一のIDを使いまわすことも考えられる
RBACロール付与
- マネージドIDの画面(この画面)からもRBACロールが付与できるが、このビューからのRBACロール付与はPreview(細かいw)
- 対象のAzure Key Vaultを選択して「キーコンテナーシークレットユーザー」を付与
- Azure Key Vaultの画面でのロール付与が通常のパターン
- ※Azure Key Vaultがポリシーベースの場合、VMのマネージドIDにシークレットの参照を許可するようなポリシーを付与
Azure Key Vault(キーコンテナー)
- 既定ではアクセスポリシーベースのAzure Key Vaultが作成されるため、RBACベースのものにする
シークレットの作成
- 共同作成者ロールとは別に、自分に「キーコンテナー管理者」を付与する
- これがないと、シークレット等の作成ができない
- テスト用のシークレットを作成
- シークレット値は分かり易く
this-is-test-secret
とした
VM上でのシークレットの利用
- 今回は、PowerShellから利用する
- トークンを取得し、KeyVaultに投げ、認証をクリアしてシークレットを取得
- VM内からしか叩けないエンドポイント(Metadata Service=169.254.289.254)の特定のエンドポイントに対してTokenを要求
$Response = Invoke-RestMethod -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fvault.azure.net' -Method GET -Headers @{Metadata="true"}
- アクセストークンを変数に格納
$KeyVaultToken = $Response.access_token
- トークンとともにAzure Key Vaultのエンドポイントにリクエストを投げ、認証を通しつつシークレットの値を取得する
Invoke-RestMethod -Uri https://<your-key-vault-URL>/secrets/<secret-name>?api-version=2016-10-01 -Method GET -Headers @{Authorization="Bearer $KeyVaultToken"}
- VM側でシークレットの取得ができていることを確認
PS C:\Users\AzureAdmin> Invoke-RestMethod -Uri https://akv-koishizu-01.vault.azure.net/secrets/secret-for-vm?api-version=2016-10-01 -Method GET -Headers @{Authorization="Bearer $KeyVaultToken"}
value id attributes tags
----- -- ---------- ----
this-is-test-secret https://akv-koishizu-01.vault.azure.net/secrets/secret-for-vm/343c4a567da448d98d02216e51ece4ca @{enabled=True; created=1681375010; updated=1681375010; recoveryLevel=Recoverable+Purgeable}
VMのマネージドIDでRBACロールを外した場合
- 権限がない場合の挙動を確認
- Azure Key Vaultのリソース側、「アクセス制御」からロールの割り当てを削除
- VM上からリクエストを投げてみると、
Forbidden
となり、シークレットを取得できない- つまり、VMのマネージドIDを表すトークンを認可に使うが、権限がないということ
- RBACロールがマネージドIDに対しても機能している!!
PS C:\Users\AzureAdmin> Invoke-RestMethod -Uri https://akv-koishizu-01.vault.azure.net/secrets/secret-for-vm?api-version=2016-10-01 -Method GET -Headers @{Authorization="Bearer $KeyVaultToken"}
Invoke-RestMethod : {"error":{"code":"Forbidden","message":"Caller is not authorized to perform action on resource.\r\nIf role assignments, deny assignments or role definitions were changed recently, please observe propagation
time.\r\nCaller: appid=2716e189-2dd0-421f-9979-ed43cee39dc1;oid=5fbc64bb-ecd9-4b44-9c44-03c314cf90c0;iss=https://sts.windows.net/ec568c69-965a-495b-8823-a7f3c2dc890f/\r\nAction:
'Microsoft.KeyVault/vaults/secrets/getSecret/action'\r\nResource:
'/subscriptions/42edd95d-ae8d-41c1-ac55-40bf336687b4/resourcegroups/20230413-vm-mid-kv/providers/microsoft.keyvault/vaults/akv-koishizu-01/secrets/secret-for-vm'\r\nAssignment: (not found)\r\nVault:
akv-koishizu-01;location=japaneast\r\n","innererror":{"code":"ForbiddenByRbac"}}}
At line:1 char:1
+ Invoke-RestMethod -Uri https://akv-koishizu-01.vault.azure.net/secret ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
おわり
- 触ってみるとイメージが湧くなぁ
- Metadata ServiceはVMのメンテナンス(Scheduled Event)を取りに行く際にも叩くので、扱えるようにせねば、うん
GitHubで編集を提案
Discussion