Managing Azure Virtual WAN with Terraform
Learn how to set up and manage Azure Virtual WAN using Terraform, including hubs, connections, and routing
Managing Azure Virtual WAN with Terraform
Azure Virtual WAN is a networking service that provides optimized and automated branch-to-branch connectivity through Azure. This guide demonstrates how to set up and manage Virtual WAN using Terraform.
Video Tutorial
Learn more about managing Azure Virtual WAN 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 concepts
Project Structure
terraform-azure-virtualwan/
├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│ └── virtualwan/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── configs/
└── routing.json
Virtual WAN Configuration
Create modules/virtualwan/main.tf
:
# Virtual WAN
resource "azurerm_virtual_wan" "main" {
name = "${var.project_name}-vwan"
resource_group_name = var.resource_group_name
location = var.location
type = "Standard"
disable_vpn_encryption = false
allow_branch_to_branch_traffic = true
office365_local_breakout_category = "OptimizeAndAllow"
tags = var.tags
}
# Virtual Hub
resource "azurerm_virtual_hub" "main" {
name = "${var.project_name}-hub"
resource_group_name = var.resource_group_name
location = var.location
virtual_wan_id = azurerm_virtual_wan.main.id
address_prefix = "10.0.0.0/24"
sku = "Standard"
route {
address_prefixes = ["10.0.1.0/24"]
next_hop_ip_address = "10.0.0.4"
}
tags = var.tags
}
# VPN Gateway
resource "azurerm_vpn_gateway" "main" {
name = "${var.project_name}-vpngw"
location = var.location
resource_group_name = var.resource_group_name
virtual_hub_id = azurerm_virtual_hub.main.id
scale_unit = 2
bgp_settings {
asn = 65515
peer_weight = 0
}
tags = var.tags
}
# ExpressRoute Gateway
resource "azurerm_express_route_gateway" "main" {
name = "${var.project_name}-ergw"
resource_group_name = var.resource_group_name
location = var.location
virtual_hub_id = azurerm_virtual_hub.main.id
scale_units = 2
tags = var.tags
}
# Virtual Network Connection
resource "azurerm_virtual_hub_connection" "main" {
name = "${var.project_name}-connection"
virtual_hub_id = azurerm_virtual_hub.main.id
remote_virtual_network_id = azurerm_virtual_network.spoke.id
routing {
associated_route_table_id = azurerm_virtual_hub_route_table.main.id
propagated_route_table {
labels = ["default"]
route_table_ids = [azurerm_virtual_hub_route_table.main.id]
}
static_vnet_route {
name = "default"
address_prefixes = ["10.0.0.0/16"]
next_hop_ip_address = "10.0.0.4"
}
}
internet_security_enabled = true
}
# Route Table
resource "azurerm_virtual_hub_route_table" "main" {
name = "${var.project_name}-rt"
virtual_hub_id = azurerm_virtual_hub.main.id
labels = ["default"]
route {
name = "default"
destinations_type = "CIDR"
destinations = ["0.0.0.0/0"]
next_hop_type = "ResourceId"
next_hop = azurerm_firewall.main.id
}
}
# Firewall
resource "azurerm_firewall" "main" {
name = "${var.project_name}-fw"
location = var.location
resource_group_name = var.resource_group_name
sku_name = "AZFW_Hub"
sku_tier = "Premium"
virtual_hub {
virtual_hub_id = azurerm_virtual_hub.main.id
public_ip_count = 1
}
firewall_policy_id = azurerm_firewall_policy.main.id
tags = var.tags
}
# Firewall Policy
resource "azurerm_firewall_policy" "main" {
name = "${var.project_name}-policy"
resource_group_name = var.resource_group_name
location = var.location
sku = "Premium"
threat_intelligence_mode = "Alert"
dns {
proxy_enabled = true
servers = ["168.63.129.16"]
}
insights {
enabled = true
default_log_analytics_workspace_id = var.log_analytics_workspace_id
retention_in_days = 30
}
intrusion_detection {
mode = "Alert"
}
tags = var.tags
}
# Secure Hub
resource "azurerm_virtual_hub_security_partner_provider" "main" {
name = "${var.project_name}-security"
resource_group_name = var.resource_group_name
location = var.location
virtual_hub_id = azurerm_virtual_hub.main.id
security_provider_name = "ZScaler"
tags = var.tags
}
# P2S VPN Gateway
resource "azurerm_point_to_site_vpn_gateway" "main" {
name = "${var.project_name}-p2s"
location = var.location
resource_group_name = var.resource_group_name
virtual_hub_id = azurerm_virtual_hub.main.id
scale_unit = 2
vpn_server_configuration_id = azurerm_vpn_server_configuration.main.id
connection_configuration {
name = "connection-config"
vpn_client_address_pool {
address_prefixes = ["172.16.0.0/24"]
}
}
tags = var.tags
}
# VPN Server Configuration
resource "azurerm_vpn_server_configuration" "main" {
name = "${var.project_name}-vpn-config"
resource_group_name = var.resource_group_name
location = var.location
vpn_authentication_types = ["AAD"]
azure_active_directory_authentication {
audience = "41b23e61-6c1e-4545-b367-cd054e0ed4b4"
issuer = "https://sts.windows.net/${data.azurerm_client_config.current.tenant_id}/"
tenant = "https://login.microsoftonline.com/${data.azurerm_client_config.current.tenant_id}"
}
}
Monitoring Configuration
- Diagnostic Settings
resource "azurerm_monitor_diagnostic_setting" "virtualwan" {
name = "${var.project_name}-diag"
target_resource_id = azurerm_virtual_wan.main.id
log_analytics_workspace_id = var.log_analytics_workspace_id
log {
category = "AllLogs"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
metric {
category = "AllMetrics"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
}
# Virtual WAN Alerts
resource "azurerm_monitor_metric_alert" "vpn_bandwidth" {
name = "${var.project_name}-vpn-bandwidth-alert"
resource_group_name = var.resource_group_name
scopes = [azurerm_vpn_gateway.main.id]
description = "Alert when VPN bandwidth is high"
criteria {
metric_namespace = "Microsoft.Network/vpnGateways"
metric_name = "AverageBandwidth"
aggregation = "Average"
operator = "GreaterThan"
threshold = 800
}
action {
action_group_id = var.action_group_id
}
}
resource "azurerm_monitor_metric_alert" "er_bandwidth" {
name = "${var.project_name}-er-bandwidth-alert"
resource_group_name = var.resource_group_name
scopes = [azurerm_express_route_gateway.main.id]
description = "Alert when ExpressRoute bandwidth is high"
criteria {
metric_namespace = "Microsoft.Network/expressRouteGateways"
metric_name = "ErGatewayConnectionBitsInPerSecond"
aggregation = "Average"
operator = "GreaterThan"
threshold = 800000000
}
action {
action_group_id = var.action_group_id
}
}
Best Practices
-
Architecture
- Plan hub locations
- Size appropriately
- Configure routing
- Enable security
-
Performance
- Use Standard SKU
- Monitor bandwidth
- Optimize routing
- Scale resources
-
Security
- Enable Firewall
- Configure policies
- Monitor traffic
- Implement logging
-
Cost Optimization
- Choose right SKU
- Monitor usage
- Optimize connections
- Review metrics
Conclusion
You’ve learned how to set up and manage Azure Virtual WAN using Terraform. This setup provides:
- Global connectivity
- Branch networking
- Security services
- Optimized routing
Remember to:
- Monitor performance
- Review security
- Update configurations
- Maintain connections