Azure Resource Manager Templates - Securing your Parameters with KeyVault

Storing secret information such as parameters in resource template files is not recommended. Often ARM templates are checked into source control. Now everyone has access to your confidential information.

Using parameters that are not checked into source control is one option. Azure offers a better option through its secure data store, KeyVault. Think of it as a vault for secrets of any type.

Deploying a KeyVault

First, you need to deploy a KeyVault. You can achieve this using the following resource template:

{
	"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
	"contentVersion": "1.0.0.0",
	"parameters": {
		"userObjectId": {
			"type": "string"
		}
	},
	"resources": [
		{
			"type": "Microsoft.KeyVault/vaults",
			"apiVersion": "2015-06-01",
			"name": "demokeyvault1",
			"location": "[resourceGroup().location]",
			"properties": {
				"enabledForTemplateDeployment": true,
				"tenantId": "[subscription().tenantId]",
				"accessPolicies": [
					{
						"tenantId": "[subscription().tenantId]",
						"objectId": "[parameters('userObjectId')]",
						"permissions": {
							"keys": ["All"],
							"secrets": ["All"]
						}
					}
				]
			},
			"sku": {
				"name": "Standard",
				"family": "A"
			}
		}
	]
}

Let’s have a look at the required properties. To use this vault for deploying templates, set enabledForTemplateDeployment to true. You also need to specify the tenantId for the subscription you are deploying to. This is easiest retrieved using the PowerShell cmdlet Get-AzureRmSubscription.

Then you specify who gets access to the keys in the accessPolicies property. In the simple case where you are the subscription admin, you specify your own objectId. To list the users with their objectIds, use the PowerShell cmdlet Get-AzureRmADuser. The tenantId in this case would be the same as above. To manage all aspects of the vault, set the permissions to “All” for both keys and secrets. In a later post, we will look at a more secure approach for a larger organization.

Finally, you provide the SKU (Standard or Premium) you want to use. The Premium version lets you add keys protected by hardware security modules (HSM).

Adding a Password to KeyVault

Next, you can add secrets to the store by deploying the following resource template:

{
	"apiVersion": "2015-06-01",
	"location": "[resourceGroup().location]",
	"type": "Microsoft.KeyVault/vaults/secrets",
	"name": "keyToYourSecret",
	"properties": {
		"value": "theActualSecret"
	},
	"dependsOn": ["[concat('Microsoft.KeyVault/vaults/demokeyvault1')]"]
}

Note that you need to use the dependsOn property again to ensure this resource is deployed after the vault.

Using Values from KeyVault in Parameters

To use values from a KeyVault, you must use a parameters file. Here, you specify the vault’s address and the secretName as follows (this snippet shows the complete parameters file):

{
	"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
	"contentVersion": "1.0.0.0",
	"parameters": {
		"secretValue": {
			"reference": {
				"keyVault": {
					"id": "/subscriptions/<subscription-id>/resourceGroups/<resource-group-id>/providers/Microsoft.KeyVault/vaults/demokeyvault1"
				},
				"secretName": "keyToYourSecret"
			}
		}
	}
}

Unfortunately, because you cannot use expressions in parameter files, you must specify the full ID of your vault. It consists of your subscription ID, resource group, and vault name. You will usually only address one specific vault for each environment, so this constraint is not as bad as it looks at first. However, we hope for a better solution from Microsoft in the future regarding the use of expressions in parameter files.