You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部署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'
          ]
        }
      }
    ]
  }
}

问题原因

  1. 模块输出引用语法错误:Bicep中引用模块输出的正确方式是模块实例名.输出名,而非模块实例名.outputs.输出名——后者是ARM模板的语法,不适用于Bicep。
  2. 依赖传递方式错误:dependsOn是模块/资源的顶级属性,不能作为参数传入子模块,这种写法会导致Bicep无法正确解析依赖关系。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 07:09:12