aztfexport

v2026.09.24

Use when exporting existing Azure resources to Terraform using aztfexport. Triggers on aztfexport, Azure import to Terraform, export Azure resource, bring Azure under Terraform management, reverse-engineer Azure infrastructure, bootstrap IaC from live Azure resources. Covers resource, resource-group, and query modes.

GitHub
Install command
npx skhub add julianobarbosa/aztfexport
Markdown
SKILL.md

aztfexport — Export Azure Resources to Terraform

Overview

aztfexport is a Microsoft tool that exports existing Azure resources into Terraform HCL + state. It reverse-engineers live Azure infrastructure into Terraform configurations. Use this for Azure-only workflows or Terraform versions before 1.14's native terraform query.

When to Use

  • Export a single Azure resource to Terraform → aztfexport resource
  • Export an entire resource group → aztfexport resource-group
  • Export resources matching an Azure Resource Graph query → aztfexport query
  • Bootstrapping IaC from existing Azure infrastructure

Use terraform-search-import skill instead when: Terraform >= 1.14 with terraform query + bulk import (multi-cloud, not Azure-specific).

Prerequisites

  1. aztfexport installed: brew install aztfexport (macOS) or see GitHub releases
  2. Azure CLI authenticated: az login + correct subscription selected
  3. Architecture check (critical on macOS):
    file $(which aztfexport)  # Check binary arch
    uname -m                  # Check system arch
    
    If mismatch (e.g., x86_64 binary on arm64 Mac), reinstall the correct architecture version.

Workflow

Step 1: Discover the Resource ID

Use Azure CLI to find the resource ID. See references/RESOURCE-DISCOVERY.md for patterns by resource type.

Generic fallback:

az resource list --query "[?name=='RESOURCE_NAME']" -o table

Step 2: Validate aztfexport Binary

file $(which aztfexport)
uname -m
aztfexport --version

Architecture mismatch causes cryptic failures. Always verify before first use on a new machine.

Step 3: Run aztfexport

Single resource:

aztfexport resource \
  --non-interactive \
  --plain-ui \
  -o ./terraform-export \
  "/subscriptions/SUB_ID/resourceGroups/RG/providers/TYPE/NAME"

Resource group:

aztfexport resource-group \
  --non-interactive \
  --plain-ui \
  -o ./terraform-export \
  RESOURCE_GROUP_NAME

Azure Resource Graph query:

aztfexport query \
  --non-interactive \
  --plain-ui \
  -o ./terraform-export \
  "resources | where name == 'MY_RESOURCE'"

Step 4: Review Generated Files

ls ./terraform-export/
# Expect: main.tf, provider.tf, terraform.tfstate, import.tf (sometimes)
  • main.tf — generated HCL with res-0 style resource names
  • provider.tf — AzureRM provider configuration
  • terraform.tfstate — imported state file
  • Consider renaming res-0 to descriptive names (update both HCL and state)

Step 5: Verify

cd ./terraform-export
terraform init
terraform plan

A clean plan (no changes) confirms successful export. Minor diffs may appear for computed attributes — review and suppress with lifecycle { ignore_changes } if appropriate.

Critical Flags

FlagPurposeWhen Required
--non-interactiveSkip interactive promptsAlways in CI/headless/Claude
--plain-uiDisable TUI (terminal UI)Always pair with --non-interactive — without it, fails when no /dev/tty
-o <dir>Output directoryAlways (must be empty or non-existent)
--appendAppend to existing Terraform dirWhen adding to existing config (but see gotcha below)
--overwriteOverwrite existing filesWhen re-exporting to same directory
--hcl-onlyGenerate HCL without importing stateWhen you only need the code

Gotchas & Troubleshooting

ProblemCauseSolution
Binary crashes silently or exec format errorArchitecture mismatch (x86 on ARM Mac)Run file $(which aztfexport) + uname -m, reinstall correct arch
--non-interactive alone failsNo /dev/tty in headless environmentsAlways pair with --plain-ui
"directory is not empty" errorOutput dir has filesUse -o <fresh-dir> or --overwrite
--append fails on non-empty dir without stateaztfexport expects existing Terraform stateUse -o to a fresh subdirectory instead
Can't find Azure resource IDResource type unknown or wrong APITry multiple az commands — see RESOURCE-DISCOVERY.md
res-0 style names in outputDefault aztfexport namingRename post-export in both HCL and state
terraform plan shows diffs after exportComputed/server-side attributesReview diffs — use ignore_changes for benign ones

Example: Export an Activity Log Alert

# Step 1: Find the resource ID
az monitor activity-log alert list -g myResourceGroup \
  --query "[?name=='my-alert'].id" -o tsv

# Step 2: Export
aztfexport resource \
  --non-interactive \
  --plain-ui \
  -o ./alert-export \
  "/subscriptions/xxxx/resourceGroups/myRG/providers/Microsoft.Insights/activityLogAlerts/my-alert"

# Step 3: Verify
cd ./alert-export
terraform init
terraform plan

Gotchas

  • Architecture mismatch between the aztfexport binary and the AzureRM provider's CGO bindings — Apple Silicon needs ARM64 build, x86 binary on M-series silently degrades.
  • Resource-name regex defaults exclude special chars — resources with . in the name (FQDNs, etc.) are skipped silently.
  • Generated import blocks (Terraform 1.5+) vs state import commands — aztfexport now writes blocks; older workflows expecting state-import calls break.
  • --include-role-assignment is OFF by default — RBAC is left out of state, which is usually exactly what you don't want.
  • Provider version pinning: aztfexport pins to specific AzureRM versions in its imports; mismatched provider in your target stack causes spurious plan diffs.
  • Non-interactive (-n) skips name customization — auto-generated TF names like azurerm_storage_account_001 end up in your code permanently if not reviewed.
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/aztfexport

Default branch

main

Latest commit

515755d

Tree SHA

fca30ca