Home Azure Cloud Authenticating Terraform via Managed Identity

Authenticating Terraform via Managed Identity

224
0

☁️ Introduction

Before Terraform can create resources in Azure, it needs to authenticate — to prove its identity.
Azure then checks authorization to determine what actions are allowed.

While authenticating via Azure Service Principal is ideal for automation outside Azure, Managed Identity (MI) is the most secure and simplest method when Terraform runs inside Azure — for example, from an Azure Virtual Machine (VM), Virtual Machine Scale Set (VMSS), Azure Kubernetes Service (AKS) node, Azure App Service, Azure Function, Azure Logic App (Standard), Azure Automation Account, Azure Container Instance (ACI), Azure DevOps Self-hosted Agent, Azure Cloud Shell, or Azure Arc-enabled Server — essentially, any environment that supports a Managed Identity.

In this post, we’ll:
✅ Authenticate Terraform using a Managed Identity (MI)
✅ Deploy a Virtual Network and Subnet using Terraform


🧩 Prerequisites

Azure subscription
You’ll need an active Azure subscription with permissions to create and manage resources.

A Linux (Ubuntu) VM
Terraform will run from inside this Azure VM.
You can create one by following the post How to Create an Ubuntu VM in Azure

Managed Identity assigned
The compute resource running Terraform (e.g., VM) must have a Managed Identity with Contributor or sufficient permissions on the target subscription or resource group.
You can follow the post How to Assign a Managed Identity to an Azure Virtual Machine (VM)

Terraform installed
You can follow Installing Terraform on Linux (Ubuntu) and Windows (WSL2 with Ubuntu).

Azure CLI installed (optional)
Useful for verifying Managed Identity configuration or troubleshooting authentication issues. You can follow Getting Started with Azure CLI on Linux (Ubuntu) and Windows (WSL2 with Ubuntu).

Verify Managed Identity Setup (optional)
As you’re using a System-Assigned Managed Identity, ensure it’s enabled:

az vm identity show --name myVM --resource-group myRG

If you see "principalId" in the output, the identity is active.

If not, enable it:

az vm identity assign --name myVM --resource-group myRG

For a User-Assigned Managed Identity, attach it to your VM:

az vm identity assign --name myVM --resource-group myRG --identities myUserAssignedIdentity

🧩 Step 1: Set Environment Variables

When Terraform runs inside Azure, it can automatically authenticate using the Managed Identity assigned to the resource (for example, an Azure VM, App Service, or Container Instance).
Terraform requests an access token from the Azure Instance Metadata Service (IMDS) — this means no secrets or credentials are required.

However, Terraform still needs to know which Azure Subscription to use.
The environment variables you set depend on whether you’re using a System-Assigned or User-Assigned Managed Identity.

🪪 Option 1: System-Assigned Managed Identity

For Linux/macOS/WSL:

export ARM_USE_MSI=true
export ARM_SUBSCRIPTION_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

For Windows PowerShell:

$env:ARM_USE_MSI="true"
$env:ARM_SUBSCRIPTION_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

💡 No client ID or tenant ID is required — Terraform automatically discovers them through IMDS.

🧾 Alternative Option: User-Assigned Managed Identity

If your Azure VM or compute resource has a User-Assigned Managed Identity, Terraform must know which one to use.

For Linux/macOS/WSL:

export ARM_USE_MSI=true
export ARM_CLIENT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
export ARM_SUBSCRIPTION_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

For Windows PowerShell:

$env:ARM_USE_MSI="true"
$env:ARM_CLIENT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$env:ARM_SUBSCRIPTION_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

💡 The ARM_CLIENT_ID identifies your specific User-Assigned MI, while ARM_SUBSCRIPTION_ID tells Terraform which subscription to use.


✅ Summary

  • No secrets or credentials are stored.
  • Always set ARM_USE_MSI=true.
  • Always provide ARM_SUBSCRIPTION_ID.
  • Set ARM_CLIENT_ID only for User-Assigned Managed Identity.

