状況に応じて App Service へ Key Vault の権限を付与する Bicep を書いていたところ、ちょっと詰まったので備忘録
何がしたいのか?
App Service 作成時、パラメータで Key Vault の名前が渡された時だけ Key Vault の権限を設定したい
うまく動かなかった Bicep
keyVaultName が空じゃない場合のみ、アクセスポリシーをデプロイしたいという気持ちで書いたので、次のようにしてみました。
resource kvAccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = if(!empty(keyVaultName)) { name: '${keyVaultName}/add' properties: { accessPolicies: [ { objectId: app.identity.principalId tenantId: app.identity.tenantId permissions: { secrets: [ 'get' 'list' ] keys: [ 'get' 'list' ] certificates: [ 'get' 'list' ] } } ] } }
何で詰まったのか
ARM テンプレート上で Key Vault の名前を使ってリソースを組み立てようとするので、 Key Vault 名が空だとフォーマットエラーになるようです。
アクセスポリシーは、子要素なので、通常 KeyVault名/add
のようになるところが、/add
と組み立てられるため、フォーマットエラーとして認識されます。
A nested resource type must have identical number of segments as its resource name. A root resource type must have segment length one greater than its resource name.
ARM テンプレートは、次のように展開されます。
{ "condition": "[not(empty(parameters('keyVaultName')))]", "type": "Microsoft.KeyVault/vaults/accessPolicies", "apiVersion": "2022-07-01", "name": "[format('{0}/{1}', parameters('keyVaultName'), 'add')]", "properties": { "accessPolicies": [ { "objectId": "[reference(resourceId('Microsoft.Web/sites', format('app-{0}-{1}-{2}-{3}', parameters('workload'), parameters('tenant'), parameters('env'), parameters('location'))), '2022-03-01', 'full').identity.principalId]", "tenantId": "[reference(resourceId('Microsoft.Web/sites', format('app-{0}-{1}-{2}-{3}', parameters('workload'), parameters('tenant'), parameters('env'), parameters('location'))), '2022-03-01', 'full').identity.tenantId]", "permissions": { "secrets": [ "get", "list" ] } } ] }, "dependsOn": [ "[resourceId('Microsoft.Web/sites', format('app-{0}-{1}-{2}-{3}', parameters('workload'), parameters('tenant'), parameters('env'), parameters('location')))]" ] },
解決策
module に実装を押し込みました。
モジュールは次の通り
param keyVaultName string param objectId string param tenantId string @allowed([ 'get' 'list' 'all' 'backup' 'delete' 'purge' 'recover' 'restore' 'set' ]) param secrets array @allowed([ 'get' 'list' 'all' 'backup' 'create' 'decrypt' 'delete' 'encrypt' 'getrotationpolicy' 'import' 'list' 'purge' 'recover' 'release' 'restore' 'rotate' 'setrotationpolicy' 'sign' 'unwrapKey' 'update' 'verify' 'wrapKey' ]) param keys array @allowed([ 'get' 'list' 'all' 'backup' 'create' 'delete' 'deleteissuers' 'getissuers' 'import' 'listissuers' 'managecontacts' 'manageissuers' 'purge' 'recover' 'restore' 'setissuers' 'update' ]) param certificates array resource kvAccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = { name: '${keyVaultName}/add' properties: { accessPolicies: [ { objectId: objectId tenantId: tenantId permissions: { secrets: secrets keys: keys certificates: certificates } } ] } }
これだと、ARM テンプレートに展開された際に、モジュール呼び出し時の name が name プロパティに差し込まれるのでフォーマットエラーにならないようです。
※ ほんとにこれが根本原因なのかは、ちょっと自信ない
まとめ
Bicep は、結構はまりどころが多いですが、慣れると便利