How to use Key Vault ARM templates and deal with sensitive parameters
At October 14, 2020 Mircosoft announced the public preview of ARM templates for adding secrets to Azure Key Vault. In this article I will explain a way how to use these templates.
Table Of Contents
The main reason why using ARM templates is the less of PowerShell modules you need. Using less modules will result in less PowerShell module updates and commands which will break. Beside that using templates will avoid editing scripts.
Key Vault overview
The Azure Key Vault is a central location where you can securely store keys, secrets and certificates. Using the Key Vault will help you to store secret information outside of script or application. By configuring an access policy you are able to configure permissions for a user, group or service principal and to monitor access and use of Key Vault items.
The templates
First I separated the Key Vault resource from the secret resource. This because the objectId parameter is mandatory. Based on the separate files I’ve created a paramater file for the Azure Key Vault resource with only the mandatory parameters.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"keyVaultName": {
"type": "string",
"metadata": {
"description": "Specifies the name of the key vault."
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Specifies the Azure location where the key vault should be created."
}
},
"enabledForDeployment": {
"type": "bool",
"defaultValue": false,
"allowedValues": [
true,
false
],
"metadata": {
"description": "Specifies whether Azure Virtual Machines are permitted to retrieve certificates stored as secrets from the key vault."
}
},
"enabledForDiskEncryption": {
"type": "bool",
"defaultValue": false,
"allowedValues": [
true,
false
],
"metadata": {
"description": "Specifies whether Azure Disk Encryption is permitted to retrieve secrets from the vault and unwrap keys."
}
},
"enabledForTemplateDeployment": {
"type": "bool",
"defaultValue": false,
"allowedValues": [
true,
false
],
"metadata": {
"description": "Specifies whether Azure Resource Manager is permitted to retrieve secrets from the key vault."
}
},
"tenantId": {
"type": "string",
"defaultValue": "[subscription().tenantId]",
"metadata": {
"description": "Specifies the Azure Active Directory tenant ID that should be used for authenticating requests to the key vault. Get it by using Get-AzSubscription cmdlet."
}
},
"objectId": {
"type": "string",
"metadata": {
"description": "Specifies the object ID of a user, service principal or security group in the Azure Active Directory tenant for the vault. The object ID must be unique for the list of access policies. Get it by using Get-AzADUser or Get-AzADServicePrincipal cmdlets."
}
},
"keysPermissions": {
"type": "array",
"defaultValue": [
"list"
],
"metadata": {
"description": "Specifies the permissions to keys in the vault. Valid values are: all, encrypt, decrypt, wrapKey, unwrapKey, sign, verify, get, list, create, update, import, delete, backup, restore, recover, and purge."
}
},
"secretsPermissions": {
"type": "array",
"defaultValue": [
"list"
],
"metadata": {
"description": "Specifies the permissions to secrets in the vault. Valid values are: all, get, list, set, delete, backup, restore, recover, and purge."
}
},
"skuName": {
"type": "string",
"defaultValue": "Standard",
"allowedValues": [
"Standard",
"Premium"
],
"metadata": {
"description": "Specifies whether the key vault is a standard vault or a premium vault."
}
}
},
"resources": [
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2019-09-01",
"name": "[parameters('keyVaultName')]",
"location": "[parameters('location')]",
"properties": {
"enabledForDeployment": "[parameters('enabledForDeployment')]",
"enabledForDiskEncryption": "[parameters('enabledForDiskEncryption')]",
"enabledForTemplateDeployment": "[parameters('enabledForTemplateDeployment')]",
"tenantId": "[parameters('tenantId')]",
"accessPolicies": [
{
"objectId": "[parameters('objectId')]",
"tenantId": "[parameters('tenantId')]",
"permissions": {
"keys": "[parameters('keysPermissions')]",
"secrets": "[parameters('secretsPermissions')]"
}
}
],
"sku": {
"name": "[parameters('skuName')]",
"family": "A"
},
"networkAcls": {
"defaultAction": "Allow",
"bypass": "AzureServices"
}
}
}
]
}
The KeyVault parameter file
The parameter file has the Key Vault name, permissions and objectId only. The objectId is an Azure AD object like a user, group or service principal. This id will get permission to the Key Vault.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"keyVaultName": {
"value": "tst-kv-tst1"
},
"objectId": {
"value": "d1a2aa35-4e4b-4b94-a9f0-137027085535"
},
"keysPermissions": {
"value": [
"list",
"read"
]
},
"secretsPermissions": {
"value": [
"list",
"read"
]
}
}
}
PowerShell command
New-AzResourceGroupDeployment -TemplateFile ./azuredeploy.json -TemplateParameterFile ./azuredeploy.parameters.json -ResourceGroupName groupname
Adding Key Vault items
After the Key Vault has been created you can fill it with items with an ARM template. I separated the resources otherwise you will be asked for an objectId every time.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"keyVaultName": {
"type": "string",
"metadata": {
"description": "Specifies the name of the key vault."
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Specifies the Azure location where the key vault should be created."
}
},
"secretName": {
"type": "string",
"metadata": {
"description": "Specifies the name of the secret that you want to create."
}
},
"secretValue": {
"type": "securestring",
"metadata": {
"description": "Specifies the value of the secret that you want to create."
}
}
},
"resources": [
{
"type": "Microsoft.KeyVault/vaults/secrets",
"apiVersion": "2019-09-01",
"name": "[concat(parameters('keyVaultName'), '/', parameters('secretName'))]",
"location": "[parameters('location')]",
"dependsOn": [
],
"properties": {
"value": "[parameters('secretValue')]"
}
}
]
}
Splatting item parameters
For security reasons I recommend using parameter objects instead of parameter files. Parameter files contains plain text and often stored at a not save location. The technique which can be used is called splatting.
A parameter object is a PowerShell hashtable which can be inserted as object.
$templateParameters = @{
keyVaultName = "keyvault-name"
secretName = "test-secret-4"
secretValue = "test-secret-4-value"
}
New-AzResourceGroupDeployment -TemplateFile ./azuredeploy.json -TemplateParameterObject $templateParameters -ResourceGroupName resoursegroup
Thank you for reading my blog how to use key vault arm templates and deal with sensitive parameters.
I hope you got a bit inspired. Enjoy your day and happy automating 👋
Related Posts
Azure Virtual Desktop Image Management Automated - Part 3 Create AVD sessionhosts on image version with ARM
This article is serie of posts about AVD Image Management Automated. In this part we are going to add new sessionhosts to an existing AVD hostpool based on a ARM template.
Read moreAzure Virtual Desktop Image Management Automated - Part 2 Save AVD image with Sysprep as Image Gallery version
This is part two of a serie posts about AVD disk management. In this blogpost I will explain how to finish a disk with sysprep and deploy it as a version into the Azure Shared Image Gallery automated.
Read moreMonitor active M365 ServiceHealth services only with PowerShell
You have some Microsoft 365 (M365) customers which you like to monitor. Every day you are looking at the customer specific M365 portal looking for Microsoft event.
Read more