Azure Import Infrastructure as Code
Convert one Azure discovery scope into reviewed Terraform with zero unintended destruction or updates.
When to invoke
- Import an Azure resource group or selected ARM resources into Terraform.
- Reverse-engineer deployed Azure infrastructure.
- Map Azure dependencies before IaC adoption.
- Diagnose drift after an attempted import.
Prerequisites and context
- Azure CLI and Terraform CLI are installed and authenticated for read-only discovery.
- Registry and Azure Verified Modules sources are reachable.
- A reviewed Terraform backend and ownership boundary are known before state mutation.
Inputs
Parse $ARGUMENTS as exactly one discovery scope; reject missing or ambiguous combinations.
| Scope |
Discovery command shape |
subscription-id |
az resource list --subscription <id> -o json |
resource-group-name |
az resource list --resource-group <name> -o json |
resource-id |
az resource show --ids <id-1> <id-2> -o json |
ARM IDs are cloud identifiers, never local file paths. Do not pass them to file-reading tools.
Procedure
- Confirm one scope, subscription context, target Terraform root, state owner, and approval boundary.
- Discover resources with the narrowest read-only Azure command and preserve sanitized evidence.
- Map parent/child relations, network and identity dependencies, cross-resource references, and creation order.
- Select an Azure Verified Module for each resource type and read its README, required inputs,
child-resource ownership, outputs, providers, and pinned version.
- If no suitable AVM exists, stop and document the gap; do not silently invent a raw-resource design.
- Generate providers, modules, variables, outputs, and examples with live non-default properties explicit.
- Run
terraform init, then derive import addresses from .terraform/modules/<key>/main*.tf;
never guess nested module, count, or for_each addresses.
- After explicit state-mutation approval, import one resource at a time and verify identity.
- Run format, validate, and plan. The accepted plan has zero destroys and zero unwanted updates.
Criteria
| Area |
Required evidence |
| Scope |
Exactly one subscription, resource group, or resource-ID set |
| Module |
Pinned AVM source and reviewed Required Inputs |
| Address |
Derived from downloaded module source after init |
| Drift |
Live non-default values represented explicitly |
| Final plan |
Zero destroys and zero unintended updates |
Output template
## Azure import result
**Status:** READY | IMPORTED | BLOCKED
**Scope:** <subscription/resource group/resource IDs>
**Terraform root:** <path>
| Resource | AVM module/version | Import address | Import | Plan result |
| --- | --- | --- | --- | --- |
### Drift and gaps
- <unmodeled property, unsupported resource, unwanted action, or none>
### Validation
- `terraform fmt`: <result>
- `terraform validate`: <result>
- `terraform plan`: <0 destroys/updates or blocker>
Limits
- Do not read ARM IDs as files or expose sensitive resource payloads.
- Do not import before backend, state ownership, address, and mutation approval are explicit.
- Do not guess AVM child resources or import addresses.
- Do not accept a plan with destruction or unexplained updates.
Related primitives
| Name |
Type |
Use it when |
azure-cli |
skill |
Read-only Azure discovery commands are required. |
terraform-cli |
skill |
Init, import, state inspection, validation, or plan procedure is required. |
azure-infrastructure |
skill |
The imported topology needs an architecture decision. |
open-horizons-security-reviewer |
agent |
Identity, network, or sensitive-data findings need review. |
Quality gate
References
1---2name: azure-import-infrastructure-as-code-23description: Imports existing Azure resources into Terraform through read-only discovery, dependency mapping, Azure Verified Module selection, source-derived import addresses, and drift-safe plans. Use when reverse-engineering a subscription, resource group, or ARM resource ID into maintainable IaC.4---56# Azure Import Infrastructure as Code78Convert one Azure discovery scope into reviewed Terraform with zero unintended destruction or updates.910## When to invoke1112- Import an Azure resource group or selected ARM resources into Terraform.13- Reverse-engineer deployed Azure infrastructure.14- Map Azure dependencies before IaC adoption.15- Diagnose drift after an attempted import.1617## Prerequisites and context1819- Azure CLI and Terraform CLI are installed and authenticated for read-only discovery.20- Registry and Azure Verified Modules sources are reachable.21- A reviewed Terraform backend and ownership boundary are known before state mutation.2223## Inputs2425Parse `$ARGUMENTS` as exactly one discovery scope; reject missing or ambiguous combinations.2627| Scope | Discovery command shape |28| --- | --- |29| `subscription-id` | `az resource list --subscription <id> -o json` |30| `resource-group-name` | `az resource list --resource-group <name> -o json` |31| `resource-id` | `az resource show --ids <id-1> <id-2> -o json` |3233ARM IDs are cloud identifiers, never local file paths. Do not pass them to file-reading tools.3435## Procedure36371. Confirm one scope, subscription context, target Terraform root, state owner, and approval boundary.382. Discover resources with the narrowest read-only Azure command and preserve sanitized evidence.393. Map parent/child relations, network and identity dependencies, cross-resource references, and creation order.404. Select an Azure Verified Module for each resource type and read its README, required inputs,41 child-resource ownership, outputs, providers, and pinned version.425. If no suitable AVM exists, stop and document the gap; do not silently invent a raw-resource design.436. Generate providers, modules, variables, outputs, and examples with live non-default properties explicit.447. Run `terraform init`, then derive import addresses from `.terraform/modules/<key>/main*.tf`;45 never guess nested module, `count`, or `for_each` addresses.468. After explicit state-mutation approval, import one resource at a time and verify identity.479. Run format, validate, and plan. The accepted plan has zero destroys and zero unwanted updates.4849## Criteria5051| Area | Required evidence |52| --- | --- |53| Scope | Exactly one subscription, resource group, or resource-ID set |54| Module | Pinned AVM source and reviewed Required Inputs |55| Address | Derived from downloaded module source after init |56| Drift | Live non-default values represented explicitly |57| Final plan | Zero destroys and zero unintended updates |5859## Output template6061```markdown62## Azure import result6364**Status:** READY | IMPORTED | BLOCKED65**Scope:** <subscription/resource group/resource IDs>66**Terraform root:** <path>6768| Resource | AVM module/version | Import address | Import | Plan result |69| --- | --- | --- | --- | --- |7071### Drift and gaps72- <unmodeled property, unsupported resource, unwanted action, or none>7374### Validation75- `terraform fmt`: <result>76- `terraform validate`: <result>77- `terraform plan`: <0 destroys/updates or blocker>78```7980## Limits8182- Do not read ARM IDs as files or expose sensitive resource payloads.83- Do not import before backend, state ownership, address, and mutation approval are explicit.84- Do not guess AVM child resources or import addresses.85- Do not accept a plan with destruction or unexplained updates.8687## Related primitives8889| Name | Type | Use it when |90| --- | --- | --- |91| `azure-cli` | `skill` | Read-only Azure discovery commands are required. |92| `terraform-cli` | `skill` | Init, import, state inspection, validation, or plan procedure is required. |93| `azure-infrastructure` | `skill` | The imported topology needs an architecture decision. |94| `open-horizons-security-reviewer` | `agent` | Identity, network, or sensitive-data findings need review. |9596## Quality gate9798- [ ] Exactly one discovery scope is used.99- [ ] Dependencies and live non-default properties are mapped.100- [ ] AVM modules and versions are explicit or a gap blocks progress.101- [ ] Import addresses come from downloaded module source.102- [ ] State mutation had explicit approval.103- [ ] Final plan has zero destroys and zero unintended updates.104105## References106107- [Azure Verified Modules Terraform index](https://azure.github.io/Azure-Verified-Modules/indexes/terraform/)108- [Terraform import language](https://developer.hashicorp.com/terraform/language/import)