How to use an SSH key stored in Azure Key Vault while building Azure Linux VMs using Terraform

So I want to use the same SSH Public key to be able to authenticate across multiple Linux VMs that I’m building in Azure in Terraform. While I did find a lot of examples (including among Terraform example repo) of how to do it if you have the key stored on your local machine I couldn’t find (or didn’t search long enough) how to use an SSH key stored in Azure Key Vault while building Azure Linux VMs using Terraform.

So to reiterate what I have and what I want.

I have:

  • a private key stored on my machine (that will be used in the future)
  • a corresponding public key dev-mgmt-ssh-key stored in an existing Azure Key Vault kv-dev-mgmt (which I don’t want to be managed by Terraform, but only used by it)

I want:

  • Terraform to read the public key that is stored in the Azure Key Vault
  • Terraform to use that key while provisioning new VM(s)

Using Terraform to read a key that is stored in Azure Key Vault

We will be using the data functions to read an existing key,

# Get existing Key Vault
data "azurerm_key_vault" "kv" {
  name                = "kv-dev-mgmt"
  resource_group_name = "rg-master"
}

# Get existing Key
data "azurerm_key_vault_key" "ssh_key" {
  name         = "dev-mgmt-ssh-key"
  key_vault_id = data.azurerm_key_vault.kv.id
}

Step 1: we used azurerm_key_vault to access an Azure Key Vault resource by specifying the Resource Group and Key Vault names

Step 2: we used azurerm_key_vault_key to access our key by providing a Key Vault Id and the Key name

Now we have the key stored in ssh_key for future reference.

Providing an ssh public key to Azure Linux VM in Terraform

# Create a VM
resource "azurerm_linux_virtual_machine" "main" {
  name                            = .....
  resource_group_name             = .....
  location                        = .....
  size                            = .....
  admin_username                  = "adminuser"
  admin_ssh_key {
    username = "adminuser"
    public_key = data.azurerm_key_vault_key.ssh_key.public_key_openssh
  }
  disable_password_authentication = true

Note: I have reducted all the configuration lines that are irrelevant to the SSH section (like image type, networking, disk, etc.)

We are passing the public_key_openssh attribute of our ssh_key data source to the public_key property of the admin_ssh_key.

We also disable password authentication by setting the disable_password_authentication to true.

Error: decoding … for public key data

As a bonus, I initially tried to use the public_key_pem attribute of the ssh_key key data source, but that, while being able to pass Terraform validate step didn’t work when running apply and was failing with ‘Error: decoding “admin_ssh_key.0.public_key” for public key data” message.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.