Azure Virtual Wan module to create a Virtual Wan with one Virtual Hub, an Azure Firewall and an Express Route Circuit with its Private Peering and VPN connections. An infrastructure example referenced in the Azure Cloud Adoption Framework is available here: raw.githubusercontent.com/microsoft/CloudAdoptionFramework/master/ready/enterprise-scale-architecture.pdf
This module use multiple sub-modules:
- Virtual Hub: Manage all Virtual Hub configurations
- Azure Firewall: Manage the creation of Azure Firewall in a Secured Hub
- Azure ExpressRoute: Manage ExpressRoute creation and configuration
- Azure VPN: Manage VPN connection in a Virtual Hub
Resource naming is based on the Microsoft CAF naming convention best practices. Use the parameter custom_<resource>_name
to override names.
We rely on the official Terraform Azure CAF naming provider to generate resource names.
Module version | Terraform version | OpenTofu version | AzureRM version |
---|---|---|---|
>= 8.x.x | Unverified | 1.8.x | >= 4.0 |
>= 7.x.x | 1.3.x | >= 3.0 | |
>= 6.x.x | 1.x | >= 3.0 | |
>= 5.x.x | 0.15.x | >= 2.0 | |
>= 4.x.x | 0.13.x / 0.14.x | >= 2.0 | |
>= 3.x.x | 0.12.x | >= 2.0 | |
>= 2.x.x | 0.12.x | < 2.0 | |
< 2.x.x | 0.11.x | < 2.0 |
If you want to contribute to this repository, feel free to use our pre-commit git hook configuration which will help you automatically update and format some files for you by enforcing our Terraform code module best-practices.
More details are available in the CONTRIBUTING.md file.
This module is optimized to work with the Claranet terraform-wrapper tool
which set some terraform variables in the environment needed by this module.
More details about variables set by the terraform-wrapper
available in the documentation.
locals {
vnets = [
{
vnet_name = "MyVnet1"
vnet_cidr = ["10.10.0.0/16"]
internet_security_enabled = true
},
{
vnet_name = "MyVnet2"
vnet_cidr = ["10.100.0.0/16"]
internet_security_enabled = false
}
]
subnets = [
{
name = "MySubnet1OnVnet1"
cidr = ["10.10.0.0/24"]
vnet_name = module.azure_virtual_network["MyVnet1"].virtual_network_name
},
{
name = "MySubnet2OnVnet1"
cidr = ["10.10.1.0/24"]
vnet_name = module.azure_virtual_network["MyVnet1"].virtual_network_name
},
{
name = "MySubnet1OnVnet2"
cidr = ["10.100.0.0/24"]
vnet_name = module.azure_virtual_network["MyVnet2"].virtual_network_name
},
{
name = "MySubnet2OnVnet2"
cidr = ["10.100.1.0/24"]
vnet_name = module.azure_virtual_network["MyVnet2"].virtual_network_name
}
]
}
module "azure_region" {
source = "claranet/regions/azurerm"
version = "x.x.x"
azure_region = var.azure_region
}
module "rg" {
source = "claranet/rg/azurerm"
version = "x.x.x"
location = module.azure_region.location
client_name = var.client_name
environment = var.environment
stack = var.stack
}
module "virtual_wan" {
source = "claranet/virtual-wan/azurerm"
version = "x.x.x"
client_name = var.client_name
environment = var.environment
stack = var.stack
location = module.azure_region.location
location_short = module.azure_region.location_short
resource_group_name = module.rg.resource_group_name
virtual_hub_address_prefix = "10.254.0.0/23"
firewall_enabled = true
express_route_enabled = true
express_route_private_peering_enabled = true
vpn_gateway_enabled = true
express_route_circuit_service_provider = "Equinix"
express_route_circuit_peering_location = "Paris"
express_route_circuit_bandwidth_in_mbps = 100
express_route_circuit_private_peering_primary_peer_address_prefix = "169.254.254.0/30"
express_route_circuit_private_peering_secondary_peer_address_prefix = "169.254.254.4/30"
express_route_circuit_private_peering_vlan_id = 1234
express_route_circuit_private_peering_peer_asn = 4321
express_route_circuit_private_peering_shared_key = "MySuperSecretSharedKey"
logs_destinations_ids = [
module.logs.log_analytics_workspace_id,
module.logs.logs_storage_account_id
]
peered_virtual_networks = [
for vnet in local.vnets : {
vnet_id = module.azure_virtual_network[vnet.vnet_name].virtual_network_id
internet_security_enabled = vnet.internet_security_enabled
# routing = {}
}
]
vpn_gateway_instance_0_bgp_peering_address = ["169.254.21.1"]
vpn_gateway_instance_1_bgp_peering_address = ["169.254.22.1"]
vpn_sites = [
{
name = "site1"
links = [
{
name = "site1-primary-endpoint"
ip_address = "20.20.20.20"
bgp = [
{
asn = 65530
peering_address = "169.254.21.2"
}
]
},
{
name = "site1-secondary-endpoint"
ip_address = "21.21.21.21"
bgp = [
{
asn = 65530
peering_address = "169.254.22.2"
}
]
}
]
}
]
vpn_connections = [
{
name = "cn-hub-to-site1"
site_name = "site1"
links = [
{
name = "site1-primary-link"
bandwidth_mbps = 200
bgp_enabled = true
ipsec_policy = {
dh_group = "DHGroup14"
ike_encryption_algorithm = "AES256"
ike_integrity_algorithm = "SHA256"
encryption_algorithm = "AES256"
integrity_algorithm = "SHA256"
pfs_group = "PFS14"
sa_data_size_kb = 102400000
sa_lifetime_sec = 3600
}
protocol = "IKEv2"
shared_key = "VeryStrongSecretKeyForPrimaryLink"
},
{
name = "site1-secondary-link"
bandwidth_mbps = 200
bgp_enabled = true
ipsec_policy = {
dh_group = "DHGroup14"
ike_encryption_algorithm = "AES256"
ike_integrity_algorithm = "SHA256"
encryption_algorithm = "AES256"
integrity_algorithm = "SHA256"
pfs_group = "PFS14"
sa_data_size_kb = 102400000
sa_lifetime_sec = 3600
}
protocol = "IKEv2"
shared_key = "VeryStrongSecretKeyForSecondaryLink"
}
]
}
]
}
module "azure_virtual_network" {
for_each = { for vnet in local.vnets : vnet.vnet_name => vnet }
source = "claranet/vnet/azurerm"
version = "x.x.x"
environment = var.environment
client_name = var.client_name
stack = var.stack
location = module.azure_region.location
location_short = module.azure_region.location_short
resource_group_name = module.rg.resource_group_name
custom_vnet_name = each.value.vnet_name
vnet_cidr = each.value.vnet_cidr
}
module "azure_network_subnet" {
source = "claranet/subnet/azurerm"
version = "x.x.x"
for_each = { for subnet in local.subnets : subnet.name => subnet }
environment = var.environment
client_name = var.client_name
stack = var.stack
location_short = module.azure_region.location_short
custom_subnet_name = each.key
resource_group_name = module.rg.resource_group_name
virtual_network_name = each.value.vnet_name
subnet_cidr_list = each.value.cidr
}
module "logs" {
source = "claranet/run/azurerm//modules/logs"
version = "x.x.x"
client_name = var.client_name
environment = var.environment
stack = var.stack
location = module.azure_region.location
location_short = module.azure_region.location_short
resource_group_name = module.rg.resource_group_name
}
Name | Version |
---|---|
azurecaf | ~> 1.2, >= 1.2.22 |
azurerm | ~> 3.73 |
null | ~> 3.0 |
Name | Source | Version |
---|---|---|
express_route | ./modules/express-route | n/a |
firewall | ./modules/firewall | n/a |
routing | ./modules/routing-intent | n/a |
vhub | ./modules/virtual-hub | n/a |
vpn | ./modules/vpn | n/a |
Name | Type |
---|---|
azurerm_virtual_wan.vwan | resource |
null_resource.routing_precondition | resource |
azurecaf_name.virtual_wan_caf | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
azure_firewall_as_next_hop_enabled | Whether use Azure Firewall as next hop or a NVA. | bool |
true |
no |
branch_to_branch_traffic_allowed | Boolean flag to specify whether branch to branch traffic is allowed | bool |
true |
no |
client_name | Name of client. | string |
n/a | yes |
custom_express_route_circuit_name | Custom ExpressRoute Circuit name | string |
null |
no |
custom_express_route_gateway_name | Custom ExpressRoute Gateway name | string |
null |
no |
custom_firewall_name | Custom Firewall's name | string |
null |
no |
custom_virtual_hub_name | Custom Virtual Hub's name | string |
null |
no |
custom_vpn_gateway_name | Custom name for the VPN Gateway | string |
null |
no |
custom_vwan_name | Custom Virtual Wan's name. | string |
null |
no |
default_tags_enabled | Option to enabled or disable default tags | bool |
true |
no |
environment | Name of application's environment. | string |
n/a | yes |
express_route_circuit_bandwidth_in_mbps | The bandwith in Mbps of the ExpressRoute Circuit being created on the Service Provider | number |
null |
no |
express_route_circuit_peering_location | ExpressRoute Circuit peering location. | string |
null |
no |
express_route_circuit_private_peering_peer_asn | Peer BGP ASN for ExpressRoute Circuit Private Peering | number |
null |
no |
express_route_circuit_private_peering_primary_peer_address_prefix | Primary peer address prefix for ExpressRoute Circuit private peering | string |
null |
no |
express_route_circuit_private_peering_secondary_peer_address_prefix | Secondary peer address prefix for ExpressRoute Circuit private peering | string |
null |
no |
express_route_circuit_private_peering_shared_key | Shared secret key for ExpressRoute Circuit Private Peering | string |
null |
no |
express_route_circuit_private_peering_vlan_id | VLAN Id for ExpressRoute Circuit | number |
null |
no |
express_route_circuit_service_provider | The name of the ExpressRoute Circuit Service Provider. | string |
null |
no |
express_route_custom_diagnostic_settings_name | Custom name of the diagnostics settings, name will be 'default' if not set. | string |
"default" |
no |
express_route_enabled | Enable or not ExpressRoute configuration | bool |
false |
no |
express_route_gateway_allow_non_virtual_wan_traffic | Whether the gateway accept traffic from non-Virtual WAN networks. | bool |
false |
no |
express_route_gateway_extra_tags | Extra tags for Express Route Gateway | map(string) |
{} |
no |
express_route_gateway_scale_unit | The number of scale unit with which to provision the ExpressRoute Gateway. | number |
1 |
no |
express_route_logs_categories | Log categories to send to destinations. | list(string) |
null |
no |
express_route_logs_destinations_ids | List of destination resources IDs for logs diagnostic destination for Express Route resource.Can be Storage Account , Log Analytics Workspace and Event Hub . No more than one of each can be set.If you want to specify an Azure EventHub to send logs and metrics to, you need to provide a formated string with both the EventHub Namespace authorization send ID and the EventHub name (name of the queue to use in the Namespace) separated by the ` |
` character. | list(string) |
null |
express_route_logs_metrics_categories | Metrics categories to send to destinations. | list(string) |
null |
no |
express_route_private_peering_enabled | Enable ExpressRoute Circuit Private Peering | bool |
false |
no |
express_route_sku | ExpressRoute SKU | object({ |
{ |
no |
extra_tags | Map of additional tags. | map(string) |
{} |
no |
firewall_availibility_zones | Availability zones in which the Azure Firewall should be created. | list(number) |
[ |
no |
firewall_custom_diagnostic_settings_name | Custom name of the diagnostics settings, name will be 'default' if not set. | string |
"default" |
no |
firewall_dns_servers | List of DNS servers that the Azure Firewall will direct DNS traffic to for the name resolution | list(string) |
null |
no |
firewall_enabled | Enable or not Azure Firewall in the Virtual Hub | bool |
true |
no |
firewall_extra_tags | Extra tags for Firewall resource | map(string) |
{} |
no |
firewall_logs_categories | Log categories to send to destinations. | list(string) |
null |
no |
firewall_logs_destinations_ids | List of destination resources IDs for logs diagnostic destination for Azure Firewall resource.Can be Storage Account , Log Analytics Workspace and Event Hub . No more than one of each can be set.If you want to specify an Azure EventHub to send logs and metrics to, you need to provide a formated string with both the EventHub Namespace authorization send ID and the EventHub name (name of the queue to use in the Namespace) separated by the ` |
` character. | list(string) |
null |
firewall_logs_metrics_categories | Metrics categories to send to destinations. | list(string) |
null |
no |
firewall_policy_id | ID of the Firewall Policy applied to this Firewall. | string |
null |
no |
firewall_private_ip_ranges | List of SNAT private CIDR IP ranges, or the special string IANAPrivateRanges , which indicates Azure Firewall does not SNAT when the destination IP address is a private range per IANA RFC 1918 |
list(string) |
null |
no |
firewall_public_ip_count | Number of public IPs to assign to the Firewall. | number |
1 |
no |
firewall_sku_tier | SKU tier of the Firewall. Possible values are Premium and Standard . |
string |
"Standard" |
no |
internet_routing_enabled | Whether force the internet routing through Azure Firewall or the NVA. | bool |
true |
no |
internet_security_enabled | Define internet security parameter in both VPN Connections and Virtual Hub Connections if set | bool |
null |
no |
location | Azure location. | string |
n/a | yes |
location_short | Short string for Azure location. | string |
n/a | yes |
logs_destinations_ids | List of destination resources IDs for logs diagnostic destination. Can be Storage Account , Log Analytics Workspace and Event Hub . No more than one of each can be set.If you want to specify an Azure EventHub to send logs and metrics to, you need to provide a formated string with both the EventHub Namespace authorization send ID and the EventHub name (name of the queue to use in the Namespace) separated by the ` |
` character. | list(string) |
n/a |
name_prefix | Prefix for generated resources names. | string |
"" |
no |
name_slug | Slug to use with the generated resources names. | string |
"" |
no |
name_suffix | Suffix for the generated resources names. | string |
"" |
no |
next_hop_nva_id | ID of the NVA used as next hop. | string |
null |
no |
office365_local_breakout_category | Specifies the Office365 local breakout category. Possible values include: Optimize , OptimizeAndAllow , All , None |
string |
"None" |
no |
peered_virtual_networks | Virtual Networks to peer with the Virtual Hub. | list(object({ |
[] |
no |
private_routing_enabled | Whether force the private routing through Azure Firewall or the NVA. | bool |
true |
no |
resource_group_name | Name of the application's resource group. | string |
n/a | yes |
routing_intent_enabled | Whether enable or not the routing intent. | bool |
false |
no |
stack | Name of application's stack. | string |
n/a | yes |
virtual_hub_address_prefix | The address prefix which should be used for this Virtual Hub. Cannot be smaller than a /24. A /23 is recommended by Azure | string |
n/a | yes |
virtual_hub_extra_tags | Extra tags for this Virtual Hub | map(string) |
{} |
no |
virtual_hub_routes | List of route blocks. next_hop_ip_address values can be azure_firewall or an IP address. |
list(object({ |
[] |
no |
virtual_hub_sku | The SKU of the Virtual Hub. Possible values are Basic and Standard |
string |
"Standard" |
no |
virtual_wan_extra_tags | Extra tags for this Virtual Wan | map(string) |
{} |
no |
virtual_wan_type | Specifies the Virtual Wan type. Possible Values include: Basic and Standard |
string |
"Standard" |
no |
vpn_connections | VPN Connections configuration | list(object({ |
[] |
no |
vpn_encryption_enabled | Boolean flag to specify whether VPN encryption is enabled | bool |
true |
no |
vpn_gateway_custom_diagnostic_settings_name | Custom name of the diagnostics settings, name will be 'default' if not set. | string |
"default" |
no |
vpn_gateway_enabled | Enable or not the deployment of a VPN Gateway and its Connections | bool |
false |
no |
vpn_gateway_extra_tags | Extra tags for the VPN Gateway | map(string) |
null |
no |
vpn_gateway_instance_0_bgp_peering_address | List of custom BGP IP Addresses to assign to the first instance | list(string) |
[] |
no |
vpn_gateway_instance_1_bgp_peering_address | List of custom BGP IP Addresses to assign to the second instance | list(string) |
[] |
no |
vpn_gateway_logs_categories | Log categories to send to destinations. | list(string) |
null |
no |
vpn_gateway_logs_destinations_ids | List of destination resources IDs for logs diagnostic destination for VPN Gateway resource.Can be Storage Account , Log Analytics Workspace and Event Hub . No more than one of each can be set.If you want to specify an Azure EventHub to send logs and metrics to, you need to provide a formated string with both the EventHub Namespace authorization send ID and the EventHub name (name of the queue to use in the Namespace) separated by the ` |
` character. | list(string) |
null |
vpn_gateway_logs_metrics_categories | Metrics categories to send to destinations. | list(string) |
null |
no |
vpn_gateway_routing_preference | Azure routing preference. Tou can choose to route traffic either via Microsoft network or via the ISP network through public Internet |
string |
"Microsoft Network" |
no |
vpn_gateway_scale_unit | The scale unit for this VPN Gateway | number |
1 |
no |
vpn_sites | VPN Site configuration | list(object({ |
[] |
no |
Name | Description |
---|---|
express_route_circuit_id | The ID of the ExpressRoute circuit |
express_route_circuit_service_key | The string needed by the service provider to provision the ExpressRoute circuit |
express_route_circuit_service_provider_provisioning_state | The ExpressRoute circuit provisioning state from your chosen service provider |
express_route_gateway_id | ID of the ExpressRoute gateway |
express_route_peering_azure_asn | ASN (Autonomous System Number) Used by Azure for BGP Peering |
firewall_id | ID of the firewall |
firewall_ip_configuration | IP configuration of the created firewall |
firewall_management_ip_configuration | Management IP configuration of the created firewall |
firewall_private_ip_address | Private IP address of the firewall |
firewall_public_ip | Public IP address of the Firewall |
virtual_hub_default_route_table_id | ID of the default route table in the Virtual Hub |
virtual_hub_id | ID of the virtual hub |
virtual_wan_id | ID of the Virtual Wan |
vpn_gateway_bgp_settings | BGP Settings of the VPN Gateway |
vpn_gateway_connections_ids | List of name and IDs of VPN gateway connections |
vpn_gateway_id | ID of the VPN Gateway |
- Azure Virtual Wan: docs.microsoft.com/en-us/azure/virtual-wan/virtual-wan-about
- Azure Firewall: docs.microsoft.com/en-us/azure/firewall/overview
- Azure Express Route Circuit: docs.microsoft.com/en-us/azure/expressroute/expressroute-circuit-peerings