Get started with Virtual WAN deployments using ARM Templates
Deploying Azure Virtual WAN using ARM templates can be frustrating and it takes some time before you get a hang on it. There are a lot of dependencies between resources and you need to make sure that everything is deployed in the correct order, and also allow both the Virtual Hub and routing to reach succeeded state before throwing more things at it. In this post I will guide you through some of the different resource types to help you with your Virtual WAN deployment.
Note: This post explains first time deployments only, to make the template reusable to be able to update the Virtual WAN you have to add some logic to it. But that is something we can cover in a separate post, let’s focus on getting that VWAN deployed!
For ARM templates, you must always specify an API version for every resource type you define in your template. The API version corresponds to a version of REST API operations that are released by the resource provider e.g
Microsoft.Network. When a resource provider enables new features a new API Version is released. Sometimes a new API Version just enables a couple of new features, and you can just change it to the most recent version and your template will still function properly without any other modifications. But that’s not always the case, in some cases a new API Version completely changes how some resources are defined and deployed. When it comes to Azure Virtual WAN the change from API Version
2020-05-01 equals a couple of breaking changes. If you see an example template using API Version
2020-04-01 you can’t just update the API Version and expect a successful deployment.
The following things are good to know when it comes to
Microsoft.Network API Versions and Virtual WAN:
2020-04-01- Do not use this version (or earlier) if you´re building a new template, you will have to do a lot of modifications when upgrading to a newer version. And you can not use Virtual Hub Route tables.
2020-05-01- With this API Version a couple of major changes where introduced:
Microsoft.Network/virtualHubshas changed a lot. Things that in earlier versions was declared as properties inside the Virtual Hub are now child resources, the most common of them
Microsoft.Network/firewallPoliciesAzure Firewall policies have been updated to support Rule Collection Groups
Microsoft.Network/firewallPolicies/ruleCollectionGroups. This completely change how Firewall Policies are defined.
2020-06-01- Latest API Version
Breaking down the template - Resource by resource
Lets break down a Virtual WAN with a secure virtual hub deployment into pieces. A complete ARM template for reference can be found in my Azure Virtual WAN Playground Repo. The examples in this post are based on that repository, check it out if you want to skip this article and dive into the full deployment at once. This article will focus on the following resource types used in a Virtual WAN:
- Virtual WAN
- Virtual Hub
- Azure Firewall Policy
- Azure Firewall
- Virtual Hub Route Tables
- Updating defaultRouteTable
- Custom Route Table
- Hub Virtual Network Connections
- VPN Sites
- VPN Gateway
- VPN Connection
Note: The code snippets in this post are examples on how you can define the resources in your ARM template. If you create a template using copy/paste and these examples it might not work as expected. See the full example in the VWAN Playground Repo to get the full picture (you can also look at a 💪Bicep verison of the template!). I’m also not covering all available properties for each resource type. For a full list of properties see ARM Template Reference. At last I’ve decided to remove the
dependsOn property from the code snippets to reduce the code, and just added a simple dependsOn note above the examples to explain what other resources it depends on. For some resources I’ve just added an extra dependsOn just to allow the Virtual Hub to fully update and reach a succeeded state. Sometimes if you throw to much at it you will end up with conflict errors or badRequests because the Virtual Hub is not back in a succeeded state after a previous operation.
There´s not much to say about the
Microsoft.Network/virtualWans resource, it’s pretty straight forward. You create the resource specifying just a couple of properties:
type- Specifies the Virtual WAN SKU, allowed values are
disableVpnEncryption- Property to disable VPN Encryption.
allowBranchToBranchTraffic- Specifies if branches should be allowed to communicate through the Virtual WAN. Important to remember that User VPN counts as a branch, if you want to allow users connected to VPN to reach an On-Premises site, this must be enabled.
office365LocalBreakoutCategory- Specify Office 365 local breakout category - Allowed values
Next up is the Virtual Hub, just like the Virtual WAN resource it’s a simple one. The properties specified are:
name- Name of the Virtual Hub
addressPrefix- The address space used by the Virtual Hub, minimum address space is /24.
virtualWan- Resource ID to the Virtual WAN.
dependsOn: Virtual WAN
Time to prepare for Azure Firewall (Secure Virtual Hub) by creating an Azure Firewall Policy. I like to specify the Azure Firewall Policy and Rule Collection Groups as separate resources in the template because it simplifies the template, especially when using multiple Rule Collection Groups. It keeps the Firewall properties separated from the Firewall Rules which is quite neat.
name- Firewall Policy Name
threatIntelMode- The operation mode for Threat Intelligence. -
threatIntelWhitelist- Threat intelligence whitelist object
ipAddresses- List of IP Addresses to whitelist from Threat Intelligence
fqdns- List of FQDNS to whitelist from Threat Intelligence
dnsSettings- Azure Firewall DNS Settings
servers- List of Custom DNS Servers
enableProxy- Property to enable DNS Proxy
requireProxyForNetworkRules- Using FQDNs in Network Rules are supported when set to true
Time to add some rules to the Firewall Policy, I’ll keep it simple for now with a single Rule Collection Group containing a single Application Rule. Note that the properties defined in the rules object will differ depending on the rule type you use (Network, Application or DNAT).
name- Name of the rule collection group
priority- Rule Collection Group priority.
ruleCollections- Group of Firewall Policy rule collections
FirewallPolicyFilterRuleCollectionfor application and network collections or
FirewallPolicyNatRuleCollectionfor DNAT collections.
name- Name of the Rule Collection
priority- Rule Collection Priority
action- Rule Collection Action
type- Allow or Deny
rules- Group of Rules (example below shows an application rule)
ruleType- ApplicationRule, NetworkRule or NatRule
name- Name of the Rule (must be unique within a rule collection)
sourceAddresses- Source IP Address or range
sourceIpGroups- Source IP Group (resource ID)
protocols- Protocols used by the Application Rule
port- Port number
protocolType- Protocol type, http, https, mssql
targetFqdns- Target FQDNs Object
fqdnTags- FQDN Tags Object
dependsOn: Azure Firewall Policy
The Azure Firewall resource deployed in a Virtual Hub is almost the same as when deployed in a Virtual Network. There are some key differences:
- The SKU property must be specified with the name
In a VNet deployed Firewall there is a
ipConfigurationsproperty object where the IP Configurations are set. The first IP Configuration object in a VNet deployed Azure Firewall have two properties,
subnetthat contains the resource ID to the AzureFirewallSubnet and the
publicIPAddressproperty that contains the resource ID to the Public IP address to use with the Azure Firewall. Additional Public IPs are assigned by adding additional
subnetproperty which is only allowed in the first IP Configuration declared.
- In a Secure Virtual Hub we don’t have the
ipConfigurationsproperty available. Since the Virtual WAN Hub is a Microsoft Managed VNet we can’t access the AzureFirewallSubnet. When it comes to the Public IP addresses we can’t decide which ones to use, the only thing we can do is specify the Public IP Count to control the number of IP Addresses allocated to the Firewall. (I really hope that we will be able to allocate IPs from Public IP Prefixes to a Secure Virtual Hub Firewall in the future!). So what do we have instead of the
- We have a new property called
virtualHubthis is where we specify the resource ID of the Virtual WAN to associate the Azure Firewall to.
- There is also a
hubIPAddressesproperty where we can specify the number of Public IPs ot use by setting the
- We have a new property called
Lets take a look at the Azure Firewall Resource:
name- Name of the Azure Firewall resource
sku- Azure Firewall SKU Object
name- Name of the Azure Firewall SKU -
tier- Standard or Premium (not available to deploy as an ordinary user, you will get an error. I guess that a private preview is happening here)
virtualHub- Virtual Hub Resource ID
hubIPAddresses- Hub IP Addresses Object
publicIPs- Public IP Property
count- Public IP count, the number of IPs to associate with the Firewall
firewallPolicy- Firewall Policy Resource ID
dependsOn: Virtual WAN, Virtual Hub, Azure Firewall Policy
Now that the Azure Firewall is deployed it’s time to get some routing in-place. I want to route all traffic from On-Premises locations to my Azure VNets through Azure Firewall. And for my VNets in Azure I want to send outbound internet traffic and traffic towards On-Premises through Azure Firewall. In order to do that I need a new Custom Hub Route Table
RT_VNet that I will associate with all VNet Connections and add a static route to the
defaultRouteTable used by all branches. Custom Route Tables for branches are not available, all branches are associated with and are propagating routes to the
name- Name of the Route Table, since it’s a child resource to the Virtual Hub make sure that the correct segments are used.
routes- List of all routes to add
name- Route name
destinationType- The type of destination,
destination- List of destinations
nextHopType- Next hop type,
nextHop- Next hop resource ID (Azure Firewall or VNet Connection)
labels- List of labels associated with this route table.
defaultRouteTable is created with the Virtual Hub and are used by all branch connections by default. I want to make sure that all traffic between On-Premises and Azure is routed through Azure Firewall and to achieve that a static route must be added. I like to reserve a CIDR block dedicated for a specific Azure region. I use this for the Virtual Hub (or Virtual Network Hub for a traditional topology) and all connected VNets in the specified region. This simplifies routing between regions and regional firewalls. In this example I add a static route with destination 10.0.0.0/16 and next hop Azure Firewall.
dependsOn: Virtual Hub, Azure Firewall
This is what the RT_VNet Hub Route Table looks like. One single static route for destination 0.0.0.0/0 has been added to send all traffic to Azure Firewall, the route table is also tagged with the label
VNet. Labels can be used to logically group route tables. I’ve added a dependsOn to the defaultRouteTable to avoid a conflict during deployment, the Virtual WAN hub does not like to run multiple routing changes at the same time.
dependsOn: Virtual Hub, Azure Firewall, defaultRouteTable
Virtual Network Connections are created as a child resource to the Virtual Hub. A Virtual Network connection is in fact just VNet peering between the Virtual Hub and a spoke VNet and its routing configuration.
name- Name of the VNet Connection, since it’s a child resource make sure that the correct segments are used.
remoteVirtualNetwork- Resource ID of the VNet to peer with the Virtual Hub
enableInternetSecurity- This is a very important property when using custom route tables sending all internet traffic to Azure Firewall. Without this property the 0.0.0.0/0 route will not show up as an effective route on resources in the peered VNet.
routingConfiguration- Object with all routing configuration for the VNet connection.
associatedRouteTable- Resource ID to the associated route table for the VNet Connection. This is the route table that the VNet will learn all its routes from.
propagatedRouteTables- Object with configuration on route tables where the VNet connection are propagating routes.
labels- This is a really cool feature. The VNet connection will propagate routes to all route tables in the Virtual WAN that have the same label as defined in this property.
ids- Resource IDs to all Route Tables that the VNet Connection should propagate routes.
dependsOn: Virtual Hub, Azure Firewall, Hub Route Table (RT_VNet)
Time to define all physical locations to where we want to connect using site-to-site VPN. VPN Sites are added to the Virtual WAN Resource. In this example BGP is being used. A VPN Site is very much like a Local Network Gateway in a traditional VNet topology.
name- Name of VPN Site
addressSpace- IP address space that is located on your on-premises site
addressPrefixes- Array with all IP Prefixes
bgpProperties- BGP Properties object.
asn- AS Number for the physical location
bgpPeeringAddress- BGP Peer IP Address (this is not the public IP of the VPN Device)
peerWeight- Peer Weight
deviceProperties- Device Properties Information. This is just pure metadata used by the Azure Team better understand your environment to add additional optimization possibilities in the future, or to help you troubleshoot.
deviceVendor- Name of the Device Vendor (for example: Citrix, Cisco, Barracuda)
deviceModel- Device model name
linkSpeedInMbps- Link speed in Mbps
ipAddress- VPN Device public IP Address
virtualWan- Virtual WAN Resource ID.
dependsOn: Virtual WAN
Time for the VPN Gateway, a quite simple resource. I don’t define any VPN Connections in the VPN Gateway resource since it will be a mess with multiple tunnels.
name- Name of VPN Gateway
virtualHub- Resource ID of the Virtual Hub where the VPN Gateway should be created.
bgpSettings- BGP Settings object
asn- VPN Gateway AS Number
vpnGatewayScaleUnit- Number of VPN Gateway Scale Units
dependsOn: Virtual WAN, Virtual Hub, Azure Firewall
Time to connect the VPN Gateway with the VPN Site. This is usually a quite simple resource to declare, but there are a lot of other properties available that could be used. An example is
ipsecPolicies that is used to configure a custom IPsec policy.
name- Name of VPN Connection. It’s a child resource, make sure that the segments are correct.
connectionBandwidth- Connected site bandwidth
enableBgp- Property to enable BGP
sharedkey- Pre-shared Key for the site-to-site connection. If no PSK is provided a key will automatically be generated by Azure.
remoteVpnSite- Resource ID to the VPN Site to connect to.
dependsOn: Virtual WAN, Virtual Hub, Azure Firewall, VPN Gateway
That’s all for this post! There are some other resources available for Virtual WAN as well like Express Route Gateway, User VPN Gateway, User VPN Configuration etc. but that´s something we can save for another time. I hope that the information in this post is enough to get you started with your Azure Virtual WAN deployments.