㊙️

Azure VMからマネージドIDを利用してAzure Key Vault内のシークレットを参照する

2023/04/13に公開

対象:★★☆

モチベ

  • 「マネージド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で編集を提案
Microsoft (有志)

Discussion