In this part of the blog series, I want to create the VPN connection from Azure to my on-premises lab environment.
As I did in the last part, I will create a new branch in Github for my work. I am doing this to ensure that my main branch is always running without errors. I will call this new branch for “VPN”.
The first step is to create the template file for the Virtual Network Gateway in Azure. I found the documentation for this item here . As with some of the other resources, there are a lot of settings that I can use, but not all of them are needed. I adapted the template for my needs, and it now looks like the code below. I have saved this file as “VirtualNetworkGateway.bicep” and placed it under the same template folder as the virtual network.
param virtualNetworkGatewayName string
param rgName string
param location string = resourceGroup().location
param sku string
@allowed([
'Vpn'
'ExpressRoute'
])
param gatewayType string = 'Vpn'
@allowed([
'RouteBased'
'PolicyBased'
])
param vpnType string = 'RouteBased'
param VirtualNetworkName string
param SubnetName string = 'GatewaySubnet'
param PublicIpAddressName string
param enableBGP bool = false
resource PublicIpAddressName_resource 'Microsoft.Network/publicIPAddresses@2021-02-01' = {
name: PublicIpAddressName
location: location
properties: {
publicIPAllocationMethod: 'Dynamic'
}
}
resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2021-02-01' = {
name: virtualNetworkGatewayName
location: location
properties: {
gatewayType: gatewayType
ipConfigurations: [
{
name: 'default'
properties: {
privateIPAllocationMethod: 'Dynamic'
subnet: {
id: resourceId(rgName, 'Microsoft.Network/virtualNetworks/subnets', VirtualNetworkName, SubnetName)
}
publicIPAddress: {
id: resourceId(rgName, 'Microsoft.Network/publicIPAddresses', PublicIpAddressName)
}
}
}
]
vpnType: vpnType
enableBgp: enableBGP
sku: {
name: sku
tier: sku
}
}
dependsOn: [
PublicIpAddressName_resource
]
}
output vngid string = virtualNetworkGateway.id
The code above contains a new expression called “@Allowed”, this expression allows me to control which values are approved for the parameter listed below this expression. This is a great way to ensure that the values passed on are correct when you have a set of approved values. To create a Virtual Network Gateway, I need to create a public IP address, so I have a resource for that, and I have made the resource for the gateway dependent on this public IP address. I now need to create the execution file that will use this template. I will call this file “DeployVPN.bicep”. Unlike the virtual network deployment file, I have chosen to add all the values into the module section instead of creating parameters and variables for them. I have pasted in the code for the deployment file below.
module virtualNetworkGateway './Templates/VirtualNetworkGateway.bicep' = {
name: 'VirtualNetworkGateway'
params: {
enableBGP: false
gatewayType: 'Vpn'
location: resourceGroup().location
PublicIpAddressName: 'pip-vng-sharedservices-001'
rgName: resourceGroup().name
sku: 'Basic'
SubnetName: 'GatewaySubnet'
virtualNetworkGatewayName: 'vng-sharedservices-001'
VirtualNetworkName: 'vnet-sharedservices-001'
vpnType: 'RouteBased'
}
}
Next, I will create the template for the Local Network Gateway and place it in the same folder as the others. The documentation on Local Network Gateways can be found here . I have pasted my template code below.
param localNetworkGatewayName string
param location string = resourceGroup().location
param gatewayIpAddress string
param addressPrefixes array = []
resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2021-02-01' = {
name: localNetworkGatewayName
location: location
properties: {
localNetworkAddressSpace: {
addressPrefixes: addressPrefixes
}
gatewayIpAddress: gatewayIpAddress
}
}
output lngid string = localNetworkGateway.id
The last bit of the VPN connection is what Microsoft calls Connection. This is what ties the Virtual Network Gateway together with the Local Network Gateway. The documentation for the connection can be found here . I have pasted in my code below. '
param connectionName string
param location string = resourceGroup().location
param connectionType string
param virtualNetworkGatewayId string
param enableBgp bool
param sharedKey string
param localNetworkGatewayId string
resource connectionName_resource 'Microsoft.Network/connections@2021-02-01' = {
name: connectionName
location: location
properties: {
connectionType: connectionType
virtualNetworkGateway1: {
id: virtualNetworkGatewayId
properties: {
}
}
enableBgp: enableBgp
sharedKey: sharedKey
localNetworkGateway2: {
id: localNetworkGatewayId
properties: {
}
}
}
dependsOn: []
}
With all the templates in place, I can update the execution code to include the Local Network Gateway and the Connection. Below is my updated execution code. I did obscure my public IP address and preshared key for security’s sake.
module virtualNetworkGateway './Templates/VirtualNetworkGateway.bicep' = {
name: 'VirtualNetworkGateway'
params: {
enableBGP: false
gatewayType: 'Vpn'
location: resourceGroup().location
PublicIpAddressName: 'pip-vng-sharedservices-001'
rgName: resourceGroup().name
sku: 'Basic'
SubnetName: 'GatewaySubnet'
virtualNetworkGatewayName: 'vng-sharedservices-001'
VirtualNetworkName: 'vnet-bicep-sharedservices-001'
vpnType: 'RouteBased'
}
}
module localNetworkGateway './Templates/LocalNetworkGateway.bicep' = {
name: 'LocalNetworkGateway'
params: {
addressPrefixes: [
'192.168.1.0/24'
'192.168.10.0/24'
]
gatewayIpAddress: '80.80.80.80'
localNetworkGatewayName: 'lng-sharedservices-001'
location: resourceGroup().location
}
}
module connection './Templates/Connection.bicep' = {
name: 'connection'
params: {
connectionName: 'cnt-sharedservices-001'
connectionType: 'IPSec'
enableBgp: false
localNetworkGatewayId: localNetworkGateway.outputs.lngid
location: resourceGroup().location
sharedKey: 'dhsjkdlahldk23e2mda'
virtualNetworkGatewayId: virtualNetworkGateway.outputs.vngid
}
}
At this point, I have all my coding done for the VPN connection, so I can now update my Github actions YAML file to include VPN in my deployment. Notice below that I have updated the branch to be the new working branch.
name: CI
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ VPN ]
pull_request:
branches: [ main ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Login to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS_BLOGSERIES }}
- name: Deploy resource group
uses: azure/arm-deploy@main
with:
scope: subscription
subscriptionId: ${{ secrets.AZURE_SUBSCRIPTION }}
region: westeurope
template: ./ResourceGroup/ResourceGroup.bicep
- name: Deploy virtual network
uses: azure/arm-deploy@main
with:
scope: subscription
subscriptionId: ${{ secrets.AZURE_SUBSCRIPTION }}
region: westeurope
template: ./Network/DeployNetwork.bicep
- name: Deploy VPN connection
uses: azure/arm-deploy@main
with:
scope: resourcegroup
resourceGroupName: rg-bicep-sharedservices-network-001
subscriptionId: ${{ secrets.AZURE_SUBSCRIPTION }}
region: westeurope
template: ./Network/DeployVPN.bicep
deploymentMode: incremental
I will now save all my files and commit them to my Github repository under the new branch. This will also kick off the Github action, and my VPN connection will then be deployed. Deploying the Virtual Network Gateway is a lengthy process that normally takes 30-45 min based on my experience. Below you can see the connection has been deployed and the status is now “Connected”.
When the deployment is done, I now have the VPN part of my code completed, and the Github action can deploy all the items I currently have in my code. I will again merge my code into the main branch and delete the VPN working branch.
For the next part of this blog series I will deploy two virtual machines and join them to my on-premises domain.
Stay tuned.