I use Terraform IAC (Infrastructure as a code) a lot to design Azure resources, While deploying Azure Resource NSG (Network Security Group), I was defining multiple roles inside NSG, Roles were mentioned inside the main.tf code script file. I wanted roles values to be moved to variables inside variable.tf file, so it can be manage better and I can reduce the code inside main.tf file for better readability.
Related Articles:
Terraform Using one module variable in another module
Writing and Using Terraform modules
Terraform for_each loop on map example
Below is the my normal code to create NSG and multiple rules, check the security_rule mentioned inside the terraform resource azurerm_network_security_group. Multiple rules are configured directly inside the main.tf terraform code file. My task is to move multiple security_rule blocks to variable.tf file.
#main.tf - Before adding dynamic block provider "azurerm" { features {} } resource "azurerm_resource_group" "demo" { name = var.rg_name location = var.location } resource "azurerm_network_security_group" "vcloud-lab" { name = var.nsg_name location = azurerm_resource_group.demo.location resource_group_name = azurerm_resource_group.demo.name security_rule { name = "Rule01" priority = 100 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "80" destination_port_range = "*" source_address_prefix = "*" destination_address_prefix = "*" } security_rule { name = "Rule02" priority = 110 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "443" destination_port_range = "*" source_address_prefix = "*" destination_address_prefix = "*" } tags = { environment = "dev" owner = "vcloud-lab.com" } } #variable.tf - Before adding dynamic block variable "rg_name" { type = string default = "RG_vCloud-lab" } variable "location" { type = string default = "West Us" } variable "nsg_name" { type = string default = "NSG_vCloud-lab" }
Before working and moving security_rule to variables I tested the existing unedited code with terraform init and terraform plan. It is working fine and will adding 2 resources.
After adding Dynamic Block to main.tf:
From main.tf I moved security_rule to the sec_rules named variable in variable.tf file. The type of sec_rules is list(object({})). Inside main.tf to use multiple rules I am using dynamic block with name security_rule (as same as resource attribute), Under it I have mentioned for_each loop taking sec_rules map/set information stored and mentioned in the variable default value. This values are fetched in the loop fashion with key pair value map (dictionary).
As you can see below in the screenshots with markings.
#main.tf - After adding dynamic block provider "azurerm" { features {} } resource "azurerm_resource_group" "demo" { name = var.rg_name location = var.location } resource "azurerm_network_security_group" "vcloud-lab" { name = var.nsg_name location = azurerm_resource_group.demo.location resource_group_name = azurerm_resource_group.demo.name dynamic "security_rule" { for_each = var.sec_rules content { name = security_rule.value["name"] priority = security_rule.value["priority"] direction = security_rule.value["direction"] access = security_rule.value["access"] protocol = security_rule.value["protocol"] source_port_range = security_rule.value["source_port_range"] destination_port_range = security_rule.value["destination_port_range"] source_address_prefix = "*" destination_address_prefix = "*" } } tags = { environment = "dev" owner = "vcloud-lab.com" } } #variable.tf - After adding dynamic block variable "rg_name" { type = string default = "RG_vloud-lab" } variable "location" { type = string default = "West Us" } variable "nsg_name" { type = string default = "NSG_vCloud-lab" } variable "sec_rules" { description = "NSG security rules" type = list(object({ name = string priority = number direction = string access = string protocol = string source_port_range = string destination_port_range = string source_address_prefix = string destination_address_prefix = string })) default = [{ name = "Rule01" priority = 100 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "80" destination_port_range = "*" source_address_prefix = "*" destination_address_prefix = "*" }, { name = "Rule02" priority = 110 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "443" destination_port_range = "*" source_address_prefix = "*" destination_address_prefix = "*" }] }
Using terraform apply -auto-approve I can verify information is getting created successfully.
Download terraform code files here or it is also available on github.com.
Below is the complete snap shot of the terrform report.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
PS D:\Projects\Terraform\Dynamic_Block> terraform init Initializing the backend... Initializing provider plugins... - Reusing previous version of hashicorp/azurerm from the dependency lock file - Using previously-installed hashicorp/azurerm v2.74.0 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 D:\Projects\Terraform\Dynamic_Block> terraform plan Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_network_security_group.vcloud-lab will be created + resource "azurerm_network_security_group" "vcloud-lab" { + id = (known after apply) + location = "westus" + name = "NSG_vCloud-lab" + resource_group_name = "RG_vCloud-lab" + security_rule = [ + { + access = "Allow" + description = "" + destination_address_prefix = "*" + destination_address_prefixes = [] + destination_application_security_group_ids = [] + destination_port_range = "*" + destination_port_ranges = [] + direction = "Inbound" + name = "Rule01" + priority = 100 + protocol = "Tcp" + source_address_prefix = "*" + source_address_prefixes = [] + source_application_security_group_ids = [] + source_port_range = "80" + source_port_ranges = [] }, + { + access = "Allow" + description = "" + destination_address_prefix = "*" + destination_address_prefixes = [] + destination_application_security_group_ids = [] + destination_port_range = "*" + destination_port_ranges = [] + direction = "Inbound" + name = "Rule02" + priority = 110 + protocol = "Tcp" + source_address_prefix = "*" + source_address_prefixes = [] + source_application_security_group_ids = [] + source_port_range = "443" + source_port_ranges = [] }, ] + tags = { + "environment" = "dev" + "owner" = "vcloud-lab.com" } } # azurerm_resource_group.demo will be created + resource "azurerm_resource_group" "demo" { + id = (known after apply) + location = "westus" + name = "RG_vCloud-lab" } Plan: 2 to add, 0 to change, 0 to destroy. ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now. PS D:\Projects\Terraform\Dynamic_Block> terraform apply -auto-approve Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_network_security_group.vcloud-lab will be created + resource "azurerm_network_security_group" "vcloud-lab" { + id = (known after apply) + location = "westus" + name = "NSG_vCloud-lab" + resource_group_name = "RG_vCloud-lab" + security_rule = [ + { + access = "Allow" + description = "" + destination_address_prefix = "*" + destination_address_prefixes = [] + destination_application_security_group_ids = [] + destination_port_range = "*" + destination_port_ranges = [] + direction = "Inbound" + name = "Rule01" + priority = 100 + protocol = "Tcp" + source_address_prefix = "*" + source_address_prefixes = [] + source_application_security_group_ids = [] + source_port_range = "80" + source_port_ranges = [] }, + { + access = "Allow" + description = "" + destination_address_prefix = "*" + destination_address_prefixes = [] + destination_application_security_group_ids = [] + destination_port_range = "*" + destination_port_ranges = [] + direction = "Inbound" + name = "Rule02" + priority = 110 + protocol = "Tcp" + source_address_prefix = "*" + source_address_prefixes = [] + source_application_security_group_ids = [] + source_port_range = "443" + source_port_ranges = [] }, ] + tags = { + "environment" = "dev" + "owner" = "vcloud-lab.com" } } # azurerm_resource_group.demo will be created + resource "azurerm_resource_group" "demo" { + id = (known after apply) + location = "westus" + name = "RG_vCloud-lab" } Plan: 2 to add, 0 to change, 0 to destroy. azurerm_resource_group.demo: Creating... azurerm_resource_group.demo: Creation complete after 5s [id=/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/RG_vCloud-lab] azurerm_network_security_group.vcloud-lab: Creating... azurerm_network_security_group.vcloud-lab: Still creating... [10s elapsed] azurerm_network_security_group.vcloud-lab: Creation complete after 20s [id=/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/RG_vCloud-lab/providers/Microsoft.Network/networkSecurityGroups/NSG_vCloud-lab] Apply complete! Resources: 2 added, 0 changed, 0 destroyed. |
Useful Articles
Create an Azure App registrations in Azure Active Directory using PowerShell & AzureCLI
Get started and configure with certificate-based authentication in Azure
Create a Virtual machine on Microsoft Azure
PowerShell List All Azure Resverations
Powershell get the list of Azure Reservations Virtual Machines instances
Get the list Azure Reservation Catalog with PowerShell and AzureCLI
Azure automation account DSC for On-Premise Virtual Machine on boarding
Azure Powershell : Operation returned an invalid status code 'BadRequest'
Get Azure virtual machine backup reports using Powershell