Azure Networking + Terraform

Build Azure Firewall with Terraform

Once you understand Azure Firewall conceptually, the next step is to build it with Terraform. This helps turn centralized traffic inspection and security policy into reusable infrastructure as code that can be reviewed, versioned, and deployed consistently.

This page shows a practical Azure Firewall Terraform example using Azure Firewall plus Firewall Policy and a rule collection group, which reflects Microsoft’s current recommended configuration model. Azure’s own Terraform quickstart demonstrates this same overall pattern. :contentReference[oaicite:1]{index=1}

Quick summary

Before going deeper, here is the simplest way to think about Azure Firewall Terraform.

What Terraform code that creates Azure Firewall, Firewall Policy, and one or more rule collection groups.
Why It makes centralized firewall policy consistent, reviewable, and reusable across environments.
When Use it whenever you want repeatable Azure Firewall deployment through infrastructure as code.
Where It fits into hub-and-spoke networks, enterprise landing zones, outbound control, and DNAT publishing designs.
Who Cloud, DevOps, platform, and network security teams usually manage it.
How Using azurerm_firewall, azurerm_firewall_policy, and often azurerm_firewall_policy_rule_collection_group. :contentReference[oaicite:2]{index=2}

Why use Terraform for Azure Firewall?

Azure Firewall can be deployed manually in the Azure portal, but Terraform is better when you need repeatable policy structure, reviewable rule logic, and reusable network security foundations.

  • It keeps firewall and policy configuration in code instead of clicks.
  • It makes rule changes visible in Git and code review.
  • It reduces manual mistakes around subnets, public IPs, and rule ordering.
  • It helps teams standardize centralized firewall patterns across environments.
  • It fits naturally into CI/CD and reusable Azure network modules.
Simple idea: Terraform turns Azure Firewall from a one-time portal deployment into a reusable security architecture pattern.

Terraform code

This example creates:

  • an Azure resource group
  • a virtual network
  • the required AzureFirewallSubnet
  • a public IP
  • an Azure Firewall Policy
  • an Azure Firewall instance
  • a Firewall Policy Rule Collection Group with one network rule collection and one application rule collection
terraform {
  required_version = ">= 1.5.0"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.100"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = var.resource_group_name
  location = var.location
}

