💪

Bicep使うときに[KeyVault].getSecret()の類に気を付けような

2023/08/24に公開

モチベ

Azure Key Vaultを参照するインフラのデプロイが厄介だと聞き、ちょっと試してみたところ思ったより厄介だったので試したことを順番に記録していく

実現したいこと

1回のデプロイの中で、

  1. Key Vaultをデプロイし
  2. Key VaultにシークレットとしてVMの管理者パスワードを格納し
  3. そのシークレットを参照する形でVMを作成する

ソース

諸々の試行錯誤の後に出来上がったものにはなるが、ソースとしてはこちら

https://github.com/zukakosan/bicep-vmwithkv/tree/main

注意事項

手順3でKey Vaultのシークレットを参照する際、getSecret()のような関数を利用するのだが、これはmoduleの変数として渡す必要があり、例えばvm.bicepの中で利用することができないという制約がある(なぜ)。

module CreateVM './modules/vm.bicep' = {
  name: 'create-vm-module'
  params: {
    location: resourceGroup().location
    vmName: vmName
    vnetName: vnetName
    subnetName: subnetName
    vmAdminUserName: vmAdminUserName
    vmAdminPassword: keyVault.getSecret('vmAdminPassword')
  }
  dependsOn: [
    CreateVnet
  ]
}

やってみる

最初の取り組み

  • 構成自体はシンプルなため、とりあえず以下のイメージでBicepファイル群を構成し、Azure CLIにてデプロイする
  • main.bicepではKeyVaultの作成も実施している。
main.bicep
Modules/
    ∟vnet.bicep
    ∟vm.bicep
  • デプロイしてみると、以下のようなエラーとともに終了
  • 依存関係的には先にKey Vaultを作っているので問題ないはずと思いつつ、公式ドキュメントを見てみるとexisting =で参照しているので、同じbicep上でKey Vaultの作成と呼び出しを行っているのがよくないのかと思い、そこを分割しようとするのが次の取り組み

https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/key-vault-parameter?tabs=azure-cli#use-getsecret-function

{"code": "KeyVaultParameterReferenceNotFound", "message": "The specified KeyVault '/subscriptions/<subID>/resourceGroups/20230823-bicepvmwithkv/providers/Microsoft.KeyVault/vaults/kv-cloud' could not be found. Please see https://aka.ms/arm-keyvault for usage details."}

Key Vaultの作成の分離

先の事情によりgetStart.bicepを作成し、そこでKey Vaultの作成と、main.bicepの呼び出しを行うように変更した。実行すると、同様のエラーで終了。デプロイに際してARMテンプレートが生成されるので結果が同じであることは目に見えていたが…一応。

エラー調査

KeyVault Bicep getSecret Notfound等で検索すると、結構出てきた。KeyVaultの作成と参照を一連のデプロイの中でできずに悩んでいる同志が結構いる模様。

https://github.com/Azure/bicep/issues/10562

  • コメントを追っていくと、表現を借りるとやはりpreflight validationによってデプロイ前にブロックされている、という認識はあっていそう

  • BicepではTerraformのような状態管理の仕組みが存在しないため、デプロイ前の静的チェックが厳密に行われるのかもしれない

  • とはいえ、同僚は同様の構造でデプロイできていると聞いていたため、同僚のやり方倣ってAzure CLIではなく、VSCode上でBicepファイルを直接デプロイするという方法でデプロイを投げてみた

  • すると、すんなりデプロイできてしまった

  • てことはつまり、Azure CLIでのバリデーションの問題なのか…?ということでKeyVaultの作成もmain.bicepに含めてしまってもいいはずという考えから、main.bicepでKey Vaultの作成も実行するパターンで、VSCodeからBicepをデプロイ

  • すると、成功

  • 結果から見るに、.getSecret()とAzure CLIの相性がよくない(過剰にvalidationがかかる)ということになる

Azure PowerShellならどうか

  • Azure PowerShellでもAzure CLIと同様のエラーが出た
  • KeyVaultが見つからないと言われる
New-AzResourceGroupDeployment : 10:47:48 - Error: Code=KeyVaultParameterReferenceNotFound; Message=The specified KeyVault '/subscriptions/<subID>/resourceGroups/20230824-depbyps/providers/Microsoft.KeyVault/vaults/kv-cloud-inckv' could not be found. 

まとめ

  • つまり、現状Key Vaultのデプロイとインフラのデプロイを一挙にやりたい場合には、Visual Studio Codeにて右クリックでデプロイするしかないということになってしまう
  • 右クリックでのデプロイであれば、おそらくPreflight Validationが回避されてデプロイできるという検証結果になった、なんとも微妙な挙動
  • とはいえ、本筋としてはAzure CLI/PowerShellから叩くやり方になるはずなので、Bicepの思想としてKey Vaultのデプロイとインフラのデプロイを分離しろというのがあるかもしれない

おわり

  • Bicep、便利で面白いけどたまに不安になる
  • [KeyVault].getSecret()以外にも、このような挙動をするものはありそう
GitHubで編集を提案
Microsoft (有志)

Discussion