Convert Azure resources to Terraform files
Use this as a starting point for managing Infrastructure as Code, after using it, make sure to use variables, modules, etc. Always follow best practices. Use at your own risk. Test it in lab first.
Usage: .\Convert_Az2TF.ps1 -SubscriptionID "<my_subscription_ID>"
Supported Azure resources (under development...):
*Some attributes/resources properties might not have been implemented yet. If you need additional resources attributes, feel free to contribute.
resourcegroups
microsoft.storage/storageaccounts
microsoft.network/publicipaddresses
microsoft.network/networksecuritygroups
microsoft.network/virtualnetworks
microsoft.network/virtualnetworks/subnets
microsoft.network/networkinterfaces
microsoft.network/connections
microsoft.network/localnetworkgateways
microsoft.network/virtualnetworkgateways
microsoft.network/routetables
microsoft.compute/availabilitysets
microsoft.compute/virtualmachines
microsoft.compute/virtualmachines/extensions
microsoft.compute/disks
microsoft.keyvault/vaults
microsoft.operationalinsights/workspaces
microsoft.managedidentity/userassignedidentities
PS C:> .\Convert_Az2TF.ps1 -SubscriptionID "<my_subscription_ID>"
[12/15/2020 17:21:48] Checking tool dependencies...
[12/15/2020 17:22:01] Finding resources in subscription <my_subscription_ID>...
[12/15/2020 17:22:05] Generating terraform files...
[12/15/2020 17:22:05] Indenting files...
[12/15/2020 17:22:12] Generating import file...
PS C:>
PS C:> cd .\terraform
PS C:\terraform> dir
Directory: C:\terraform
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 12/15/2020 5:22 PM 63 main.tf
-a---- 12/15/2020 5:22 PM 3576 resources.tf
-a---- 12/15/2020 5:22 PM 2211 terraform_import.cmd
PS C:\terraform>
PS C:\terraform> terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/azurerm versions matching "~> 2.21"...
- Installing hashicorp/azurerm v2.40.0...
- Installed hashicorp/azurerm v2.40.0 (signed by HashiCorp)
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
PS C:\terraform> terraform validate
Success! The configuration is valid.
PS C:\terraform> .\terraform_import.cmd
...
C:\terraform> terraform import azurerm_resource_group.rg_containers /subscriptions/<my_subscription_ID>/resourceGroups/containers
azurerm_resource_group.rg_containers: Importing from ID "/subscriptions/<my_subscription_ID>/resourceGroups/containers"...
azurerm_resource_group.rg_containers: Import prepared!
Prepared azurerm_resource_group for import
azurerm_resource_group.rg_containers: Refreshing state... [id=/subscriptions/<my_subscription_ID>/resourceGroups/containers]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
PS C:\terraform> terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
azurerm_resource_group.rg_containers: Refreshing state... [id=/subscriptions/<my_subscription_ID>/resourceGroups/containers]
...
------------------------------------------------------------------------
No changes. Infrastructure is up-to-date.
This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.
PS C:\terraform> Get-Content .\main.tf
provider "azurerm" {
version = "~> 2.21"
features {}
}
PS C:\terraform> Get-Content .\resources.tf
resource "azurerm_resource_group" "rg_containers" {
name = "containers"
location = "westus2"
}
resource "azurerm_resource_group" "rg_mfrg" {
name = "mfrg"
location = "eastus"
tags = {
CostCenter = "10203040"
Dept = "IT"
Owner = "Contoso"
}
}
resource "azurerm_storage_account" "stg_account_name" {
name = "<storage_account_name>"
resource_group_name = azurerm_resource_group.rg_mfrg.name
location = "eastus"
account_tier = "Standard"
account_kind = "StorageV2"
account_replication_type = "LRS"
allow_blob_public_access = true
min_tls_version = "TLS1_2"
tags = {
Delete = "123"
Env = "Test"
}
}
resource "azurerm_virtual_network" "vnet_main-vnet" {
name = "main-vnet"
resource_group_name = azurerm_resource_group.rg_mfrg.name
location = "eastus"
address_space = ["10.8.0.0/16"]
dns_servers = ["10.10.13.101", "10.7.0.4"]
tags = {
blah = "123"
Environment = "Prod"
}
}
resource "azurerm_subnet" "subnet_GatewaySubnet" {
name = "GatewaySubnet"
resource_group_name = azurerm_resource_group.rg_mfrg.name
virtual_network_name = azurerm_virtual_network.vnet_main-vnet.name
address_prefixes = ["10.8.200.0/24"]
}
resource "azurerm_subnet" "subnet_hybridsubnet" {
name = "hybridsubnet"
resource_group_name = azurerm_resource_group.rg_mfrg.name
virtual_network_name = azurerm_virtual_network.vnet_main-vnet.name
address_prefixes = ["10.8.2.0/24"]
}
resource "azurerm_subnet" "subnet_default" {
name = "default"
resource_group_name = azurerm_resource_group.rg_mfrg.name
virtual_network_name = azurerm_virtual_network.vnet_main-vnet.name
address_prefixes = ["10.8.0.0/24"]
service_endpoints = ["Microsoft.Storage"]
}
resource "azurerm_subnet" "subnet_AzureBastionSubnet" {
name = "AzureBastionSubnet"
resource_group_name = azurerm_resource_group.rg_mfrg.name
virtual_network_name = azurerm_virtual_network.vnet_main-vnet.name
address_prefixes = ["10.8.3.0/24"]
}
resource "azurerm_subnet" "subnet_corp-subnet" {
name = "corp-subnet"
resource_group_name = azurerm_resource_group.rg_mfrg.name
virtual_network_name = azurerm_virtual_network.vnet_main-vnet.name
address_prefixes = ["10.8.1.0/24"]
service_endpoints = ["Microsoft.Storage", "Microsoft.KeyVault"]
}
resource "azurerm_public_ip" "pip_azgwpublicip" {
name = "azgwpublicip"
resource_group_name = azurerm_resource_group.rg_mfrg.name
location = "eastus"
allocation_method = "Dynamic"
sku = "Basic"
ip_version = "IPv4"
idle_timeout_in_minutes = "4"
}
resource "azurerm_managed_disk" "disk_notuseddisk_0" {
name = "notuseddisk_0"
location = "westus2"
resource_group_name = azurerm_resource_group.rg_containers.name
storage_account_type = "Standard_LRS"
create_option = "Empty"
disk_size_gb = "32"
}
resource "azurerm_managed_disk" "disk_notuseddisk_1" {
name = "notuseddisk_1"
location = "brazilsouth"
resource_group_name = azurerm_resource_group.rg_containers.name
storage_account_type = "Standard_LRS"
create_option = "Empty"
disk_size_gb = "32"
}
PS C:\terraform>
PS C:\terraform> Get-Content .\resources.tf
resource "azurerm_resource_group" "rg_tfstate" {
name = "tfstate"
location = "eastus2"
}
resource "azurerm_resource_group" "rg_wvdnewrg" {
name = "wvdnewrg"
location = "eastus"
}
resource "azurerm_resource_group" "rg_mflabs" {
name = "mflabs"
location = "eastus"
}
resource "azurerm_storage_account" "stg_acc_name1" {
name = "stg_acc_name1"
resource_group_name = azurerm_resource_group.rg_tfstate.name
location = "eastus2"
account_tier = "Standard"
account_kind = "StorageV2"
account_replication_type = "LRS"
}
resource "azurerm_storage_account" "stg_acc_name2" {
name = "stg_acc_name2"
resource_group_name = azurerm_resource_group.rg_mflabs.name
location = "eastus"
account_tier = "Standard"
account_kind = "Storage"
account_replication_type = "LRS"
}
resource "azurerm_availability_set" "avset_wvd-vm-availabilitySet-eastus" {
name = "wvd-vm-availabilitySet-eastus"
resource_group_name = azurerm_resource_group.rg_wvdnewrg.name
location = "eastus"
managed = true
platform_fault_domain_count = "2"
platform_update_domain_count = "5"
}
resource "azurerm_availability_set" "avset_wvdvmnew-availabilitySet-eastus" {
name = "wvdvmnew-availabilitySet-eastus"
resource_group_name = azurerm_resource_group.rg_wvdnewrg.name
location = "eastus"
managed = true
platform_fault_domain_count = "2"
platform_update_domain_count = "5"
}
resource "azurerm_virtual_network" "vnet_mflabs-vnet" {
name = "mflabs-vnet"
resource_group_name = azurerm_resource_group.rg_mflabs.name
location = "eastus"
address_space = ["10.7.0.0/16"]
dns_servers = ["10.10.13.101", "10.7.0.4"]
}
resource "azurerm_subnet" "subnet_mflabs-azsubnet" {
name = "mflabs-azsubnet"
resource_group_name = azurerm_resource_group.rg_mflabs.name
virtual_network_name = azurerm_virtual_network.vnet_mflabs-vnet.name
address_prefixes = ["10.7.0.0/24"]
}
resource "azurerm_public_ip" "pip_AZDC1-ip" {
name = "AZDC1-ip"
resource_group_name = azurerm_resource_group.rg_mflabs.name
location = "eastus"
allocation_method = "Dynamic"
sku = "Basic"
ip_version = "IPv4"
idle_timeout_in_minutes = "4"
}
resource "azurerm_public_ip" "pip_AZCS1-ip" {
name = "AZCS1-ip"
resource_group_name = azurerm_resource_group.rg_mflabs.name
location = "eastus"
allocation_method = "Dynamic"
sku = "Basic"
ip_version = "IPv4"
idle_timeout_in_minutes = "4"
domain_name_label = "<domain_name_label>"
}
resource "azurerm_network_interface" "nic_azdc1801" {
name = "azdc1801"
resource_group_name = azurerm_resource_group.rg_mflabs.name
location = "eastus"
ip_configuration {
name = "ipconfig1"
subnet_id = azurerm_subnet.subnet_mflabs-azsubnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.pip_AZDC1-ip.id
}
ip_configuration {
name = "ipconfig2"
subnet_id = azurerm_subnet.subnet_mflabs-azsubnet.id
private_ip_address_allocation = "Dynamic"
}
tags = {
blah = "test"
yep = "5"
}
}
resource "azurerm_network_interface" "nic_wvd-vm-0-nic" {
name = "wvd-vm-0-nic"
resource_group_name = azurerm_resource_group.rg_wvdnewrg.name
location = "eastus"
ip_configuration {
name = "ipconfig"
subnet_id = azurerm_subnet.subnet_mflabs-azsubnet.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_network_interface" "nic_wvdvmnew-0-nic" {
name = "wvdvmnew-0-nic"
resource_group_name = azurerm_resource_group.rg_wvdnewrg.name
location = "eastus"
ip_configuration {
name = "ipconfig"
subnet_id = azurerm_subnet.subnet_mflabs-azsubnet.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_network_interface" "nic_azcs1490" {
name = "azcs1490"
resource_group_name = azurerm_resource_group.rg_mflabs.name
location = "eastus"
ip_configuration {
name = "ipconfig1"
subnet_id = azurerm_subnet.subnet_mflabs-azsubnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.pip_AZCS1-ip.id
}
}
resource "azurerm_managed_disk" "disk_AZDC1_DataDisk_0" {
name = "AZDC1_DataDisk_0"
location = "eastus"
resource_group_name = azurerm_resource_group.rg_mflabs.name
storage_account_type = "Standard_LRS"
create_option = "Empty"
disk_size_gb = "128"
}
resource "azurerm_windows_virtual_machine" "vm_AZDC1" {
name = "AZDC1"
resource_group_name = azurerm_resource_group.rg_mflabs.name
location = "eastus"
size = "Standard_B2s"
admin_username = "<user>"
admin_password = "<passwd>"
license_type = "Windows_Server"
boot_diagnostics {
storage_account_uri = "https://<storage_account_name>.blob.core.windows.net/"
}
network_interface_ids = [
azurerm_network_interface.nic_azdc1801.id
]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
disk_size_gb = "127"
name = "AZDC1_OsDisk_1_5498a2a2073341c9b67abaa47673899d"
}
source_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2012-R2-Datacenter"
version = "latest"
}
}
resource "azurerm_windows_virtual_machine" "vm_AZCS1" {
name = "AZCS1"
resource_group_name = azurerm_resource_group.rg_mflabs.name
location = "eastus"
size = "Standard_B2s"
admin_username = "<user>"
admin_password = "<passwd>"
license_type = "Windows_Server"
boot_diagnostics {
storage_account_uri = "https://<storage_account_name>.blob.core.windows.net/"
}
network_interface_ids = [
azurerm_network_interface.nic_azcs1490.id
]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
disk_size_gb = "127"
name = "AZCS1_OsDisk_1_14b0d6fd0a2940ccab5b04c5f9560dd8"
}
source_image_reference {
publisher = "MicrosoftWindowsServer"
offer = "WindowsServer"
sku = "2019-Datacenter"
version = "latest"
}
}
resource "azurerm_windows_virtual_machine" "vm_wvd-vm-0" {
name = "wvd-vm-0"
resource_group_name = azurerm_resource_group.rg_wvdnewrg.name
location = "eastus"
size = "Standard_D2s_v3"
admin_username = "<user>"
admin_password = "<passwd>"
license_type = "Windows_Client"
availability_set_id = azurerm_availability_set.avset_wvd-vm-availabilitySet-eastus.id
network_interface_ids = [
azurerm_network_interface.nic_wvd-vm-0-nic.id
]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
disk_size_gb = "127"
name = "wvd-vm-0_OsDisk_1_76c703cc6c544127b2f68cc9775eb018"
}
source_image_reference {
publisher = "MicrosoftWindowsDesktop"
offer = "office-365"
sku = "20h1-evd-o365pp"
version = "latest"
}
}
resource "azurerm_virtual_machine_data_disk_attachment" "disk_att_AZDC1_DataDisk_0" {
managed_disk_id = azurerm_managed_disk.disk_AZDC1_DataDisk_0.id
virtual_machine_id = azurerm_windows_virtual_machine.vm_AZDC1.id
lun = 0
caching = "None"
}
PS C:\terraform>