resource "azurerm_virtual_network" "vnet" {
  name                = var.vnet_name
  address_space       = ["10.70.0.0/16"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "firewall_subnet" {
  name                 = "AzureFirewallSubnet"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.70.0.0/26"]
}

resource "azurerm_public_ip" "firewall_pip" {
  name                = var.public_ip_name
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Static"
  sku                 = "Standard"
}

resource "azurerm_firewall_policy" "fw_policy" {
  name                = var.firewall_policy_name
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  dns {
    proxy_enabled = true
    servers       = ["168.63.129.16"]
  }

  tags = {
    environment = var.environment
    managed_by  = "terraform"
    purpose     = "centralized-firewall-policy"
  }
}

resource "azurerm_firewall" "firewall" {
  name                = var.firewall_name
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  sku_name            = "AZFW_VNet"
  sku_tier            = "Standard"
  firewall_policy_id  = azurerm_firewall_policy.fw_policy.id

  ip_configuration {
    name                 = "firewall-ipconfig"
    subnet_id            = azurerm_subnet.firewall_subnet.id
    public_ip_address_id = azurerm_public_ip.firewall_pip.id
  }

  tags = {
    environment = var.environment
    managed_by  = "terraform"
    purpose     = "centralized-firewall"
  }
}

resource "azurerm_firewall_policy_rule_collection_group" "fw_rcg" {
  name               = "default-rule-collection-group"
  firewall_policy_id = azurerm_firewall_policy.fw_policy.id
  priority           = 100

  network_rule_collection {
    name     = "network-rules"
    priority = 100
    action   = "Allow"

    rule {
      name                  = "allow-ntp"
      protocols             = ["UDP"]
      source_addresses      = ["10.70.1.0/24"]
      destination_addresses = ["13.86.101.172"]
      destination_ports     = ["123"]
    }
  }

  application_rule_collection {
    name     = "application-rules"
    priority = 200
    action   = "Allow"

    rule {
      name             = "allow-microsoft"
      source_addresses = ["10.70.1.0/24"]
      destination_fqdns = [
        "www.microsoft.com"
      ]
      protocols {
        port = 443
        type = "Https"
      }
    }
  }
}
Important reminder: Microsoft’s official Terraform quickstart for Azure Firewall and Firewall Policy also uses a policy-driven model with application and network rules. :contentReference[oaicite:3]{index=3}

Code breakdown

AzureFirewallSubnet

Azure Firewall requires a dedicated subnet named AzureFirewallSubnet, and Microsoft documents that this subnet must be at least a /26. This is one of the most important deployment requirements. :contentReference[oaicite:4]{index=4}

Public IP

The firewall needs a Standard public IP for many common deployment models. Azure also supports multi-public-IP patterns in separate examples. :contentReference[oaicite:5]{index=5}

Firewall Policy

Microsoft recommends Firewall Policy as the preferred configuration model for Azure Firewall, and the Terraform provider exposes azurerm_firewall_policy for this purpose. :contentReference[oaicite:6]{index=6}

Azure Firewall

The azurerm_firewall resource creates the firewall instance itself, attaches it to the required subnet, and links it to the Firewall Policy. :contentReference[oaicite:7]{index=7}

Rule Collection Group

Firewall Policy Rule Collection Groups organize network, application, and DNAT rule collections under the policy. Terraform exposes this through azurerm_firewall_policy_rule_collection_group. :contentReference[oaicite:8]{index=8}

Why this structure is useful

This example is practical because it follows the current Azure direction: firewall instance plus Firewall Policy plus rule collection groups, instead of treating the firewall itself as the whole configuration model. :contentReference[oaicite:9]{index=9}

Important firewall fields

A good Azure Firewall Terraform page should explain that deployment is not only about creating the firewall resource. Several fields strongly affect whether the design actually works.

Field What it controls Example
sku_name Firewall deployment mode for the resource AZFW_VNet
sku_tier Firewall SKU tier Standard
firewall_policy_id Which Firewall Policy the instance should use policy resource ID
subnet_id Which subnet hosts the firewall instance AzureFirewallSubnet
public_ip_address_id Which public IP is attached to the firewall IP configuration Standard Public IP
proxy_enabled Whether Firewall Policy DNS proxy is enabled true
Important reminder: A Terraform apply can succeed even if the firewall still does not inspect real traffic because the subnet routes, rule design, or DNS expectations are wrong.

Rule collection group model

In Azure’s current model, Firewall Policy is where the firewall logic lives, and Rule Collection Groups organize the actual rule collections beneath that policy. Microsoft’s Terraform quickstart uses this model with application and network rules, and the Terraform provider has a dedicated resource for it. :contentReference[oaicite:10]{index=10}

Layer Purpose Simple explanation
Firewall Policy Top-level policy object The reusable policy container for Azure Firewall behavior
Rule Collection Group Organizes collections under the policy The ordered container that holds one or more rule collections
Rule Collection Groups related rules Such as one network rule collection or one application rule collection
Rule The actual traffic match logic For example allow NTP or allow HTTPS to a specific FQDN
Simple idea: Policy is the strategy, rule collection groups are the structure, and rules are the detailed traffic logic.

Suggested variables

Variables make Azure Firewall Terraform code more reusable across development, testing, and production environments.

variable "resource_group_name" {
  description = "Name of the Azure resource group"
  type        = string
}

variable "location" {
  description = "Azure region for deployment"
  type        = string
  default     = "South Africa North"
}

variable "vnet_name" {
  description = "Name of the Azure Virtual Network"
  type        = string
}

variable "public_ip_name" {
  description = "Name of the Azure Firewall public IP"
  type        = string
}

variable "firewall_name" {
  description = "Name of the Azure Firewall instance"
  type        = string
}

variable "firewall_policy_name" {
  description = "Name of the Azure Firewall Policy"
  type        = string
}

variable "environment" {
  description = "Environment name"
  type        = string
  default     = "dev"
}

Example terraform.tfvars

resource_group_name  = "rg-network-dev-san-1"
location             = "South Africa North"
vnet_name            = "vnet-hub-dev-san-1"
public_ip_name       = "pip-fw-dev-san-1"
firewall_name        = "fw-dev-san-1"
firewall_policy_name = "fwp-dev-san-1"
environment          = "dev"

Suggested outputs

Outputs help expose firewall and policy IDs for validation or later modules.

output "firewall_id" {
  value = azurerm_firewall.firewall.id
}

output "firewall_policy_id" {
  value = azurerm_firewall_policy.fw_policy.id
}

output "firewall_public_ip" {
  value = azurerm_public_ip.firewall_pip.ip_address
}

How to run it

A simple Terraform execution flow looks like this:

terraform init
terraform fmt
terraform validate
terraform plan
terraform apply

In real teams, these steps often run through CI/CD after review rather than manually every time.

Good habit: Always run terraform fmt and terraform validate before planning or applying changes.

Real-world usage

This Azure Firewall Terraform pattern can grow into real enterprise security architecture workflows.

Hub-and-spoke centralized inspection

A platform team deploys one or more Azure Firewall instances in a hub VNet and uses route tables so spoke traffic passes through the firewall for outbound inspection.

Policy reuse across environments

A security team uses Firewall Policy to standardize application and network rule logic across multiple Azure environments or regions.

Outbound control plus NTP or update access

Teams use network rule collections for low-level traffic like NTP and application rule collections for outbound web access to approved destinations.

Important mindset: Start with a clear policy-driven firewall example, then expand into route tables, DNAT collections, IP Groups, multi-public-IP patterns, or forced tunneling when your architecture needs them. :contentReference[oaicite:11]{index=11}

Best practices

  • Use Firewall Policy for new designs.
  • Keep AzureFirewallSubnet dedicated to the firewall only.
  • Make sure the firewall subnet is at least /26 as documented by Azure.
  • Use clear names for policies, rule collection groups, and public IPs.
  • Be deliberate with route tables so traffic actually reaches the firewall.
  • Plan DNS behavior early if using FQDN-based application rules or DNS proxy.
  • Keep rule collections readable and logically grouped.
  • Document why each rule collection exists, not only what it allows.
Strong next step: After this firewall example, a natural progression is DNAT rule collections, route table steering, IP Groups, and then more advanced hub-and-spoke or forced-tunneling patterns. :contentReference[oaicite:12]{index=12}

Common mistakes

  • Using the wrong subnet name instead of AzureFirewallSubnet.
  • Making the firewall subnet too small.
  • Deploying the firewall correctly but forgetting route tables.
  • Treating Firewall Policy as optional in new standardized designs.
  • Mixing application-rule intent and network-rule intent without a clear structure.
  • Assuming successful deployment means real traffic is being inspected.
Common beginner trap: Just because Terraform created Azure Firewall successfully does not mean the firewall is in the traffic path. Routing still decides whether workloads actually use it.

Frequently asked questions

What Terraform resources are commonly used for Azure Firewall?

Common resources include azurerm_firewall, azurerm_firewall_policy, and azurerm_firewall_policy_rule_collection_group. :contentReference[oaicite:13]{index=13}

Why do Terraform Azure Firewall examples often include Firewall Policy?

Because Microsoft recommends Firewall Policy as the preferred configuration model for Azure Firewall. :contentReference[oaicite:14]{index=14}

What subnet name does Azure Firewall require?

Azure Firewall requires a dedicated subnet named AzureFirewallSubnet, and Microsoft documents that it must be at least a /26. :contentReference[oaicite:15]{index=15}

What should I learn after Azure Firewall Terraform?

A good next step is DNAT rule collections, route table steering, IP Groups, multi-public-IP designs, and broader hub-and-spoke inspection patterns. :contentReference[oaicite:16]{index=16}

Summary

Azure Firewall Terraform is one of the best practical ways to understand how centralized network inspection becomes infrastructure as code. It teaches you how firewall instances, Firewall Policy, and rule collection groups fit together and how reusable Azure security foundations are built in real environments.

Official Azure documentation

These official references are useful if you want deeper platform details for Azure Firewall, Firewall Policy, and Terraform deployment patterns.