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

使用Bicep模块创建Function App后获取默认主机密钥遇问题

问题描述

原本已实现主模板内直接创建Function App并使用其密钥的Bicep模板,现需调整为:通过主模板调用Bicep模块创建Function App,再将该Function App的密钥传入另一模块,存储为APIM机密命名值。

初始方案与编译错误

参考ChatGPT给出的方案:

// Create the Function App
module functionApp 'br:azcontreg.azurecr.io/bicep/modules/functionapp:v23.01.17.01' = {
  name: 'functionApp'
  params: {
    functionAppName: functionAppName
    appServicePlanName: appServicePlanName
    appServicePlanResourceGroup: appServicePlanResourceGroup
    storageAccountName: storageAccountName
    storageAccountResourceGroup: storageAccountResourceGroup
  }
}

// Retrieve the Function App keys
output functionAppKeys object = listKeys(functionApp.outputs.id, '2019-08-01')

// Create the API Management named value
module apimNamedValue 'br:azcontreg.azurecr.io/bicep/modules/apimnamedvalue:v23.01.17.01' = {
  name: 'apimNamedValue'
  scope: resourceGroup('rg-apim-${subscription().displayName}')
  dependsOn: [
    functionApp
    keyVault
  ]
  params: {
    name: '${functionApp.outputs.appServiceName}-key'
    secret: true
    value: functionAppKeys.keys[0].value
    environment: environment
  }
}

执行时出现编译错误:

This expression is being used in an argument of the function
"listKeys", which requires a value that can be calculated at the start
of the deployment. Properties of functionApp which can be calculated
at the start include "name".bicep(BCP181)

调整后的代码与部署错误

Function App模块代码

resource appService 'Microsoft.Web/sites@2021-03-01' = {
    name: name
    kind: appKind
    location: location
    tags: tags
    identity: {
        type: !empty(identityName) ? 'SystemAssigned, UserAssigned' : 'SystemAssigned'
        userAssignedIdentities: !empty(identityName) ? { 
            '${appServiceIdentity.id}': {}
        } : null
    }
    properties: {
        httpsOnly: true
        reserved: false
        serverFarmId: appServicePlan.id
        virtualNetworkSubnetId: !empty(vnetName) && !empty(vnetSubnetName) ? vnetSubnet.id : null
    }

    resource appServiceAppSettings 'config' = {
        name: 'appsettings'
        properties: appSettingsInternal
    }

    resource appServiceSlotConfigNames 'config' = {
        name: 'slotConfigNames'
        properties: {
            appSettingNames: deploymentSlotSettingNames
        }
    }

    resource appServiceWeb 'config' = {
        name: 'web'
        properties: {
            alwaysOn: alwaysOn
            ftpsState: 'FtpsOnly'
            healthCheckPath: healthCheckPath
            ipSecurityRestrictions: ipSecurityRestrictions
            use32BitWorkerProcess: use32BitProcess
            vnetRouteAllEnabled: vnetRouteAll
        }
    }
}
output appServiceId string = appService.id

主模板调用Function App模块

module functionApp 'br:crbicepregistryprod001.azurecr.io/bicep/modules/appservice:v23.04.13.01' = {
  name: 'functionApp'
  params: {
    name: functionAppName
    appServicePlanScope: functionAppServicePlanEnv.rg
    appServicePlanName: functionAppServicePlanEnv.name
    appKind: 'functionapp'
    vnetName: 'vnet-${environment}-uksouth'
    vnetSubnetName: functionAppServicePlanEnv.subnet
    ipSecurityRestrictions: functionAppIpSecurityRestrictions
    appSettings: functionAppSettings
    enableSlot: false
    alwaysOn: true
    healthCheckPath: '/health'
  }
  dependsOn: [
    appInsights
    keyVault
  ]
}

主模板调用APIM命名值模块

module apimNamedValue 'br:crbicepregistryprod001.azurecr.io/bicep/modules/apimnamedvalueforlistkeys:v23.06.13.02' = {
  name: 'apimNamedValue'
  scope: resourceGroup('rg-apim-${subscription().displayName}')
  dependsOn: [
    functionApp
    keyVault
  ]
  params: {
    name: '${functionApp.outputs.appServiceName}-key'
    secret: true
    resourceId: functionApp.outputs.appServiceId
    environment: environment
  }
}

APIM命名值模块代码(用于获取密钥)

@description('Name of the NamedValue to deploy')
param name string

@description('Resource Id to be used in the listkeys function')
param resourceId string

@description('Used in listkeys function')
param apiVersion string = '2022-09-01'

@description('Specify if the value is secret. Defaults to false')
param secret bool = false

@description('Specify if the value is a key vault reference. Also implies value is secret. Defaults to false')
param keyVaultReference bool = false

@description('APIM environment to deploy to')
@allowed([
    'dev'
    'int'
    'act'
    'prod'
])
param environment string = 'dev'

var apimName = {
    dev: 'apim-dev-002'
    int: 'apim-int-001'
    act: 'apim-act-001'
    prod: 'apim-prod-002'
}[environment]

var value = listKeys(resourceId, apiVersion)
resource apim 'Microsoft.ApiManagement/service@2021-08-01' existing = {
    name: apimName

    resource apimNamedValue 'namedValues' = {
        name: name
        properties: {
            displayName: name
            secret: secret || keyVaultReference
            keyVault: keyVaultReference ? {
                secretIdentifier: value
            } : null
            value: !keyVaultReference ? value : null
        }
    }
}

output namedValueId string = apim::apimNamedValue.id
output namedValueName string = apim::apimNamedValue.name
output namedValueNameFormatted string = '{{${apim::apimNamedValue.name}}}'

部署错误信息

在Azure门户查看资源组部署时,仅返回如下错误:

{
  "code": "BadRequest",
  "message": ""
}

错误猜测

推测错误原因是:APIM模块运行在APIM所在的资源组范围内,尝试访问另一资源组中Function App的密钥时,因权限或跨资源组访问问题导致“未找到”错误。


内容的提问来源于stack exchange,提问作者Rob Bowman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:47:00