How to use stored secrets from Azure Key Vault while deploying ARM VMs

Server deployments can be very challenging when it comes to delegating deployments to admins that must not know local admin credentials. Learn how to automate deployments without giving your passwords away using Azure Key Vault.

Who does not know this scenario? You want a trainee to deploy a Windows Server but you do not want to give him or her access to your secret administrator passwords at all. Or you want to delegate deployments to a service provider but you need your passwords to stay save? Azure Key Vault could be what makes your life way easier.

Azure Key Vault is a cloud service used for storing keys and secrets which are encrypted using keys from Hardware Security Modules (HSMs). It is designed so that Microsoft never sees or can extract your keys or secrets stored in Azure Key Vault.

What do we need?

First of all we need a Key Vault. You can create one using Azure Primary Portal or using PowerShell:

New-AzureRmKeyVault -VaultName "MyKeyVault" -ResourceGroupName "MyResourceGroup" -Location "NorthEurope" -EnabledForDeployment -Sku standard

There are two pricing tiers (A1 Standard and P1 Premium). Both of them differ in the fact that with P1 you get your keys HSM backed; with A1 you don’t.

Create a Key Vault
Create a Key Vault

Access policies are an interesting feature. Storing your keys and secrets encrypted and having the whole world read them won’t make sense in most scenarios. And having your secrets altered by anyone you don’t know will not make your security strategy better. So you should kiss – keep it simple, stupid.

Azure Key Vault access policies

In my demo environment I have selected two principals that have access to keys and/or secrets in my key vault. One of them, a delegated admin account that I use for automated VM deployments only has access to secrets like passwords, not to keys.

Create a secret for your local admin password

In an automated VM deployment a user account can be logged in into an Azure subscription via PowerShell using encrypted credentials. After having created your Key Vault you need to enter your passphrase as secure string and pass it to the Set-AzureKeyVaultSecret cmdlet which creates or updates a secret in your Vault:

$password = read-host -assecurestring
Set-AzureKeyVaultSecret -VaultName keyvault -Name admin -SecretValue $password

Now you’re all set up for some PowerShell automation.

Automated login to Azure Resource Manager

For automated PowerShell login to Azure Resource Manager you first have to enter your Azure admins passphrase as secure string and save it in a .txt-file.

read-host -assecurestring | convertfrom-securestring | out-file C:\temp\passphrase_encrypted.txt

That file then contains an AES-encrypted standard string that can be imported again later on. To reimport the saved encrypted passphrase and create logon credentials you can use the following PowerShell code:

$password = get-content C:\temp\passphrase_encrypted.txt | convertto-securestring
$credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist "",$password

With those credentials you can now login into your subscription:

Login-AzureRMAccount -Credential $credentials

Automated VM deployment

Now you can automate your VM deployment. For this purpose you can use the following example script:

$location = "NorthEurope"
$ResourceGroupName= "myResourceGroup"
$LocalAdminUser = "adminUserName"
$ResourceGroup = New-AzureRmResourceGroup -Name $ResourceGroupName -Location $Location
$StorageAccountName = "mystorageaccount"
$Test = Get-AzureRmStorageAccountNameAvailability $StorageAccountName
If ($Test) {
$storageAccount =New-AzureRmStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName -SkuName "Standard_LRS"-Kind "Storage"-Location $location
$mySubnet = New-AzureRmVirtualNetworkSubnetConfig -Name "mySubnet" -AddressPrefix
$myVnet = New-AzureRmVirtualNetwork -Name "myVnet" -ResourceGroupName $ResourceGroupName -Location $location -AddressPrefix -Subnet $mySubnet
$myPublicIp = New-AzureRmPublicIpAddress -Name "myPublicIp" -ResourceGroupName $ResourceGroupName -Location $location -AllocationMethod Static
$myNIC = New-AzureRmNetworkInterface -Name "myNIC" -ResourceGroupName $ResourceGroupName -Location $location -SubnetId $myVnet.Subnets[0].Id -PublicIpAddressId $myPublicIp.Id

## Now get the secret from your Azure Key Vault that you've created before and create your local admin credentials
$Secret = Get-AzureKeyVaultSecret -VaultName MyKeyVault -Name admin
$Cred = [PSCredential]::new($LocalAdminUser, $Secret.SecretValue)

$myVm = New-AzureRmVMConfig -VMName "myVM" -VMSize "Standard_A2"
$myVM = Set-AzureRmVMOperatingSystem -VM $myVM -Windows -ComputerName "myVM" -Credential $cred -ProvisionVMAgent -EnableAutoUpdate
$myVM = Set-AzureRmVMSourceImage -VM $myVM -PublisherName "MicrosoftWindowsServer" -Offer "WindowsServer" -Skus "2016-Datacenter" -Version "latest"
$myVM = Add-AzureRmVMNetworkInterface -VM $myVM -Id $myNIC.Id
$blobPath = "vhds/myOsDisk1.vhd"
$osDiskUri = $storageAccount.PrimaryEndpoints.Blob.ToString() + $blobPath
$myVM = Set-AzureRmVMOSDisk -VM $myVM -Name "myOsDisk1" -VhdUri $osDiskUri -CreateOption fromImage

New-AzureRmVM -ResourceGroupName $ResourceGroupName -Location $location -VM $myVM

The passage that’s relevant for us is

$Secret = Get-AzureKeyVaultSecret -VaultName MyKeyVault -Name admin
$Cred = [PSCredential]::new($LocalAdminUser, $Secret.SecretValue)

With that code you read the Azure KeyVault secret you created earlier and put it into credentials that are passed to the VM configuration and so will be used as admin logon credentials for your new VM. No trainee and no service provider will ever get access to the passphrase and yet they will be able to automatically deploy a new VM to Azure Resource Manager.

Now, give it a try and happy testing.

Stay tuned and bye for now,

Author: Tom Janetscheck

Cloud Security Enthusiast | Security Advocate

2 thoughts on “How to use stored secrets from Azure Key Vault while deploying ARM VMs”

Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your 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

%d bloggers like this: