Skip to content

Terraform Track

The Terraform track delivers a functionally equivalent variant of the SMB Ready Foundation alongside the canonical Bicep track. Partners already standardized on Terraform can adopt the foundation without adding Bicep to their toolchain.

AspectBicepTerraform
Deployment scopesTwo templates: deploy-mg.bicep (MG) + main.bicep (sub)Single root composes both scopes
OrchestrationPre-provision hook runs MG template, then azd provisionSingle azd provisionterraform apply
Module systemmodules/*.bicep17 child modules under modules/
AVM postureAVM-first (13 modules)Raw azurerm_* / azapi_resource
ManagedBy tag"Bicep""Terraform"
State managementARM deployments (stateless)Remote state in Azure Storage
ComponentPinRationale
terraform>= 1.9Required for import block + mock_provider
azurerm~> 4.04.x LTS-equivalent; allows minor upgrades
azapi~> 2.0Needed for Azure Migrate (no azurerm support)
infra/terraform/smb-ready-foundation/
├── azure.yaml # azd manifest (provider: terraform)
├── backend.tf # backend "azurerm" {} partial config
├── versions.tf, providers.tf
├── variables.tf, locals.tf
├── main.tf # 17 module calls + root import block
├── outputs.tf
├── modules/
│ ├── management-group/ # MG + subscription association
│ ├── policy-assignments-mg/ # 33 MG-scoped policy assignments
│ ├── resource-groups/ # 6 resource groups
│ ├── network-hub/ # Hub VNet, NSG, 4 subnets, PDZ
│ ├── network-spoke/ # Spoke VNet, NSG, optional NAT
│ ├── firewall/ # Azure Firewall Basic (conditional)
│ ├── route-tables/ # Spoke + gateway UDRs
│ ├── vpn-gateway/ # VPN Gateway VpnGw1AZ (conditional)
│ ├── peering/ # Hub↔spoke peering
│ ├── monitoring/ # Log Analytics Workspace
│ ├── backup/ # RSV + DefaultVMPolicy
│ ├── policy-backup-auto/ # Sub-scope DINE + role assignments
│ ├── migrate/ # Azure Migrate (azapi_resource)
│ ├── keyvault/ # Key Vault + PE + diag settings
│ ├── automation/ # Automation Account + LAW link
│ ├── budget/ # Consumption budget
│ └── defender/ # Defender for Cloud Free
├── hooks/ # pre/post-provision (bash + PowerShell)
├── scripts/ # bootstrap-tf-backend + remove
└── tests/
└── scenarios.tftest.hcl # 6 plan-mode scenario tests
azd provision
├─ hooks/pre-provision.{sh,ps1}
│ 1. Validate OWNER, CIDRs (hub/spoke/on-prem overlap)
│ 2. Azure preflight (auth, required RP registration)
│ 3. Bootstrap TF backend (RG + storage + container)
│ 4. Write terraform.auto.tfvars.json
│ 5. Clean stale budget / faulted resources
│ 6. terraform init -reconfigure
├─ terraform apply
│ - MG + subscription association (with import block)
│ - 33 MG-scoped + 1 sub-scoped policy assignments (34 total)
│ - 6 resource groups, budget, Defender pricings
│ - Hub/spoke VNets, NSGs, subnets, PDZ
│ - Conditional: NAT gateway OR firewall + route tables
│ - Conditional: VPN gateway (serialized after firewall)
│ - Conditional: hub-spoke peering
│ - LAW, RSV, policy-backup-auto, Migrate, KV, Automation
└─ hooks/post-provision.{sh,ps1}
- Terraform outputs summary + next steps

The Terraform track includes plan-mode tests covering all scenarios:

Terminal window
cd infra/terraform/smb-ready-foundation
terraform test

Six test runs validate: baseline, firewall, vpn, full, default values, and edge cases. Tests use mock_provider + override_resource — no Azure credentials required.

Terminal window
terraform fmt -check -recursive
terraform init -backend=false && terraform validate
npm run validate:terraform
npm run validate:iac-security-baseline