From Portal to Code: Your First Steps Importing Azure Resources into Terraform
If you’ve ever inherited an Azure environment, you’ll know that not everything is built with Infrastructure as Code from the start. Often, resources are created manually in the portal or with scripts, and you’re left to bring some order to the chaos. If you’re moving to Terraform (which I highly recommend for Azure), you may want to bring your existing resources under code management without having to rebuild everything from scratch.
Here’s how you can approach importing Azure resources into Terraform state if you’re getting started, focusing on a Virtual Network, a Key Vault, and a Private Endpoint. This is the sort of practical task you’ll face when you want to avoid configuration drift and get your Azure set-up under control.
Why Import?
- Consistency: All your resources are defined in code, so you always know what you have.
- Change tracking: Terraform’s state file becomes your single source of truth. No more guessing who created what.
- Safer changes: You can plan and preview changes before making them, which is far less risky than manual edits.
Step 1: Write Your Terraform Resource Blocks
Before you import, you need to create a matching resource block for each Azure resource in your Terraform files. You do not need to fill in every property at this stage; just cover the basics.
Virtual Network (UK South):
resource "azurerm_virtual_network" "existing_vnet" {
name = "my-existing-vnet"
resource_group_name = "my-resource-group"
location = "UK South"
address_space = ["10.0.0.0/16"]
}
Key Vault (UK South):
resource "azurerm_key_vault" "existing_kv" {
name = "my-existing-keyvault"
resource_group_name = "my-resource-group"
location = "UK South"
sku_name = "standard"
}
Private Endpoint (UK South):
resource "azurerm_private_endpoint" "existing_pe" {
name = "my-existing-pe"
resource_group_name = "my-resource-group"
location = "UK South"
subnet_id = azurerm_subnet.existing_subnet.id
private_service_connection {
name = "example-connection"
private_connection_resource_id = azurerm_key_vault.existing_kv.id
subresource_names = ["vault"]
is_manual_connection = false
}
}
Tip: Make sure you have any referenced resources, such as subnets, defined in Terraform as well, or import them separately.
Step 2: Find the Azure Resource IDs
You will need the full Azure Resource ID for each resource. The easiest way to find these is by using the Azure Portal, Azure CLI, or PowerShell.
Azure CLI Example:
az network vnet show -g my-resource-group -n my-existing-vnet --query id -o tsv
az keyvault show -g my-resource-group -n my-existing-keyvault --query id -o tsv
az network private-endpoint show -g my-resource-group -n my-existing-pe --query id -o tsv
Step 3: Import Each Resource
With your resource blocks and IDs ready, run the import commands in your terminal:
terraform import azurerm_virtual_network.existing_vnet "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/my-resource-group/providers/Microsoft.Network/virtualNetworks/my-existing-vnet"
terraform import azurerm_key_vault.existing_kv "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/my-resource-group/providers/Microsoft.KeyVault/vaults/my-existing-keyvault"
terraform import azurerm_private_endpoint.existing_pe "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/my-resource-group/providers/Microsoft.Network/privateEndpoints/my-existing-pe"
Remember: Replace
<SUBSCRIPTION_ID>
and the resource names with your own values.
Step 4: Tidy Up and Validate
After importing, run terraform plan
. Terraform may flag missing or mismatched properties, which is perfectly normal. Update your Terraform files so that they match the actual configuration of your resources. Importing only links the state—it does not automatically fill in all the settings for you.
Continue running terraform plan
and updating your files until you reach a point where there are no changes to apply. At this stage, your resources are properly managed by Terraform.
Final Thoughts
Importing resources into Terraform state is not the most glamorous part of the job, but it is essential for bringing order to your Azure environment. It can be a bit fiddly the first time, but once you have done it, you will appreciate the control and consistency it brings.
Are you importing resources into Terraform? Have you got any tips or stories to share? Please leave a comment below. I am always interested to hear how others are managing their Azure estates.