This links to my the previous question, click the link for the rest of my code and how it all fits together: Use output value from module that has a for_each set
Whilst the answer was helpful in solving the issue and allowing me to run the pipeline, I think there is an error because of the way the VM is generated using the for_each on the module. This results in the incorrect value being passed to the network_security_rule. Below is an example of the error:
Error: Error Creating/Updating Network Security Rule "nsr-sbox-http80" (NSG "module.fico_app_vm.linux_vm_nsg" / Resource Group "rg-sbox-app"): network.SecurityRulesClient#CreateOrUpdate: Failure sending request: StatusCode=404 -- Original Error: Code="ResourceNotFound" Message="The Resource 'Microsoft.Network/networkSecurityGroups/module.fico_app_vm.linux_vm_nsg' under resource group 'rg-sbox-app' was not found. For more details please go to https://aka.ms/ARMResourceNotFoundFix"
on main.tf line 58, in resource "azurerm_network_security_rule" "fico-app-sr-80":
58: resource "azurerm_network_security_rule" "fico-app-sr-80" {
outputs.tf
output "linux_vm_ips" {
value = azurerm_network_interface.dwp_network_interface.private_ip_address
}
output "linux_vm_nsg" {
value = azurerm_network_security_group.dwp_network_security_group.name
}
At first I thought it was because the NSG isn't being created, but I checked the console and it does create it. The issue is the NSG is created in the module for each VM. The VM's are created by looping over the variable in tfvars file. How do I pass the NSG name created in the module to the security rule which is outside of the module?:
resource "azurerm_network_security_rule" "fico-app-sr-80" {
name = "nsr-${var.environment}-${var.directorate}-${var.business_unit}-${var.vm_identifier}${var.instance_number}-http80"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "80"
source_address_prefixes = ["module.fico_web_vm.linux_vm_ips"]
destination_address_prefix = "VirtualNetwork"
resource_group_name = azurerm_resource_group.rg_fico_app.name
network_security_group_name = "module.fico_app_vm.linux_vm_nsg"
}
# Network Security Group
resource "azurerm_network_security_group" "network_security_group" {
name = "nsg-${var.environment}-${var.directorate}-${var.business_unit}-${var.vm_identifier}-${var.vm_name}"
resource_group_name = var.resource_group
location = var.location
}
Something to note as well, is that the var.vm_name iterates through the key of each map and this makes up part of the name of the NSG.
module in main.tf:
module "fico_app_vm" {
for_each = var.app_servers
source = "../modules/compute/linux_vm"
source_image_id = var.app_image_id
location = var.location
vm_name = each.key
vm_identifier = "${var.vm_identifier}${var.instance_number}"
vm = each.value
disks = each.value["disks"]
resource_group = azurerm_resource_group.rg_fico_app.name
directorate = var.directorate
business_unit = var.business_unit
environment = var.environment
network_rg_identifier = var.network_rg_identifier
subnet_name = "sub-${var.environment}-${var.directorate}-${var.business_unit}-be01"
diag_storage_account_name = var.diag_storage_account_name
ansible_storage_account_name = var.ansible_storage_account_name
ansible_storage_account_key = var.ansible_storage_account_key
log_analytics_workspace_name = var.log_analytics_workspace_name
backup_policy_name = var.backup_policy_name
enable_management_locks = true
}
tfvars:
app_servers ={
app-1 = {
size = "Standard_E2s_v3"
admin_username = "xxx"
public_key = "xxx"
disks = [32, 32]
zone_vm = "1"
zone_disk = ["1"]
}
}
I realised what my error was. I needed to change this:
network_security_group_name = "module.fico_app_vm.linux_vm_nsg"
to this
network_security_group_name = module.fico_app_vm[each.key].linux_vm_nsg
But I also needed to reference the value in the source address prefixes. So to reference the key I created another variable and changed this:
source_address_prefixes = ["module.fico_web_vm.linux_vm_ips"]
to this:
source_address_prefix = module.fico_web_vm[each.value.web_server].linux_vm_ip
I also had to change to source_address_prefix and thats why the type error was occurring!
The security rule now looks like this:
resource "azurerm_network_security_rule" "fico-app-sr-80" {
for_each = var.app_servers
name = "nsr-${var.environment}-${var.directorate}-${var.business_unit}-${var.vm_identifier}${var.instance_number}-http80"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = module.fico_web_vm[each.value.web_server].linux_vm_ip
destination_address_prefix = "VirtualNetwork"
resource_group_name = azurerm_resource_group.rg_dwp_fico_app.name
network_security_group_name = module.fico_app_vm[each.key].linux_vm_nsg
And variable looks like this:
app_servers = {
app-1 = {
size = "Standard_E2s_v3"
admin_username = "azureuser"
public_key = xxxx
disks = [32, 32]
zone_vm = "1"
zone_disk = ["1"]
web_server = "web-1"
}
}