部署Key Vault访问策略时,Bicep中如何引用系统分配身份?
问题:引用App Service托管标识principalId失败的原因及修复方案
问题背景
需要通过Bicep模板向Azure部署三个关联资源:
- 带有系统分配托管标识的App Service
- Key Vault
- 允许App Service访问Key Vault的访问策略
App Service模块输出系统分配标识的principalId,部署Key Vault访问策略时需引用该值。但执行AZ CLI订阅级部署命令:
az deployment sub create --location WestEurope --template-file ./main.bicep --parameters ./parameters/parameters-dev.json
出现错误:
'The language expression property 'outputs' doesn't exist, available properties are 'templateHash, parameters, mode, provisioningState, timestamp, duration, correlationId, providers, dependencies, outputResources'.
相关代码
main.bicep
module appService 'modules/appService.bicep' = { name: 'deployAppService' scope: resourceGroup(appServiceResourceGroup) params: { name: appServiceName location: appServiceLocation alwaysOn: appServiceAlwaysOn apimIpAddress: appServiceApimIpAddress appServicePlanResourceGroup: appServicePlanResourceGroup appServicePlanName: appServicePlanName } } module keyVault 'modules/keyVault.bicep' = { name: 'deployKeyVault' scope: resourceGroup(appServiceResourceGroup) params: { name: keyVaultName dependsOn: [ appService ] location: appServiceLocation } } module keyVaultAccessPolicy 'modules/keyVaultAccessPolicy.bicep' = { name: 'deployKeyVaultAccessPolicy' scope: resourceGroup(appServiceResourceGroup) params: { name: '${appServiceName}-ap' dependsOn: [ keyVault ] objectId: appService.outputs.appServiceManagedIdentity } }
appService.bicep
param name string param location string param alwaysOn bool param apimIpAddress string param appServicePlanResourceGroup string param appServicePlanName string resource appService 'Microsoft.Web/sites@2020-12-01' = { name: name location: location kind: 'app' identity: { type: 'SystemAssigned' } properties: { serverFarmId: '${subscription().id}/resourceGroups/${appServicePlanResourceGroup}/providers/Microsoft.Web/serverfarms/${appServicePlanName}' enabled: true alwaysOn: alwaysOn } } output appServiceManagedIdentity string = appService.identity.principalId
keyVault.bicep
param name string param location string param dependsOn array resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { name: name location: location dependsOn: dependsOn properties: { enabledForDeployment: true enabledForTemplateDeployment: true enabledForDiskEncryption: true tenantId: subscription().tenantId accessPolicies: [] sku: { name: 'standard' family: 'A' } } }
keyVaultAccessPolicy.bicep
param name string param dependsOn array param objectId string resource keyVaultAccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = { name: name dependsOn: dependsOn properties: { accessPolicies: [ { tenantId: subscription().tenantId objectId: objectId permissions: { secrets: [ 'get' ] } } ] } }
问题原因
- 模块输出引用语法错误:Bicep中引用模块输出的正确方式是
模块实例名.输出名,而非模块实例名.outputs.输出名——后者是ARM模板的语法,不适用于Bicep。 - 依赖传递方式错误:
dependsOn是模块/资源的顶级属性,不能作为参数传入子模块,这种写法会导致Bicep无法正确解析依赖关系。 - Key Vault访问策略子资源定义错误:访问策略是Key Vault的子资源,需要通过
parent属性关联父资源,而非仅通过名称拼接。
修复方案
1. 修正模块输出引用语法
在main.bicep中,将appService.outputs.appServiceManagedIdentity改为appService.appServiceManagedIdentity:
module keyVaultAccessPolicy 'modules/keyVaultAccessPolicy.bicep' = { name: 'deployKeyVaultAccessPolicy' scope: resourceGroup(appServiceResourceGroup) params: { keyVaultName: keyVaultName objectId: appService.appServiceManagedIdentity // 修正引用方式 } }
2. 调整依赖管理方式
将dependsOn从子模块参数移到模块的顶级属性:
main.bicep中的keyVault模块
module keyVault 'modules/keyVault.bicep' = { name: 'deployKeyVault' scope: resourceGroup(appServiceResourceGroup) dependsOn: [ appService ] // 定义模块依赖 params: { name: keyVaultName location: appServiceLocation } }
main.bicep中的keyVaultAccessPolicy模块
module keyVaultAccessPolicy 'modules/keyVaultAccessPolicy.bicep' = { name: 'deployKeyVaultAccessPolicy' scope: resourceGroup(appServiceResourceGroup) dependsOn: [ keyVault ] // 定义模块依赖 params: { keyVaultName: keyVaultName objectId: appService.appServiceManagedIdentity } }
移除子模块中的dependsOn参数
修改keyVault.bicep,去掉dependsOn参数和资源中的dependsOn属性:
param name string param location string resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { name: name location: location properties: { enabledForDeployment: true enabledForTemplateDeployment: true enabledForDiskEncryption: true tenantId: subscription().tenantId accessPolicies: [] sku: { name: 'standard' family: 'A' } } }
3. 修正Key Vault访问策略的子资源定义
修改keyVaultAccessPolicy.bicep,通过existing资源引用父Key Vault,并设置parent属性:
param keyVaultName string param objectId string // 引用已存在的Key Vault资源 resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { name: keyVaultName } // 定义访问策略子资源,指定parent resource keyVaultAccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = { parent: keyVault name: 'add' // 访问策略子资源名称固定为'add' properties: { accessPolicies: [ { tenantId: subscription().tenantId objectId: objectId permissions: { secrets: [ 'get' ] } } ] } }
验证修复
重新执行AZ CLI部署命令,此时Bicep会正确解析模块输出、依赖关系以及子资源关联,部署将正常完成。
内容的提问来源于stack exchange,提问作者JJuice
相关产品推荐
相关产品推荐

