How to get the Secret from an Output of an Azure Key Vault ARM Template Deployment to the Main ARM Template

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

  1. 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

Credits: Some Icon made by SmashIcons from www.flaticon.com 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s