Menu Close

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

  1. Key Vault overview
  2. The templates
  3. The Key Vault parameter file
  4. Adding Key Vault items
  5. Splatting item parameters



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

The files can be found at my GitHub repository

Leave a Reply

Your email address will not be published. Required fields are marked *