ARM模板部署InvalidTemplate错误 缺AliasPrimaryConnectionString
Azure ARM模板部署InvalidTemplate错误修复
错误基础信息
部署失败返回详情:
- 状态:Failed
- 错误码:
InvalidTemplate - 错误消息:无法处理位于第788行第5列、资源路径为
/subscriptions//resourceGroups//providers/Microsoft.KeyVault/vaults/keyvaultName/secrets/的资源对应的模板语言表达式,报错提示:The language expression property 'AliasPrimaryConnectionString' doesn't exist, available properties are 'primaryConnectionString, secondaryConnectionString, primaryKey, secondaryKey, keyName'
已知异常特征:
- 同一模板一周前可正常部署,期间未对模板内容做任何修改
- 登录Azure门户查看,Service Bus访问策略的SAS密钥中确实存在
AliasPrimaryConnectionString配置 - 当前模板调用Service Bus使用的API版本为
2017-04-01,初始排查无法定位属性缺失原因
问题涉及的模板片段:
{ "type": "Microsoft.KeyVault/vaults/secrets", "name": "[concat(variables('AppKVName'), '/DeviceOrchestrationServiceBusSendKey', if(equals(copyIndex(), 0), '', copyIndex()))]", "apiVersion": "2018-02-14", "location": "[resourceGroup().location]", "dependsOn": [ "[variables('AppKVName')]" ], "properties": { "value": "[replace(listKeys(resourceId(variables('StorageSubscriptionId'), variables('StorageResourceGroup'), 'Microsoft.ServiceBus/namespaces/topics/authorizationRules',concat(variables('AppServiceBusName'), if(equals(copyIndex(), 0), '', copyIndex())), variables('DeviceOrchestrationTopic'), variables('SendAccessKey')), variables('ServiceBusApiVersion')).AliasPrimaryConnectionString,';EntityPath=deviceorchestrationtopic', '')]" }, "copy": { "name": "DeviceOrchestrationServiceBusSendKeyCopy", "count": "[variables('PartitionCountDeviceOrchestration')]" } }
根因
AliasPrimaryConnectionString是Service Bus配置异地灾备(Geo-DR)配对后,listKeys接口才会返回的别名连接字符串字段。2017-04-01版本Service Bus API存在已知行为:当异地DR配对的复制状态未达到"已完成"、或者ARM侧资源元数据缓存未同步时,接口会直接省略所有Alias开头的返回字段。
Azure门户默认调用最新版本的Service Bus API,所以门户侧能看到该字段,但模板指定的老版本API实际返回结果中没有这个字段,就会触发模板表达式校验失败。这个缓存同步延迟最长可达10天,刚好匹配"一周前部署正常、模板未修改"的现象。
修复方案
- 优先升级模板中Service Bus的API版本:将
variables('ServiceBusApiVersion')的值修改为2021-11-01及以上的稳定版本,新版本API修复了元数据同步时字段缺失的问题,返回结构和门户展示完全对齐。 - 如果暂时无法升级API版本,需要给表达式增加属性存在性判断,避免直接访问不存在的属性触发校验错误,修改后的
properties.value写法参考:
"value": "[replace(if(contains(listKeys(resourceId(variables('StorageSubscriptionId'), variables('StorageResourceGroup'), 'Microsoft.ServiceBus/namespaces/topics/authorizationRules',concat(variables('AppServiceBusName'), if(equals(copyIndex(), 0), '', copyIndex())), variables('DeviceOrchestrationTopic'), variables('SendAccessKey')), variables('ServiceBusApiVersion')), 'AliasPrimaryConnectionString'), listKeys(resourceId(variables('StorageSubscriptionId'), variables('StorageResourceGroup'), 'Microsoft.ServiceBus/namespaces/topics/authorizationRules',concat(variables('AppServiceBusName'), if(equals(copyIndex(), 0), '', copyIndex())), variables('DeviceOrchestrationTopic'), variables('SendAccessKey')), variables('ServiceBusApiVersion')).AliasPrimaryConnectionString, listKeys(resourceId(variables('StorageSubscriptionId'), variables('StorageResourceGroup'), 'Microsoft.ServiceBus/namespaces/topics/authorizationRules',concat(variables('AppServiceBusName'), if(equals(copyIndex(), 0), '', copyIndex())), variables('DeviceOrchestrationTopic'), variables('SendAccessKey')), variables('ServiceBusApiVersion')).primaryConnectionString),';EntityPath=deviceorchestrationtopic', '')]"
上述逻辑会先判断返回结果中是否存在AliasPrimaryConnectionString字段,存在则取别名连接串,不存在则回退取主连接串,不会触发模板编译错误。
- 排查时不要以门户展示的字段为准,可手动调用对应版本的listKeys接口确认实际返回字段,和模板中使用的API版本返回保持一致。
内容的提问来源于stack exchange,提问作者Rohit Raj
相关产品推荐
相关产品推荐

