The Scenario
I have a set of ARM templates that deploys an azure app service solution with Azure Key Vault and a secret value.

The main template is calling out via the linked template resource reference to the Key Vault resource template.
... snippet ...
},
"resources": [
{
"apiVersion": "2018-05-01",
"name": "linkedTemplate-keyvault",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "incremental",
"templateLink": {
"uri": "[uri(deployment().properties.templateLink.uri, 'azuredeploy-rkazurekeyvault.json')]",
"contentVersion": "1.0.0.0"
},
...
This will create the key vault resource along with a secret. The secret value will be used as a database admin password.
The main template is also calling out to an Azure SQL Server resource linked template that has a parameter for the database admin password. The same for Azure website which is my function app. To extend this technique, I can do this for other type of secrets such as API keys such as twitter API or Google Maps API keys.
The Objective
For the Azure SQL server and Azure web site linked templates to retrieve a secret value from the created Azure Key Vault resource linked template. All orchestrated in the main ARM template.

This would happen in one ARM deployment.
Note that an alternative and easier approach is to simply just pass in the password parameter value in step (1) directly to the desired linked templates, but I am demonstrating referencing the value from the Azure Key Vault template output exclusively.
Implementation Approach
To illustrate

- In the key vault linked template, the output returns the resource id the of the key vault resource to the main template.
"outputs": {
"rkkeyvault": {
"value": "[resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))]",
"type": "string"
}
}
In main template, for SQL Server, set parameter DB admin password value from the output of key vault template.
"parameters": {
"sqlserver-name": {
"value": "[parameters('sqlserver-name')]"
},
"sqldatabase-name": {
"value": "[parameters('sqldatabase-name')]"
},
"sqlAdministratorLogin": {
"value": "[parameters('sqlAdministratorLogin')]"
},
"sqlAdministratorLoginPassword": {
"reference": {
"keyVault": {
"id": "[reference('linkedTemplate-keyvault').outputs.rkkeyvault.value]"
},
"secretName": "[variables('dbpasswordsecretName')]"
}
},
For azure website/function app and SQL Server templates, to set the parameter values, you need to reference as follows
{
"apiVersion": "2018-05-01",
"name": "linkedTemplate-website",
"type": "Microsoft.Resources/deployments",
"dependsOn": ["linkedTemplate-appserviceplan", "linkedTemplate-sqlserver"],
"properties": {
"mode": "incremental",
"templateLink": {
"uri": "[uri(deployment().properties.templateLink.uri, 'azuredeploy-website.json')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"sqlAdministratorLoginPassword": {
"reference": {
"keyVault": {
"id": "[reference('linkedTemplate-keyvault').outputs.rkkeyvault.value]"
},
"secretName": "[variables('dbpasswordsecretName')]"
}
}
}
}
}
The key lines are
"sqlAdministratorLoginPassword": {
"reference": {
"keyVault": {
"id": "[reference('linkedTemplate-keyvault').outputs.rkkeyvault.value]"
},
Apply the same technique for the website/function linked template to setup the application connection string to include the DB password.
{
"apiVersion": "2018-05-01",
"name": "linkedTemplate-sqlserver",
"type": "Microsoft.Resources/deployments",
"dependsOn": ["linkedTemplate-keyvault"],
"properties": {
"mode": "incremental",
"templateLink": {
"uri": "[uri(deployment().properties.templateLink.uri, 'azuredeploy-rksqlserver.json')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"sqlserver-name": {
"value": "[parameters('sqlserver-name')]"
},
"sqldatabase-name": {
"value": "[parameters('sqldatabase-name')]"
},
"sqlAdministratorLogin": {
"value": "[parameters('sqlAdministratorLogin')]"
},
"sqlAdministratorLoginPassword": {
"reference": {
"keyVault": {
"id": "[reference('linkedTemplate-keyvault').outputs.rkkeyvault.value]"
},
"secretName": "[variables('dbpasswordsecretName')]"
}
},
"location": {
"value": "[parameters('location')]"
}
}
To see the full ARM template solution, visit https://github.com/RoyKimYYZ/azuredeploy-functionapp-sql-keyvault
Final Remarks
I hope I helped ease the learning curve in applying this technique. It’s not hard, but for me personally was very time consuming for me to get all the pieces to work together and getting the right syntax. This even when I cross reference with ARM template examples in the GitHub Azure quick start templates. From a security best practices perspective, managed identity is recommended specifically for App Service to Azure SQL Database connection. To reiterate, I just wanted to show managing and setting key vault secrete values in a linked template design. I also I hope showed a more sophisticated and real-world design and implementation that you can use for your organization and projects.
For related readings
- https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authoring-templates#outputs
- https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-tutorial-use-key-vault
- https://github.com/Azure/azure-quickstart-templates
Credits: Some Icon made by SmashIcons from www.flaticon.com