These days there are different authentication methods you can use to configure a Point-to-Site (P2S) VPN connection to a VNet in Azure. Such a P2S VPN connection can be useful when you want to securely connect to resources in that VNet or any of it’s peered VNets from a client device on a remote location. Like when you are working from home or from a customer’s site on your own or corporate Windows 11 device. Next to that you can also use it instead of a Site-to-Site (S2S) VPN, when you for example only need to connect a few client devices to that VNet.
If you’re interested, you can always find more information about P2S VPN connections on this Microsoft Docs page
Just like with almost all other Azure resources and services, there are different ways you can deploy and configure a P2S VPN. You can use Azure CLI, ARM templates or Bicep, but in this blog post I will focus on how you can use Azure PowerShell to configure a P2S VPN to an existing VNet using Azure certificate authentication. And to make it all a little easier and more automated, I wrote the below Azure PowerShell script which does all of the following:
- Check if the PowerShell window is running as Administrator (which is a requirement), otherwise the Azure PowerShell script will be exited.
- Check if the VPN gateway variable is correctly declared and/or if the VPN gateway resource exists in the targeted Azure subscription, otherwise the script will be exited.
- Check if the root certificate (a base-64 encoded X.509 .CER file) is present in the C:\Temp folder, otherwise the script will be exited.
- Add the VPN client address pool to the VPN gateway.
- Add the client root certificate to the VPN gateway.
- Generate the VPN client configuration files and download them as a zipped folder (vpnclientconfiguration.zip) in the C:\Temp folder.
To use the script copy and save it as Configure-P2S-VPN-to-an-existing-VNet-using-Azure-certificate-authentication.ps1 or download it from GitHub. Then before using the script, adjust all variables to your use (you can find an adjusted example in a screenshot below) and then run the customized script with Administrator privileges from Windows Terminal, Visual Studio Code, or Windows PowerShell. Or you can simply run it from Cloud Shell.
Prerequisites
- An Azure Subscription.
- An Azure Administrator account with the necessary RBAC roles.
- An existing VNet (preferably the HUB VNet) and Azure VPN Gateway (at least with a SKU VpnGw1).
- C:\Temp folder must exist (or your own specified folder, adjust variables accordingly) on the device where you run the script.
- A self-signed root certificate (a base-64 encoded X.509 .CER file) * stored in the C:\Temp folder on the device where you run the script.
* I already wrote a PowerShell script you can use to automate the creation of a new self-signed root certificate and a client certificate for use with an Azure P2S VPN. You can find the related blog post over here or you can download the script directly from GitHub.


Azure PowerShell script
If you are not running the script from Cloud Shell, don’t forget to sign in with the Connect-AzAccount cmdlet to connect your Azure account. And if you are using multiple Azure subscriptions, select the proper subscription with the Get-AzSubscription cmdlet before running the script.

