如何在ARM模板参数数组中引用Azure Key Vault密钥?
问题:通过ARM模板将Key Vault密钥与批量环境变量配置到App Service应用设置
需求说明
需要通过ARM模板部署App Service Web应用,实现以下目标:
- 将Azure Key Vault中的密钥配置为应用设置(环境变量)
- 保留原有通过参数文件值数组批量填充应用设置的方式,并将Key Vault密钥加入该数组
- 同时配置App Insights的Instrumentation Key到应用设置,用
copy函数批量处理参数数组中的环境变量
已尝试的失败方案
直接在数组元素中引用Key Vault
尝试在参数文件的环境变量数组中直接嵌套Key Vault引用结构,部署失败:{ "name": "KVsecret1", "reference": { "keyVault": { "id": "/subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.KeyVault/vaults/<vault_name>" }, "secretName": "secret1" } }定义Key Vault引用参数后在数组中调用
先在参数顶层定义Key Vault引用参数,再在环境变量数组中调用,结果仅使用了字面字符串值,未正确拉取密钥:"parameters": { "KVsecret1": { "reference": { "keyVault": { "id": "/subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.KeyVault/vaults/<vault_name>" }, "secretName": "KVsecret1" } }, "envVars": { "value": [ { "name": "envVarKeyName", "value": "stringLiteralValueHere" }, { "name": "KVsecret1", "value": "[parameters('KVsecret1')]" } ] } }批量配置的copy函数问题
尝试用copy函数批量处理环境变量时,因copy的name配置错误,无法动态生成应用设置的键值对:{ "type": "Microsoft.Web/sites/config", "apiVersion": "2022-03-01", "name": "[concat(parameters('backEndwebAppName'),'/appsettings')]", "properties": { "APPINSIGHTS_INSTRUMENTATIONKEY": "[reference(concat('microsoft.insights/components/',parameters('appInsightsName')),'2020-02-02').InstrumentationKey]", "secret1FromKeyvault": "[parameters('secret1FromKeyvault')]", "copy": [ { "name": "envVarsFromParams", "count": "[length(parameters('backEndEnvVariables'))]", "input": { "name": "[parameters('backEndEnvVariables')[copyIndex('envVarsFromParams').name]]", "value": "[parameters('backEndEnvVariables')[copyIndex('envVarsFromParams').value]]" } } ] }, "dependsOn": [ "[resourceId('Microsoft.Web/sites', parameters('backEndwebAppName'))]" ] }
可行实现方案
方案1:分离普通变量与Key Vault引用参数(推荐)
步骤1:参数文件配置
将普通环境变量数组与Key Vault引用参数分开定义,Key Vault引用仅支持顶层参数:
{ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "someStringParam": { "value": "stringLiteralValueHere" }, "backEndwebAppName": { "value": "your-webapp-name" }, "appInsightsName": { "value": "your-appinsights-name" }, "backEndEnvVariables": { "value": [ { "name": "envVarKeyName", "value": "stringLiteralValueHere" } ] }, "secret1FromKeyvault": { "reference": { "keyVault": { "id": "/subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.KeyVault/vaults/<vault_name>" }, "secretName": "secret1" } } } }
步骤2:ARM模板配置
修正copy函数的name为properties,直接向应用设置的属性对象添加批量键值对,同时单独配置Key Vault密钥和App Insights参数:
{ "type": "Microsoft.Web/sites/config", "apiVersion": "2022-03-01", "name": "[concat(parameters('backEndwebAppName'), '/appsettings')]", "properties": { "APPINSIGHTS_INSTRUMENTATIONKEY": "[reference(concat('microsoft.insights/components/', parameters('appInsightsName')), '2020-02-02').InstrumentationKey]", "KVsecret1": "[parameters('secret1FromKeyvault')]" }, "copy": [ { "name": "properties", "count": "[length(parameters('backEndEnvVariables'))]", "input": { "[parameters('backEndEnvVariables')[copyIndex()].name]": "[parameters('backEndEnvVariables')[copyIndex()].value]" } } ], "dependsOn": [ "[resourceId('Microsoft.Web/sites', parameters('backEndwebAppName'))]" ] }
方案2:数组中混合普通值与Key Vault引用(进阶)
如果需要在同一个参数数组中混合普通环境变量和Key Vault密钥,可通过模板函数判断处理:
步骤1:参数文件配置
数组元素新增secretReference字段标识Key Vault引用:
"backEndEnvVariables": { "value": [ { "name": "envVarKeyName", "value": "stringLiteralValueHere" }, { "name": "KVsecret1", "secretReference": { "keyVaultId": "/subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.KeyVault/vaults/<vault_name>", "secretName": "secret1" } } ] }
步骤2:ARM模板配置
用if和contains函数判断元素类型,动态获取值或密钥:
{ "type": "Microsoft.Web/sites/config", "apiVersion": "2022-03-01", "name": "[concat(parameters('backEndwebAppName'), '/appsettings')]", "properties": { "APPINSIGHTS_INSTRUMENTATIONKEY": "[reference(concat('microsoft.insights/components/', parameters('appInsightsName')), '2020-02-02').InstrumentationKey]" }, "copy": [ { "name": "properties", "count": "[length(parameters('backEndEnvVariables'))]", "input": { "[parameters('backEndEnvVariables')[copyIndex()].name]": "[if(contains(parameters('backEndEnvVariables')[copyIndex()], 'secretReference'), reference(resourceId('Microsoft.KeyVault/vaults/secrets', split(parameters('backEndEnvVariables')[copyIndex()].secretReference.keyVaultId, '/')[4], split(parameters('backEndEnvVariables')[copyIndex()].secretReference.keyVaultId, '/')[8], parameters('backEndEnvVariables')[copyIndex()].secretReference.secretName), parameters('backEndEnvVariables')[copyIndex()].value)]" } } ], "dependsOn": [ "[resourceId('Microsoft.Web/sites', parameters('backEndwebAppName'))]" ] }
关键前置条件
- Key Vault需启用模板部署访问:在Key Vault的访问策略中勾选"允许通过Azure Resource Manager进行模板部署"
- 执行部署的主体(用户/服务主体)需拥有Key Vault的
secrets/get权限
内容的提问来源于stack exchange,提问作者Andrew Wiebe
相关产品推荐
相关产品推荐

