Deploying VPN gateways and connections, using Azure Resource Manager

Edit: I wrote a “part 2” where I explain how it’s done with PowerShell, you can find it here: https://cloudpuzzles.net/2015/10/deploying-vpn-gateways-and-connections-using-azure-resource-manager-part-2/

Last week at SCU a bunch of us joined Kristian Nese in his Azure Resource Manager (ARM) session and discussed ARM templates and how to build them. During the session we talked about the Network Gateway provider which lets us manage VPN gateways and connections. Since this is not yet possible through the portal (portal.azure.com) on an ARM based network, we were not sure if the provider was released yet, or even finished.

After I got home I had the time to research this, and it does exist. The API contains 3 resources:

  • Connections
    • Used to create the connection between your sites
  • Local Network Gateways
    • This is where you specify your local network settings
  • Virtual Network Gateways
    • This is used to create the gateway on your virtual network in Azure

Let’s walk through the process of creating a template that adds all of the above.

Pre-requisites:

  • A virtual network in Azure
  • A local gateway, this could also be another Azure network

First of all, you will need a public IP for your gateway, this can be requested through the Microsoft.Network/publicIPAddresses resource. Like with other resources, you need to specify some settings for this (some of which are standard for each resource, the first 4 in this case):

  • Api-version
  • Type
  • Name
  • Location
  • And a property of ‘publicIPAllocationMethod’

For this example, it looks like this:

[text]
{
"apiVersion": "[variables(‘api-version’)]",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[parameters(‘gatewayPublicIPName’)]",
"location": "[parameters(‘location’)]",
"properties": {
"publicIPAllocationMethod": "Dynamic"
}
}
[/text]

Notice that I’ve used parameters so I don’t have to hardcode names etc in the template, and it’s easier to reference later in the template.

Next up, we want a local network gateway, which contains the IP address and subnet of the other end of the VPN tunnel. Using the Microsoft.Network/localNetworkGateways resource we can do this. Again some settings are needed:

  • localNetworkAddressSpace
    • This is the network subnets you are using locally
  • gatewayIpAddress
    • The public IP of your VPN device

The code:

[text]
{
"apiVersion": "[variables(‘api-version’)]",
"type": "Microsoft.Network/localNetworkGateways",
"name": "[parameters(‘localGatewayName’)]",
"location": "[parameters(‘location’)]",
"properties": {
"localNetworkAddressSpace": {
"addressPrefixes": [
"[parameters(‘localAddressPrefix’)]"
]
},
"gatewayIpAddress": "[parameters(‘localGatewayIpAddress’)]"
}
}
[/text]

Now we will create a virtual network gateway by using the Microsoft.Network/virtualNetworkGateways resource. This one is a bit more tricky since it depends on the public IP to be created first. The settings:

  • dependsOn
    • This tells Azure to deploy the public IP before the gateway – and I’m also using it for the network
  • vpnType
    • RouteBased or PolicyBased routing
  • gatewayType
    • This need to be ‘VPN’
  • enableBgp
    • True or false, in my case it’s false (BGP is only used for ExpressRoute connections)
  • Properties:
    • ipConfigurations
      • privateIPAllocationMethod
        • Dynamic or static – dynamic for me
      • Subnet
        • The subnet for your gateway, should at least be a /29 in your virtual network
      • publicIPAddress
        • Here we’ll reference the public IP we created before
    • Name
      • A name for the configuration

Once again, here is my configuration:

[text]
{
"apiVersion": "[variables(‘api-version’)]",
"type": "Microsoft.Network/virtualNetworkGateways",
"name": "[parameters(‘gatewayName’)]",
"location": "[parameters(‘location’)]",
"dependsOn": [
"[concat(‘Microsoft.Network/publicIPAddresses/’, parameters(‘gatewayPublicIPName’))]",
"[concat(‘Microsoft.Network/virtualNetworks/’, parameters(‘virtualNetworkName’))]"
],
"properties": {
"ipConfigurations": [
{
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[variables(‘gatewaySubnetRef’)]"
},
"publicIPAddress": {
"id": "[resourceId(‘Microsoft.Network/publicIPAddresses’,parameters(‘gatewayPublicIPName’))]"
}
},
"name": "vnetGatewayConfig"
}
],
"gatewayType": "Vpn",
"vpnType": "[parameters(‘vpnType’)]",
"enableBgp": false
}
}
[/text]

As you might notice, I am using dependsOn to make sure the public IP and network is in place. This is done by using concat to reference “Microsoft.Network/publicIPAddresses/<public ip name from my parameter>” and the same for my network.

For the subnet and publicIPAddress properties I am referencing the ‘id’ of them. In my final template you can see how I did that using variables.

Finally we need to add a connection between the local and virtual network gateways by using Microsoft.Network/connections resource:

  • dependsOn
    • Again we need to have some other resources in place first
  • Properties:
    • virtualNetworkGateway1
    • localNetworkGateway2
    • connectionType
      • IPSec
    • routingWeight
      • 10 in my case
    • sharedKey
      • I’m passing this as a parameter

The code:

[text]
{
"name": "[parameters(‘connectionName’)]",
"apiVersion":"2015-06-15",
"type": "Microsoft.Network/connections",
"location": "[parameters(‘location’)]",
"dependsOn": [
"[concat(‘Microsoft.Network/virtualNetworkGateways/’, parameters(‘gatewayName’))]",
"[concat(‘Microsoft.Network/localNetworkGateways/’, parameters(‘localGatewayName’))]"
],
"properties": {
"virtualNetworkGateway1": {
"id": "[resourceId(‘Microsoft.Network/virtualNetworkGateways’, parameters(‘GatewayName’))]"
},
"localNetworkGateway2": {
"id": "[resourceId(‘Microsoft.Network/localNetworkGateways’, parameters(‘localGatewayName’))]"
},
"connectionType": "IPsec",
"routingWeight": 10,
"sharedKey": "[parameters(‘sharedKey’)]"
}
}
[/text]

My full template for Azure Resource Manager gateways can be found on GitHub. It contains parameters and variables as mentioned. When I’ve tested it a bit more I’ll submit it for the ARM template collection.
To deploy it by using PowerShell, create a resource group and run the deployment:

[powershell]
New-AzureResourceGroup -Name gatewaydemo -Location "West Europe"
New-AzureResourceGroupDeployment -ResourceGroupName gatewaydemo -TemplateFile .vnet-withgateway2.json
[/powershell]

You can also specify the parameters I’ve put in the template. PowerShell loads these as you specify the template file.

It can take a while (usually 30 minutes) to deploy a gateway, so sit back and relax. The end result should look something like this:

armgw1

4 comments

  1. Great article, small issue i found; the section that you explain ‘vpnType’ you mention that this is ‘Dynamic’ or ‘Static’ routing, however this is referring to ‘RouteBased’ or ‘PolicyBased’ routing.

    Regards
    Ben Pearce

    Like

    1. You are correct, they changed the parameters to RouteBased and PolicyBased recently. I have an updated post coming up soon, where I’ll note it. Thanks for pointing out!

      Like

  2. Jesper…have you tried this recently? I’m attempting to create a gateway using essentially cut and paste from this and getting “Invalid Template”. Does this still work?

    Like

    1. Hi Eric,

      “Static” and “Dynamic” has been replaced with “PolicyBased” and “RouteBased” since I wrote this post. I have updated the post and template on GitHub now.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s