<#
.SYNOPSIS
A script used to configure a Point-to-Site (P2S) VPN Connection to an existing VNet in Azure using Azure certificate authentication.
.DESCRIPTION
A script used to configure a Point-to-Site (P2S) VPN Connection to an existing VNet in Azure using Azure certificate authentication.
First of all some checks will be performed, to see if the VPN gateway variable is declared correctly and/or the VPN gateway resource does exist in the Azure environment.
Then the script will also check if the root certificate is present in the C:\Temp folder.
If one of the checks fails, the script will be exited.
But if all checks are OK, the script will continue with adding the VPN client address pool and the client root certificate to the VPN gateway.
And at the end, the VPN client configuration files are generated and downloaded (vpnclientconfiguration.zip) to the C:\Temp folder.
.NOTES
Filename: Configure-P2S-VPN-to-an-existing-VNet-using-Azure-certificate-authentication.ps1
Created: 05/01/2022
Last modified: 05/01/2022
Author: Wim Matthyssen
PowerShell: Azure Cloud Shell or Azure PowerShell
Version: Install latest Azure Powershell modules (at least Az version 5.9.0 and Az.Network version 4.7.0 is required)
Action: Change variables were needed to fit your needs.
Disclaimer: This script is provided "As IS" with no warranties.
.EXAMPLE
.\Configure-P2S-VPN-to-an-existing-VNet-using-Azure-certificate-authentication.ps1
.LINK
https://wmatthyssen.com/2022/01/05/azure-powershell-script-configure-a-p2s-vpn-to-an-existing-vnet-using-azure-certificate-authentication/
#>
## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Variables
$rgNetworkSpoke = #<your VNet rg here> The Azure resource group in which your existing VNet is deployed. Example: "rg-hub-myh-networking"
$gatewayName = #<your virtual network gateway name here> The existing virtual network gateway. Example: "vpng-hub-myh-weu"
$vpnClientAddressPool = #<your VPN client address pool here> The VPN client address pool from which the VPN clients receive an IP address. Example: "172.16.101.0/24"
$rootCertName = #<your root certificate name here> The name of the root certificate. Example: "p2s-myh-root-cert"
$rootCertBase64Path = #<your exported root cert (.CER) file path here> The file path to the exported root Base-64 encoded X.509 (.CER) file. Example: "C:\Temp\$rootCertName.cer"
$tempFolderName = "Temp"
$tempFolder = "C:\" + $tempFolderName +"\"
$vpnClientConfigZip = "vpnclientconfiguration.zip"
$vpnClientConfigDestinationFolder = $tempFolder + $vpnClientConfigZip
$global:currenttime= Set-PSBreakpoint -Variable currenttime -Mode Read -Action {$global:currenttime= Get-Date -UFormat "%A %m/%d/%Y %R"}
$foregroundColor1 = "Red"
$foregroundColor2 = "Yellow"
$writeEmptyLine = "`n"
$writeSeperatorSpaces = " - "
## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Check if running as Administrator, otherwise exit the script
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$isAdministrator = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if ($isAdministrator -eq $false) {
Write-Host ($writeEmptyLine + "# Please run PowerShell as Administrator" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine
exit
}
## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Start script execution
Write-Host ($writeEmptyLine + "# Script started. Without any errors, it will need around 6 minutes to complete" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine
## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Check VPN gateway and root certificate
# Check the VPN gateway variable and the existence of the resource. If it is not declared correctly or the resource is not there, exit the script
try {
$gateway = Get-AzVirtualNetworkGateway -ResourceGroupName $rgNetworkSpoke -Name $gatewayName -ErrorAction Stop
} catch {
Write-Host ($writeEmptyLine + "# An error occurred: Check the $gatewayName variable and the existence of the resource in the environment" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine
Write-Host ($writeEmptyLine + "# The script will be stopped. Please fix the error, and rerun the script" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine
exit
}
# Check if the root certificate is available in the Temp folder, otherwise exit the script
If(!(test-path $rootCertBase64Path -PathType Leaf))
{
Write-Host ($writeEmptyLine + "# The Client root certificate $rootCertName can not be found at the specified location" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine
Write-Host ($writeEmptyLine + "# The script will be stopped. Please fix the error, and rerun the script" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine
exit
}
Write-Host ($writeEmptyLine + "# VPN Gateway $gatewayName and root certificate $rootCertName checks completed with succes" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine
## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Add the VPN client address pool
Set-AzVirtualNetworkGateway -VirtualNetworkGateway $gateway -VpnClientAddressPool $vpnClientAddressPool
Write-Host ($writeEmptyLine + "# VPN client address pool $vpnClientAddressPool added to the virtual gateway $gatewayName" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine
## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Add the client root certificate to the virtual gateway
$cert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2($rootCertBase64Path)
$base64Cert = [system.convert]::ToBase64String($cert.RawData)
Add-AzVpnClientRootCertificate -PublicCertData $base64Cert -ResourceGroupName $rgNetworkSpoke -VirtualNetworkGatewayName $gatewayName -VpnClientRootCertificateName $rootCertName
Write-Host ($writeEmptyLine + "# Client root certificate $rootCertName added to the virtual gateway $gatewayName" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine
## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Generate VPN client configuration files and download them in the C:\Temp folder
# Generate VPN client configuration files
$vpnClientConfig = New-AzVpnClientConfiguration -ResourceGroupName $rgNetworkSpoke -Name $gatewayName -AuthenticationMethod "EapTls"
# Download VPN client configuration files (vpnclientconfiguration.zip)
Import-Module BitsTransfer
Start-BitsTransfer -Source $vpnClientConfig.VPNProfileSASUrl -Destination $vpnClientConfigDestinationFolder
Write-Host ($writeEmptyLine + "# VPN configuration files generated and downloaded into $tempFolder" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine
## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Write script completed
Write-Host ($writeEmptyLine + "# Script completed" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine
## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------








I hope this Azure PowerShell script comes in handy and helps you to easily configure a secure connection via a P2S VPN to a VNet in your own Azure environment.
If you have any questions or recommendations about it, feel free to contact me through my Twitter handle (@wmatthyssen) or to just leave a comment.
Pingback: PowerShell script: Generate a self-signed root certificate and client certificate for use with an Azure P2S VPN – Wim Matthyssen
Pingback: Securely connect to your Azure VMs with JIT and a P2S VPN – Wim Matthyssen
Pingback: Securely attach on your Azure VMs with JIT and a P2S VPN – Wim Matthyssen - Firnco