Create a virtual machine and include certificate retrieved from a key vault

This article helps you to create a virtual machine in Azure Stack and push certificates onto it.


A key vault in Azure Stack is used to store certificates. Certificates are helpful in many different scenarios. For example, consider a scenario where you have a virtual machine in Azure Stack that is running an application that needs a certificate. This certificate can be used for encrypting, for authenticating to Active Directory, or for SSL on a website. Having the certificate in a key vault helps make sure that it's secure.

In this article, we walk you through the steps required to push a certificate onto a Windows virtual machine in Azure Stack. You can use these steps either from the Azure Stack Development Kit, or from a Windows-based external client if you are connected through VPN.

The following steps describe the process required to push a certificate onto the virtual machine:

  1. Create a Key Vault secret.
  2. Update the azuredeploy.parameters.json file.
  3. Deploy the template

Create a Key Vault secret

The following script creates a certificate in the .pfx format, creates a key vault, and stores the certificate in the key vault as a secret. You must use the -EnabledForDeployment parameter when you're creating the key vault. This parameter makes sure that the key vault can be referenced from Azure Resource Manager templates.

# Create a certificate in the .pfx format
New-SelfSignedCertificate `
  -certstorelocation cert:\LocalMachine\My `

$pwd = ConvertTo-SecureString `
  -String "<Password used to export the certificate>" `
  -Force `

Export-PfxCertificate `
  -cert "cert:\localMachine\my\<Certificate Thumbprint that was created in the previous step>" `
  -FilePath "<Fully qualified path where the exported certificate can be stored>" `
  -Password $pwd

# Create a key vault and upload the certificate into the key vault as a secret
$vaultName = "contosovault"
$resourceGroup = "contosovaultrg"
$location = "local"
$secretName = "servicecert"
$fileName = "<Fully qualified path where the exported certificate can be stored>"
$certPassword = "<Password used to export the certificate>"

$fileContentBytes = get-content $fileName `
  -Encoding Byte

$fileContentEncoded = [System.Convert]::ToBase64String($fileContentBytes)
$jsonObject = @"
"data": "$filecontentencoded",
"dataType" :"pfx",
"password": "$certPassword"
$jsonObjectBytes = [System.Text.Encoding]::UTF8.GetBytes($jsonObject)
$jsonEncoded = [System.Convert]::ToBase64String($jsonObjectBytes)

New-AzureRmResourceGroup `
  -Name $resourceGroup `
  -Location $location

New-AzureRmKeyVault `
  -VaultName $vaultName `
  -ResourceGroupName $resourceGroup `
  -Location $location `
  -sku standard `

$secret = ConvertTo-SecureString `
  -String $jsonEncoded `
  -AsPlainText -Force

Set-AzureKeyVaultSecret `
  -VaultName $vaultName `
  -Name $secretName `
   -SecretValue $secret

When you run the previous script, the output includes the secret URI. Make a note of this URI. You have to reference it in the Push certificate to Windows Resource Manager template. Download the vm-push-certificate-windows template folder onto your development computer. This folder contains the azuredeploy.json and azuredeploy.parameters.json files, which you will need in the next steps.

Modify the azuredeploy.parameters.json file according to your environment values. The parameters of special interest are the vault name, the vault resource group, and the secret URI (as generated by the previous script). The following file is an example of a parameter file:

Update the azuredeploy.parameters.json file

Update the azuredeploy.parameters.json file with the vaultName, secret URI, VmName, and other values as per your environment. The following JSON file shows an example of the template parameters file:

  "$schema": "",
  "contentVersion": "",
  "parameters": {
    "newStorageAccountName": {
      "value": "kvstorage01"
    "vmName": {
      "value": "VM1"
    "vmSize": {
      "value": "Standard_D1_v2"
    "adminUserName": {
      "value": "demouser"
    "adminPassword": {
      "value": "demouser@123"
    "vaultName": {
      "value": "contosovault"
    "vaultResourceGroup": {
      "value": "contosovaultrg"
    "secretUrlWithVersion": {
      "value": "https://testkv001.vault.local.azurestack.external/secrets/testcert002/82afeeb84f4442329ce06593502e7840"

Deploy the template

Now deploy the template by using the following PowerShell script:

# Deploy a Resource Manager template to create a VM and push the secret onto it
New-AzureRmResourceGroupDeployment `
  -Name KVDeployment `
  -ResourceGroupName $resourceGroup `
  -TemplateFile "<Fully qualified path to the azuredeploy.json file>" `
  -TemplateParameterFile "<Fully qualified path to the azuredeploy.parameters.json file>"

When the template is deployed successfully, it results in the following output:

Deployment output

When this virtual machine is deployed, Azure Stack pushes the certificate onto the virtual machine. In Windows, the certificate is added to the LocalMachine certificate location, with the certificate store that the user provided. In Linux, the certificate is placed under the /var/lib/waagent directory, with the file name <UppercaseThumbprint>.crt for the X509 certificate file and <UppercaseThumbprint>.prv for the private key.

Retire certificates

In the preceding section, we showed you how to push a new certificate onto a virtual machine. Your old certificate is still on the virtual machine, and it can't be removed. However, you can disable the older version of the secret by using the Set-AzureKeyVaultSecretAttribute cmdlet. The following is an example usage of this cmdlet. Make sure to replace the vault name, secret name, and version values according to your environment:

Set-AzureKeyVaultSecretAttribute -VaultName contosovault -Name servicecert -Version e3391a126b65414f93f6f9806743a1f7 -Enable 0

Next steps