Terraform Azure network security - azure

I'm trying to configure a network security rule for a network security group in Azure via Terraform with multiple source addresses.
Based on the documentation
https://www.terraform.io/docs/providers/azurerm/r/network_security_rule.html
However, I'm not able to get this to work nor can I find any examples for it:
https://www.terraform.io/docs/providers/azurerm/r/network_security_rule.html#source_address_prefixes
I get the Error:
Error: azurerm_network_security_rule.test0: "source_address_prefix": required field is not set
Error: azurerm_network_security_rule.test0: : invalid or unknown key: source_address_prefixes
Here is my sample:
resource "azurerm_network_security_rule" "test0" {
name = "RDP"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "3389"
source_address_prefixes = "{200.160.200.30,200.160.200.60}"
destination_address_prefix = "VirtualNetwork"
network_security_group_name= "${azurerm_network_security_group.test.name}"
resource_group_name = "${azurerm_resource_group.test.name}"
}
Please let me know.
Thanks!

source_address_prefixes needs list of source address prefixes.
Modify it as below:
source_address_prefixes = ["200.160.200.30","200.160.200.60"]
There also a mistake in azurerm_network_security_group.test.name, the correct type is azurerm_network_security_group.test0.name. The following tf file works for me.
resource "azurerm_resource_group" "test0" {
name = "shuinsg"
location = "West US"
}
resource "azurerm_network_security_group" "test0" {
name = "shuinsgtest"
location = "${azurerm_resource_group.test0.location}"
resource_group_name = "${azurerm_resource_group.test0.name}"
}
resource "azurerm_network_security_rule" "test0" {
name = "RDP"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "TCP"
source_port_range = "*"
destination_port_range = "3389"
source_address_prefixes = ["200.160.200.30","200.160.200.60"]
destination_address_prefix = "VirtualNetwork"
network_security_group_name= "${azurerm_network_security_group.test0.name}"
resource_group_name = "${azurerm_resource_group.test0.name}"
}
Here is my test result.

An "address_prefix" is a string values representing a CIDR e.g. 10.0.0.0/24. So in your case source_address_prefix = "200.160.200.30/32" and destination_address_prefix = "${azurerm_virtual_network.test.address_space.0}" depending on what you want to refer to.

Related

Passing the outputs from a module when the module is created using a for_each

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 think it's the problem that you read the previous answer not carefully. The answer shows you need to change the security group name like this:
network_security_group_name = module.fico_app_vm.linux_vm_nsg
There are no double-quotes. Double-quotes means it's a string. But you need to use the module attribute, not a string with a value "module.fico_app_vm.linux_vm_nsg". The error also shows it directly.
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"
}
}

What is the equivalent argument field for source, source service tag and destination field in NSG security rules azure using teraform deployment

In the Source and Destination columns, VirtualNetwork, AzureLoadBalancer, and Internet are service tags, rather than IP addresses. How do i create this using terraform?
I am trying to create NSG on azure using terraform. While creating nsg security rules fields like source, source service tags and destination field is mandatory for creating nsg. How do i create this field using terraform ?
You could see source_address_prefix or destination_address_prefix in the Argument Reference. Tags such as ‘VirtualNetwork’, ‘AzureLoadBalancer’ and ‘Internet’ can also be used.
For example, you just need to add the specific service tag in the source_address_prefix and destination_address_prefix field.
# VirtualNetwork
security_rule {
name = "RDP"
priority = 300
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "VirtualNetwork"
destination_address_prefix = "VirtualNetwork"
}
#AppService
security_rule {
name = "SQL"
priority = 310
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "AppService"
destination_address_prefix = "*"
}
result

azure with terraform multiple rules for security group

