Private Linking from inside an Azure VM to multiple regional networks

We’re utilizing Non-public Linking – as described right here – in a number of eventualities, globally distributed:

Common deployments are often dealt with by construct brokers in these remoted regional networks which (😀 after all just for emergency debugging) additionally can be utilized as bounce packing containers.

This may make some out-of-the-ordinary upkeep jobs, which aren’t coated with cross-regional deployment pipelines, a bit cumbersome as one virtually has to connect with every of those bounce packing containers.

To make this simpler, I created a script in PowerShell, which permits to connect with a kind of useful resource (Key Vault on this instance) in all these networks directly from a standalone Azure VM.

VM connected to Key Vault instances in multiple regions with Private Link

I thought-about digital community peering from my VMs digital community into the digital networks of these areas however needed to keep away from to get blocked by potential IP tackle area overlaps. Therefore I applied linking these regional sources into my VMs digital community and in addition sustaining non-public DNS information in a personal DNS zone related to this digital community and with that not messing up the unique setting.

Within the following paragraphs I describe probably the most related components of this script:

setting the stage

When working with Non-public Linking and Non-public DNS the non-public DNS zone title and the subresource or groupId needs to be used based on this table:

$dnsZone = ""
$groupId = "vault"
Enter fullscreen mode

Exit fullscreen mode

extracting VM metadata

To retrieve details about the Azure VM one is at present engaged on, the metadata information endpoint can be utilized:

$vmInfo = Invoke-RestMethod -Headers @{"Metadata" = "true" } -Technique GET -NoProxy -Uri ""

$nicId = az vm present --subscription $vmInfo.compute.subscriptionId --resource-group $vmInfo.compute.resourceGroupName --name $vmInfo.compute.title --query networkProfile.networkInterfaces[0].id --output tsv

$subnetId = az community nic present --ids $nicId --query ipConfigurations[0] --output tsv

$vnetInfo = $subnetId.break up("")[0..8]
$vnetId = [string]::Be a part of("", $vnetInfo)
Enter fullscreen mode

Exit fullscreen mode

This extracts the Ids of the digital community and the subnet the present Azure VM is related to.

vnetId is derived from subnetId by breaking down the segments as neither az community nic present nor az community vnet subnet present return a ready-to-use vnetId; not a pleasant method working with these segments, however possibly somebody can depart me a touch upon the right way to enhance readability right here

Wait a minute – why mixing PowerShell and Azure CLI?

I made a decision to make use of Azure CLI as a substitute of Azure PowerShell as CLI permits working with sources in subscriptions outdoors the present context by merely specifying the distant --subscription and --resource-group. With Azure PowerShell I’d be needing to change backwards and forwards – from/to subscription which holds the VM and to/from subscription which holds the regional networks and sources.

the script assumes that Azure CLI session / context is ready to the subscription holding the sources and that Azure VM is in one other subscription

All of the steps on this script could be simply achieved with Azure CLI and bash / zsh mixed with jq.

non-public DNS zone

First we’d like a personal DNS zone related to the VMs digital community which is able to obtain the non-public IP tackle entries of the non-public hyperlink endpoints:

Write-Host "create/test non-public DNS zone" $dnsZone "for group" $groupId

if (!$(az community private-dns zone present -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId -n $dnsZone --query id -o tsv)) {
    az community private-dns zone create -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId `
        -n $dnsZone

Write-Host "create non-public DNS hyperlink"

az community private-dns hyperlink vnet create -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId `
    -n $("vnet-" + $groupId + "-dns-link") `
    -z $dnsZone -v $vnetId -e false
Enter fullscreen mode

Exit fullscreen mode

bear in mind that typically a VM restart is required when switching a digital community from one non-public DNS hyperlink to a different

non-public hyperlink + endpoints

The script then iterates by way of a (right here hypothetical) set of deployment cases and areas …

  • determines the regional Key Vault resourceId – once more with a hypothetical / regional naming scheme
  • creates names distinctive inside the Azure VMs subscription + useful resource group for personal hyperlink, non-public endpoint and DNS zone group
  • creates a personal endpoint and hyperlink from the Key Vault useful resource to VMs subnet (may be one other subnet within the VMs digital community)
  • creates a personal DNS zone group which robotically maintains the non-public DNS zone report for the non-public endpoint inside the non-public DNS zone related to the VMs digital community
Write-Host "non-public hyperlink all KeyVault cases"

foreach ($occasion in "int", "qa", "stage", "prod") {
    foreach ($location in "eus", "weu", "sea")  ConvertFrom-Json

        $linkName = $keyVaultName + "-" + $vmInfo.compute.title + "-link"
        $endpointName = $keyVaultName + "-" + $vmInfo.compute.title + "-pep"
        $groupName = $keyVaultName + "-" + $vmInfo.compute.title + "-zonegroup"

        az community private-endpoint create --connection-name $linkName `
            --name $endpointName `
            -g $vmInfo.compute.resourceGroupName `
            --subscription $vmInfo.compute.subscriptionId `
            --private-connection-resource-id $keyVault.Id `
            --group-id $groupId `
            --subnet $subnetId

        az community private-endpoint dns-zone-group create `
            -g $vmInfo.compute.resourceGroupName `
            --subscription $vmInfo.compute.subscriptionId `
            --endpoint-name $endpointName `
            --name $groupName `
            --private-dns-zone $dnsZone `
            --zone-name $dnsZone            
Enter fullscreen mode

Exit fullscreen mode

That is it. To connect with different forms of sources “simply” $dnsZone and $groupId have to be exchanged in addition to the willpower of the goal useful resource’s resourceId.

In our eventualities we even have globally distributed sources like

  • CosmosDB
  • API Administration
  • Container Registry

(in comparison with regional sources like Key Vault, Storage, SQL, Service Bus).

For these international sources it is mindless to connect with all endpoints in all areas. Therefore the script would have to be tailored to solely connect with the principle area.


At starting of the script current digital community peerings (which in my case may doubtlessly trigger conflicts with non-public hyperlinks), current non-public endpoints and personal DNS hyperlinks are deleted from the VMs digital community to present the script a clear slate to work on:

Write-Host "delete current (VM's) digital community hyperlinks"

az community vnet peering record --vnet-name $vnetInfo[8] -g $vnetInfo[4] --subscription $vnetInfo[2] --output json | ConvertFrom-Json | % {
    az community vnet peering delete --ids $_.Id

Write-Host "delete current (VM's) non-public endpoint hyperlinks"

az community private-endpoint record -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId --output json | ConvertFrom-Json | % {
    az community private-endpoint delete --ids $_.Id

Write-Host "delete current (VM's) non-public DNS hyperlinks"

az community private-dns hyperlink vnet record -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId --zone-name $dnsZone -o json | ConvertFrom-Json | % {
    if ($ -eq $vnetId) {
        Write-Host "deleting hyperlink: $($"
        az community private-dns hyperlink vnet delete -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId --zone-name $dnsZone --name $_.title --yes
Enter fullscreen mode

Exit fullscreen mode

This part of the script would solely delete non-public endpoints and hyperlinks created within the context of the VM. In case such endpoints and personal DNS hyperlinks exist in different subscriptions or useful resource teams, az community private-endpoint record + delete in addition to az community private-dns hyperlink vnet record + delete have to be enhanced.

Add a Comment

Your email address will not be published. Required fields are marked *