Securing application secrets with Azure Key Vault deployed using Terraform

Abhimanyubajaj
4 min readOct 29, 2023

--

Azure Key Vault is a cloud service for securely storing and accessing secrets. Vaults support storing software and HSM-backed keys, secrets, and certificates. To do any operations with Key Vault, you first need to authenticate to it. There are three ways to authenticate to Key Vault:

  • Service principal and certificate: You can use a service principal and an associated certificate that has access to Key Vault.
  • Managed identities for Azure resources: When you deploy an app on a virtual machine in Azure, you can assign an identity to your virtual machine that has access to Key Vault.
  • Service principal and secret: You can use a service principal and an associated secret that has access to Key Vault.

In this article we will be deploying an Azure VM and configure Azure managed identity. So, let’s get started.

Github link for source code

https://github.com/Abhimanyu9988/azure-key-vault-with-vm.git

Setting up the the terraform

This Terraform configuration is designed to set up the necessary Azure resources for securing secrets in Azure Key Vault. The configuration includes:

  1. Resource Group: It creates an Azure resource group to organize and manage related resources.
  2. Virtual Network and Subnet: It defines a virtual network and subnet for network segmentation and isolation.
  3. Public IP Address: An Azure Public IP address is allocated dynamically for the virtual machine.
  4. Network Interface: It creates a network interface with dynamic private IP allocation and associates it with the public IP address.
  5. Linux Virtual Machine: This resource provisions an Azure virtual machine running Ubuntu. It specifies the size, admin username, and password for the VM. The VM is configured to use a standard OS disk.
  6. Azure Key Vault: It provisions an Azure Key Vault instance with specific configurations, including enabling disk encryption, setting access policies, and defining SKU settings.
  7. Key Vault Secret: A secret named “secret-for-azure-kv” is added to the Azure Key Vault.
  8. Outputs: The configuration defines various outputs, including the VM name, resource group name, key vault name, public IP address, admin username, admin password, VM name, and key vault secret name.

Clone this repository to your local machine. Modify the variables in variables.tf to customize your deployment.

Run the following commands to deploy Azure resources:

terraform init
terraform apply — auto-approve

Once you are done with it. You would have Virtual machine and an Azure Key Vault ready on Azure portal. We would now assign an identity to the VM. We have the script after-terraform-cmd.sh to do that for us automatically. The script content

#az vm identity assign --name "Azure-key-vault-vm" --resource-group "key-vault-rg"
#echo "Assign permissions to the VM identity"
#echo "Edit the systemAssignedIdentity value in the snippet below"
#az keyvault set-policy --name "keyvaultvmwithterraform" --object-id "<systemAssignedIdentity>" --secret-permissions get list


#!/bin/bash

# Retrieve VM name and resource group name from Terraform outputs
VM_NAME=$(terraform output -raw azurerm_linux_virtual_machine_name | sed 's/"//g' | awk '{$1=$1};1')
RESOURCE_GROUP=$(terraform output -raw resource_group_name | sed 's/"//g' | awk '{$1=$1};1')

# Assign managed identity to the VM
IDENTITY_RESULT=$(az vm identity assign --name "$VM_NAME" --resource-group "$RESOURCE_GROUP")

# Extract the systemAssignedIdentity from the output
SYSTEM_ASSIGNED_IDENTITY=$(echo "$IDENTITY_RESULT" | jq -r '.systemAssignedIdentity')

# Retrieve Key Vault name from Terraform output
KEY_VAULT_NAME=$(terraform output key_vault_name | sed 's/"//g' | awk '{$1=$1};1')

# Set Key Vault policy for the systemAssignedIdentity
az keyvault set-policy --name "$KEY_VAULT_NAME" --object-id "$SYSTEM_ASSIGNED_IDENTITY" --secret-permissions get list

# ssh inside the vm
UserName=$(terraform output -raw admin_username | sed 's/"//g' | awk '{$1=$1};1')
PublicIP=$(terraform output -raw public_ip_address | sed 's/"//g' | awk '{$1=$1};1')
ssh $UserName@$PublicIP

az vm identity assign — name “$VM_NAME” — resource-group “$RESOURCE_GROUP” creates a system-assigned identity for the virtual machine by using the Azure CLI

az keyvault set-policy — name “$KEY_VAULT_NAME” — object-id “$SYSTEM_ASSIGNED_IDENTITY” — secret-permissions get list
assigns permissions to the VM identity

Once this is done, We need to ssh inside the VM, Create a Python script and get secretValue. Our python code looks like

from azure.keyvault.secrets import SecretClient
from azure.identity import DefaultAzureCredential

key_vault_name = "<Your Key Vault Name>"
key_vault_uri = f"https://<Your Key Vault Name>.vault.azure.net"
secret_name = "<Your Secret Name>"

credential = DefaultAzureCredential()
client = SecretClient(vault_url=key_vault_uri, credential=credential)
retrieved_secret = client.get_secret(secret_name)

print(f"The value of secret '{secret_name}' in '{key_vault_name}' is: '{retrieved_secret.value}'")

We install all the dependancies and execute the fetch_secret.py

adminuser@Azure-key-vault-vm:~$ python3 fetch_secret.py
The value of secret ‘secret-for-azure-kv’ in ‘keyvaultvmwithterraform’ is: ‘kvvaultsecretvalue’

Viola!! Everything is looking good and you are all set!!

For more information or in case you get stuck, Feel free to connect with me on LinkedIn

https://www.linkedin.com/in/theabhibajaj/

--

--

Abhimanyubajaj

I solve problems. CKAD, CKA, Azure, AWS, GCP, Terraform Certified. Senior Software Engineer at Cisco.