I need to setup multiple security rules for Azure resources.
On AWS, I could just do multiple ingress:
resource "aws_security_group" "mygroup" {
name = "mygroup"
ingress {
description = "allow all on ssh port"
from_port = var.ssh
to_port = var.ssh
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "public port"
from_port = var.public
to_port = var.public
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "restricted"
from_port = var.restricted
to_port = var.restricted
protocol = "tcp"
cidr_blocks = ["<restricted-ip>/32"]
}
But I do not know how to do this on Azure.
As far as I can see azurerm_network_security_group allows only one security_rule (is this correct?).
Maybe I would be able to create multiple azurerm_network_interface_security_group_association for the same network_interface_id but different network_security_group_id?
You use an azurerm_network_security_rule resource per rule you add as follows: (example quoted from azurerm_network_security_rule resource docs)
resource "azurerm_network_security_group" "example" {
name = "acceptanceTestSecurityGroup1"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
}
resource "azurerm_network_security_rule" "example" {
name = "test123"
priority = 100
direction = "Outbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.example.name
network_security_group_name = azurerm_network_security_group.example.name
}
Technically, you can define them inline, but you shouldn't as it makes it impossible for other modules to add security group rules if needed. This happens pretty often in practice in my experience, so please don't use inline rule, use separate resources. Your colleagues, including your future self, will thank you.

azurerm_network_security_rule with variable source_address_prefix

I'm deploying some firewall rules on Azure with Terraform and would like to keep the "source_address_prefix" in a variable, given that the list contains more than 20 IPs and they can change. Since I have around 5 rules, it's not ideal to add the IPs in each block and would rather use a variable
Tried the following variations of variable:
source_address_prefix = ["${var.whitelist_ips}"]
source_address_prefix = "${var.whitelist_ips}"
variables.tf
variable "whitelist_ips" {
type = "list"
default = ["199.83.128.0/21","198.143.32.0/19", "149.126.72.0/21","103.28.248.0/22", "45.64.64.0/22", "185.11.124.0/22", "192.230.64.0/18", "107.154.0.0/16", "45.60.0.0/16", "45.223.0.0/16", "2a02:e980::/29"]
}
main.tf
resource "azurerm_network_security_rule" "https" {
name = "Whitelist-HTTPS"
priority = 101
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "443"
destination_port_range = "*"
source_address_prefix = ["${var.whitelist_ips}"]
destination_address_prefix = "${azurerm_public_ip.ingress.ip_address}"
resource_group_name = "test"
network_security_group_name = "test"
depends_on = [azurerm_resource_group.aks]
}
Getting the following errors:
Error: Incorrect attribute value type
on main.tf line 35, in resource "azurerm_network_security_rule" "http":
35: source_address_prefix = ["${var.whitelist_ips}"]
Inappropriate value for attribute "source_address_prefix": string required.
Begone with that weird 0.11 syntax, with explicit depends_on, also the source port seemed wrong:
resource azurerm_network_security_rule this {
name = "Whitelist-HTTPS"
resource_group_name = azurerm_resource_group.this.name
network_security_group_name = azurerm_network_security_group.this.name
priority = 101
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefixes = var.whitelist_ips
destination_address_prefix = azurerm_public_ip.ingress.ip_address
}
variable whitelist_ips {
description = "A list of IP CIDR ranges to allow as clients. Do not use Azure tags like `Internet`."
default = ["199.83.128.0/21", "198.143.32.0/19", "2a02:e980::/29"]
type = list(string)
}
Should have paid attention to the docs. The actual block is "source_address_prefixes" and not "source_address_prefix".

How to reference azure network security ID in a module in Terraform?

I'm not sure how to reference an azure network security group in a module. I created a module that I can reuse for any VM I create which works to an extent except I'm not sure how to assign the network security group ID to it. The below is an example (slightly amended, I don't have it on me) that is very close to what I have and is based on.
main.tf at root
module "vm1" {
source = "/modules/vm/"
NSG = ????
}
tfvars
nic_name = apache_vm_nic
location = West Europe
........
modules/vm/main.tf
.........
resource "azurerm_network_interface" "myterraformnic" {
name = "var.nic_name"
location = "var.location"
resource_group_name = "${azurerm_resource_group.myterraformgroup.name}"
network_security_group_id = { WHAT DO I PUT HERE? }
ip_configuration {
name = "myNicConfiguration"
subnet_id = "${azurerm_subnet.myterraformsubnet.id}"
private_ip_address_allocation = "dynamic"
public_ip_address_id = "${azurerm_public_ip.myterraformpublicip.id}"
}
}
resource "azurerm_network_security_group" "apache-nsg" {
name = "myNetworkSecurityGroup"
location = "eastus"
resource_group_name = "${azurerm_resource_group.myterraformgroup.name}"
security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "azurerm_network_security_group" "nginx-nsg" {
name = "myNetworkSecurityGroup"
location = "eastus"
resource_group_name = "${azurerm_resource_group.myterraformgroup.name}"
security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
in the module/main.tf file under network_security_group_id, I can't exactly put ${azurerm_network_security_group.apache-nsg.id} or ${azurerm_network_security_group.nginx-nsg.id}. So what can I put so I can reuse this module for all VMs?
Thanks
Your question isn't quite clear to me but I am going to assume you want to create a generic network security group that you want to assign to multiple instances of your VM module.
If you want to pass the ID of a security group from main.tf at root, you'd do this:
Create a network security group resource outside your module, e.g. inside main.tf at root, just like you created a few inside your VM module (for Apache and Nginx), so that main.tf at root looks like this:
resource "azurerm_network_security_group" "some_generic_vm_nsg" {
....
}
module "vm1" {
source = "/modules/vm/"
NSG = "${azurerm_network_security_group.some_generic_vm_nsg.id}"
}
Note that we are now passing the ID of the nsg to your VM module instance.
However, your VM module has not declared the NSG variable yet. So create the file modules/vm/variables.tf and put this in it:
variable "NSG" {
type = "string"
}
And inside your module, network_security_group_id = { WHAT DO I PUT HERE? } becomes:
network_security_group_id = "${var.NSG}"
This way, you can assign the same network security group to multiple VM module instances.
You can study this documentation for more elaborate information.

Resources