Deconstructing JSON: Super Secrets

“Psst… Hey buddy, want to keep your plain text password in your source control?”

Hopefully, you answer is “No”, but if you’d been following along with this JSON/ARM template series of posts, you will have noticed that I’ve defaulted to deployments with straight up, plain text, username/passwords in my template examples. So before we go any further, lets secure this up a bit!

Goal: Deploy a Windows Nano VM using an ARM template in GitHub without having to put the Admin username or password anywhere in plain text.

To do this, we’ll need a place to hide the secrets. In this case, we’ll use Azure Key Vault. With Key Vault, you create a resource group and vault (using PowerShell or an ARM template) and then load up some secrets or keys. You can hide basic passwords or load certificates.

I’m going to create my Key Vault using PowerShell. I’m purposely creating my vault in its own Resource Group. You can create the Key Vault in the same Resource Group as the rest of your deployment, but then if you delete the whole group for during testing, you’ll have to recreate the vault each time.

  1. Log into Azure
  2. Get your Subscription details, copy the GUID of the subscription you want to use for the key vault into the $VSSubID variable.
  3. Customize the variables for the Resource Group name, Vault name and deployment region.
  4. Once the vault is created, customize the “SuperSecretPassword” and “FancyAdminName” to your liking and add those secrets to the vault.
 Login-AzureRmAccount
Get-AzureRmSubscription
$VSSubID = {subcription_guid}  
Set-AzureRmContext -SubscriptionID $VSSubID

$RGName = "KeyVaultRG"
$VaultName = "MyVaultName"
$Location = "West US"

New-AzureRmResourceGroup -Name $RGName -Location $Location

New-AzureRmKeyVault -VaultName $VaultName -ResourceGroupName $RGName -Location $Location

Set-AzureRmKeyVaultAccessPolicy -VaultName $VaultName -EnabledForTemplateDeployment -ResourceGroupName $RGName

$secretvalue = ConvertTo-SecureString 'SuperSecretPassword' -AsPlainText -Force
$secret = Set-AzureKeyVaultSecret -VaultName $VaultName -Name 'ServerAdminPassword' -SecretValue $secretvalue

$secretvalue = ConvertTo-SecureString 'FancyAdminName' -AsPlainText -Force
$secret = Set-AzureKeyVaultSecret -VaultName $VaultName -Name 'ServerAdminName' -SecretValue $secretvalue

Now that my vault is crated, I’ll need to edit my ARM template to grab the secrets from the Key Vault when my VM is deployed. Make the change to your parameters.json file, not your deployment template. This way you can use the same template deployment with different subscriptions and vaults easily. Instead of using the basic string type for your adminUsername and adminPassword, reference the secrets you added to the vault.

 "adminUsername": {
      "reference": {
      "keyVault": {
        "id": "/subscriptions/{guid}/resourceGroups/KeyVaultRG/providers/Microsoft.KeyVault/vaults/ImperfectKeyVault"
      }, 
      "secretName": "ServerAdminName" 
       } 
    },
   "adminPassword": {
      "reference": {
      "keyVault": {
        "id": "/subscriptions/{guid}/resourceGroups/KeyVaultRG/providers/Microsoft.KeyVault/vaults/ImperfectKeyVault"
      }, 
      "secretName": "ServerAdminPassword" 
       } 
    }

Now, when you run your deployment, the admin username and password will be pulled from the vault and passed to your VM during creation. If you go to log in that server directly, you’ll need to provide the plain text versions of those secrets just like usual.  It’s worth noting that not anyone can pull keys out of your vault.  By default only the subscription admin will be able to access the contents of the vault, but you can add additional permissions to a vault to allow for other users and automation tools to access the same secrets.

You can find the example of this template in my GitHub repo.

Learn more about Azure Key Vault at https://azure.microsoft.com/en-us/documentation/articles/key-vault-get-started/