Step-by-Step: Revoking and Reinstating Client VPN Certificates for Azure Point-to-Site VPNs

Microsoft Azure provides Point-to-Site VPN (aka. Client VPN) connectivity for secure remote access by development and operations teams to cloud-based workloads that are provisioned on an Azure Virtual Network.  Azure Point-to-Site VPN connectivity uses SSTP as a firewall-friendly tunneling protocol and certificates for mutual authentication of each client connection.

Azure Site-to-Site and Point-to-Site VPN

You can find more details on configuring Azure Point-to-Site VPNs at the following link location:

When discussing Azure Point-to-Site VPN connectivity, one of the questions I frequently hear is ...

Great! But ... how do I disable a Point-to-Site VPN user when they're leaving my organization?

Azure Point-to-Site VPNs use certificates for user authentication and authorization, so we can simply revoke a user's certificate to disable their Point-to-Site VPN access.  In this article, we'll step through the process of revoking and reinstating user certificates for Azure Point-to-Site VPNs by using the Azure PowerShell module and the Azure Service Management REST API.

Authenticate to Azure

Before we can manage Azure resources via the Azure PowerShell module, we'll first need to authenticate.  Authentication to Azure can be accomplished via management certificates, or via Azure Active Directory.  In this article, we'll use management certificates to authenticate to Azure via both Azure PowerShell and the Azure Service Management REST API. 

# Download Azure Management Certificate

Get-AzurePublishSettingsFile

# Import Azure Management Certificate

Import-AzurePublishSettingsFile "${env:USERPROFILE}\Documents\Azure.publishsettings"

In a future article, we'll explore using Azure AD to authenticate to Azure via Azure PowerShell and the Azure Service Management REST API.

Select Azure Subscription

Once we've authenticated to Azure, we'll next select the Azure subscription in which our Azure Virtual Network is provisioned.  Many organizations have more than one Azure subscription for different release stages (dev, test, production), applications or business units.

# Select Azure Subscription

$subscriptionName = (Get-AzureSubscription).SubscriptionName | Out-GridView -Title "Select Azure Subscription" -PassThru

Select-AzureSubscription -SubscriptionName $subscriptionName

Get Subscription ID and Management Certificate Thumbprint

After selecting the appropriate Azure subscription, we'll need to grab the subscription ID and the management certificate thumbprint we used when authenticating to Azure.  We'll need these values to authenticate to Azure via the Azure Service Management REST API later in this article.

# Get Azure subscription information

$subscription = Get-AzureSubscription $subscriptionName -ExtendedDetails

$certificate = $subscription.Certificate

$subscriptionId = $subscription.SubscriptionId

Select Azure Virtual Network

Some organizations may have more than one Azure Virtual Network provisioned within their Azure subscription. In this step, we'll select the Azure Virtual Network that has the Point-to-Site VPN Gateway provisioned within it.

# Select Azure VNet for which to manage VPN certificates

$azureVNet = (Get-AzureVNetSite).Name | Out-GridView -Title "Select Azure VNet" -PassThru

Select VPN Client Certificate to Revoke

Now, we can choose the VPN client certificate that's associated with the user that we wish to disable.  When initially provisioning VPN client certificates for your users, be sure to use a certificate naming convention that makes it easy to identify each certificate based on username.  Also, be sure to save a copy of each certificate in a safe location so that you can easily access them later, if needed.

# Import saved copy of user's VPN client certificate

$certPassword = Read-Host "Enter VPN client certificate password" -AsSecureString

Import-PfxCertificate -FilePath "${env:USERPROFILE}\Documents\Azure\P2S VPN\VPN01Client.pfx" -CertStoreLocation Cert:CurrentUser\My -Exportable -Password $certPassword

# Select VPN client certificate to Revoke

$vpnCertThumbprint = (Get-ChildItem Cert:\CurrentUser\My | Out-GridView -Title "Select VPN certificate to revoke" -PassThru).Thumbprint

Revoke VPN Client Certificate

We've selected all the relevant values we'll need when revoking a Point-to-Site VPN client certificate, so now we can call the Azure Service Management REST API to perform the actual revoke process.  When we call this API, we'll pass along the relevant values that we've collected above.

# Build web request header

$requestHeader = @{"x-ms-version" = "2012-03-01"}

# Revoke a VPN Client Certificate

$revokeVPNCertUri = "https://management.core.windows.net/$subscriptionId/services/networking/$azureVNet/gateway/clientcertificates/$vpnCertThumbprint"

$response = Invoke-RestMethod -Uri $revokeVPNCertUri -Certificate $certificate -Method Post -Headers $requestHeader

# Confirm Revoked VPN Client Certificates

$listRevokedVPNCertUri = "https://management.core.windows.net/$subscriptionId/services/networking/$azureVNet/gateway/clientcertificates"

$response = Invoke-RestMethod -Uri $listRevokedVPNCertUri -Certificate $certificate -Method Get -Headers $requestHeader

$response.ClientCertificates.Thumbprint

After a user's VPN client certificate is revoked, if they should attempt to connect to the Point-to-Site VPN Gateway, their connection will not be successfully authenticated and they will receive the below error message.

Azure VPN Client

Reinstate a Revoked VPN Client Certificate

In some cases, you may find that you need to later reinstate a revoked VPN client certificate.  Luckily, we can use the same Azure API to reinstate certificates that were previously revoked by using the code snippet below.

# Reinstate a VPN Client Certificate

$reinstateVPNCertUri = https://management.core.windows.net/$subscriptionId/services/networking/$azureVNet/gateway/clientcertificates/$vpnCertThumbprint

$response = Invoke-RestMethod -Uri $reinstateVPNCertUri -Certificate $certificate -Method Delete -Headers $requestHeader