Managing Azure Firewall with Terraform
Learn how to set up and manage Azure Firewall using Terraform, including network rules, application rules, and threat intelligence
Managing Azure Firewall with Terraform
Azure Firewall is a managed, cloud-based network security service that protects your Azure Virtual Network resources. This guide demonstrates how to set up and manage Azure Firewall using Terraform.
Video Tutorial
Learn more about managing Azure Firewall with Terraform in this comprehensive video tutorial:
Prerequisites
- Azure CLI configured with appropriate permissions
- Terraform installed (version 1.0.0 or later)
- Resource group created
- Understanding of networking and security concepts
Project Structure
terraform-azure-firewall/
├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│ └── firewall/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── policies/
└── rules.json
Firewall Configuration
Create modules/firewall/main.tf
:
# Firewall Policy
resource "azurerm_firewall_policy" "main" {
name = "${var.project_name}-policy"
resource_group_name = var.resource_group_name
location = var.location
sku = "Premium"
dns {
proxy_enabled = true
servers = ["168.63.129.16"]
}
threat_intelligence_mode = "Alert"
threat_intelligence_allowlist {
ip_addresses = ["192.168.1.0/24"]
fqdns = ["*.microsoft.com"]
}
insights {
enabled = true
default_log_analytics_workspace_id = var.log_analytics_workspace_id
retention_in_days = 30
}
intrusion_detection {
mode = "Alert"
signature_overrides {
id = "123456789"
state = "Alert"
}
traffic_bypass {
name = "bypass-rule"
protocol = "TCP"
description = "Test description"
destination_ports = ["80", "443"]
destination_addresses = ["192.168.1.1"]
source_addresses = ["192.168.1.2"]
}
}
identity {
type = "SystemAssigned"
}
tags = var.tags
}
# Firewall
resource "azurerm_firewall" "main" {
name = "${var.project_name}-fw"
location = var.location
resource_group_name = var.resource_group_name
sku_name = "AZFW_VNet"
sku_tier = "Premium"
firewall_policy_id = azurerm_firewall_policy.main.id
dns_servers = ["168.63.129.16"]
zones = ["1", "2", "3"]
threat_intel_mode = "Alert"
ip_configuration {
name = "configuration"
subnet_id = azurerm_subnet.firewall.id
public_ip_address_id = azurerm_public_ip.firewall.id
}
management_ip_configuration {
name = "management"
subnet_id = azurerm_subnet.management.id
public_ip_address_id = azurerm_public_ip.management.id
}
tags = var.tags
}
# Network Rules
resource "azurerm_firewall_policy_rule_collection_group" "network" {
name = "network-rules"
firewall_policy_id = azurerm_firewall_policy.main.id
priority = 100
network_rule_collection {
name = "network-rules"
priority = 100
action = "Allow"
rule {
name = "allow-rdp"
protocols = ["TCP"]
source_addresses = ["10.0.0.0/16"]
destination_addresses = ["192.168.1.0/24"]
destination_ports = ["3389"]
}
rule {
name = "allow-ssh"
protocols = ["TCP"]
source_addresses = ["10.0.0.0/16"]
destination_addresses = ["192.168.1.0/24"]
destination_ports = ["22"]
}
}
}
# Application Rules
resource "azurerm_firewall_policy_rule_collection_group" "application" {
name = "application-rules"
firewall_policy_id = azurerm_firewall_policy.main.id
priority = 200
application_rule_collection {
name = "app-rules"
priority = 100
action = "Allow"
rule {
name = "allow-microsoft"
protocols {
type = "Http"
port = 80
}
protocols {
type = "Https"
port = 443
}
source_addresses = ["10.0.0.0/16"]
destination_fqdns = ["*.microsoft.com"]
}
rule {
name = "allow-updates"
protocols {
type = "Https"
port = 443
}
source_addresses = ["10.0.0.0/16"]
destination_fqdns = ["*.ubuntu.com"]
terminate_tls = true
web_categories = ["ComputersAndTechnology"]
}
}
}
# NAT Rules
resource "azurerm_firewall_policy_rule_collection_group" "nat" {
name = "nat-rules"
firewall_policy_id = azurerm_firewall_policy.main.id
priority = 300
nat_rule_collection {
name = "nat-rules"
priority = 100
action = "Dnat"
rule {
name = "rdp-nat"
protocols = ["TCP"]
source_addresses = ["*"]
destination_address = azurerm_public_ip.firewall.ip_address
destination_ports = ["3389"]
translated_address = "10.0.0.4"
translated_port = "3389"
}
}
}
# IDPS Policy
resource "azurerm_firewall_policy_rule_collection_group" "idps" {
name = "idps-rules"
firewall_policy_id = azurerm_firewall_policy.main.id
priority = 400
network_rule_collection {
name = "idps-network"
priority = 100
action = "Allow"
rule {
name = "allow-http"
protocols = ["TCP"]
source_addresses = ["10.0.0.0/16"]
destination_addresses = ["*"]
destination_ports = ["80", "443"]
}
}
}
Network Configuration
- Virtual Network Setup
resource "azurerm_virtual_network" "main" {
name = "${var.project_name}-vnet"
address_space = ["10.0.0.0/16"]
location = var.location
resource_group_name = var.resource_group_name
subnet {
name = "AzureFirewallSubnet"
address_prefix = "10.0.1.0/24"
}
subnet {
name = "AzureFirewallManagementSubnet"
address_prefix = "10.0.2.0/24"
}
tags = var.tags
}
resource "azurerm_public_ip" "firewall" {
name = "${var.project_name}-fw-pip"
location = var.location
resource_group_name = var.resource_group_name
allocation_method = "Static"
sku = "Standard"
zones = ["1", "2", "3"]
tags = var.tags
}
resource "azurerm_public_ip" "management" {
name = "${var.project_name}-mgmt-pip"
location = var.location
resource_group_name = var.resource_group_name
allocation_method = "Static"
sku = "Standard"
zones = ["1", "2", "3"]
tags = var.tags
}
Route Configuration
- Route Table
resource "azurerm_route_table" "main" {
name = "${var.project_name}-rt"
location = var.location
resource_group_name = var.resource_group_name
route {
name = "ToInternet"
address_prefix = "0.0.0.0/0"
next_hop_type = "VirtualAppliance"
next_hop_in_ip_address = azurerm_firewall.main.ip_configuration[0].private_ip_address
}
tags = var.tags
}
resource "azurerm_subnet_route_table_association" "main" {
subnet_id = azurerm_subnet.main.id
route_table_id = azurerm_route_table.main.id
}
Monitoring Configuration
- Diagnostic Settings
resource "azurerm_monitor_diagnostic_setting" "firewall" {
name = "${var.project_name}-diag"
target_resource_id = azurerm_firewall.main.id
log_analytics_workspace_id = var.log_analytics_workspace_id
log {
category = "AzureFirewallApplicationRule"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
log {
category = "AzureFirewallNetworkRule"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
metric {
category = "AllMetrics"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
}
resource "azurerm_monitor_metric_alert" "firewall" {
name = "${var.project_name}-health-alert"
resource_group_name = var.resource_group_name
scopes = [azurerm_firewall.main.id]
description = "Alert when firewall health is degraded"
criteria {
metric_namespace = "Microsoft.Network/azureFirewalls"
metric_name = "FirewallHealth"
aggregation = "Average"
operator = "LessThan"
threshold = 100
}
action {
action_group_id = var.action_group_id
}
}
Best Practices
-
Performance
- Use Premium SKU
- Enable zones
- Configure DNS proxy
- Optimize rules
-
Security
- Enable threat intelligence
- Configure IDPS
- Implement logging
- Monitor traffic
-
High Availability
- Use zone redundancy
- Configure failover
- Monitor health
- Implement backup
-
Cost Optimization
- Optimize rules
- Use appropriate zones
Conclusion
You’ve learned how to set up and manage Azure Firewall using Terraform. This setup provides:
- Network security
- Application protection
- Threat intelligence
- Traffic monitoring
Remember to:
- Monitor firewall health
- Review security rules
- Update policies
- Maintain configurations