⚙️ Step 2: Terraform Script (main.tf)

Create a new folder (e.g., terraform-azure-msi) and inside it, create a file named main.tf.

mkdir terraform-azure-msi
cd terraform-azure-msi
nano main.tf

Note: You may use vi instead of nano if you are familiar and I use that mostly.

Paste the following Terraform configuration:

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
  }
}

provider "azurerm" {
  # use_msi = true # if not using env variable
  features {}
}

# Option 1: Create a new Resource Group
resource "azurerm_resource_group" "rg" {
  name     = "tfmsi-rg"
  location = "eastus"
}

# Create a Virtual Network
resource "azurerm_virtual_network" "vnet" {
  name                = "tfmsi-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

# Create a Subnet inside the Virtual Network
resource "azurerm_subnet" "subnet" {
  name                 = "tfmsi-subnet"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.1.0/24"]
}

💡 Note:
The key difference is the line use_msi = true in the provider block — this tells Terraform to authenticate using the Managed Identity available on the host.


⚙️ Step 3: Initialize and Apply Terraform

1️⃣ Initialize Terraform

terraform init

Downloads the Azure provider plugin and prepares Terraform for this project.
💡 You’ll see “Terraform has been successfully initialized.”

2️⃣ Review the Plan

terraform plan

Previews what Terraform will create — nothing is applied yet.
💡 You should see: Plan: 3 to add, 0 to change, 0 to destroy.

3️⃣ Apply the Configuration

terraform apply

Terraform will now use the Managed Identity for authentication and begin creating Azure resources.
When prompted, type yes.

💡 After a few moments, you’ll see:

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Step 4: Verify in Azure Portal

Go to Azure Portal → Resource Groups → tfmsi-rg
You’ll find your Virtual Network (tfmsi-vnet) and Subnet (tfmsi-subnet) created successfully.


🧹 Step 5: (Optional) Clean Up

When finished, clean up to avoid charges:

terraform destroy

When prompted, type yes.

💡 You’ll see:

Destroy complete! Resources: 2 destroyed.

🔍 Bonus: Verify Authentication

You can confirm that Terraform used the Managed Identity by checking Azure Activity Logs:

  • Go to Azure Portal → Monitor → Activity Log
  • Look under Caller — it should show the Managed Identity name instead of your personal account or Service Principal.

Summary

✅ Use Managed Identity for the most secure and seamless Terraform authentication when running within Azure.
✅ No secrets, no credentials — just native Azure identity integration.
✅ Ideal for VMs, DevOps agents, and containerized automation inside Azure.
✅ Run terraform init → plan → apply → destroy confidently with secure identity-based access.

By following this process, you ensure Terraform connects to Azure securely and automatically through a Managed Identity — a best practice for cloud-native, secret-free automation.

Previous articleHow to Assign a Managed Identity to an Azure Virtual Machine (VM)
Next articleGetting Started with Azure DevOps Organization
Heartin Kanikathottu
As a seasoned Cloud and Security Architect, I’ve led transformative initiatives in key roles, including Vice President at Morgan Stanley, Principal Architect at Societe Generale, and Tech Lead & Cloud Security Architect at VMware, among others. I’m also an internationally published author with multiple books available on platforms like Amazon and O'Reilly. Notably, one of my books was recognized as the 8th best cloud computing book of all time in 2020, reflecting the impact of my contributions to the field. With over 15 professional certifications from providers such as Microsoft (Azure), Amazon (AWS), Oracle (Java), Pivotal (Spring), and IBM, I bring a wealth of expertise to my work. Academically, I hold dual Master’s degrees in Cloud Computing and Data Analytics. I’m passionate about sharing knowledge and mentoring others, which is why I actively speak at global technical forums such as Tech Opportunities Fest at Platform Calgary, Google's Kubernetes Meetup, Java User Group, Elasticsearch Meetup, and the Agile India Conference.

LEAVE A REPLY

Please enter your comment!
Please enter your name here