Skip to content

Instantly share code, notes, and snippets.

@KaiWalter
Created May 15, 2022 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KaiWalter/8dd1dfca55d81653fd50802ff0062c79 to your computer and use it in GitHub Desktop.
Save KaiWalter/8dd1dfca55d81653fd50802ff0062c79 to your computer and use it in GitHub Desktop.
Private linking resources from inside an Azure VM to multiple regional networks
param (
[Parameter(Mandatory)]
[ValidateSet(
"blob",
"configurationStores",
"namespace",
"registry",
"sites",
"Sql",
"sqlServer",
"table",
"vault"
)]
[string]
$GroupId,
[Parameter(Mandatory)]
[string]
$ResourceNamePattern,
[Parameter(Mandatory)]
[string]
$ResourceGroupNamePattern,
[switch]
$SkipDeletes,
[switch]
$SkipCreate
)
# --------------------------------------------------------------------------------
# determine resource Ids
switch ($GroupId) {
"blob" {
$dnsZone = "privatelink.blob.core.windows.net"
$resourceType = "Microsoft.Storage/storageAccounts"
}
"configurationStores" {
$dnsZone = "privatelink.azconfig.io"
$resourceType = "Microsoft.AppConfiguration/configurationStores"
}
"namespace" {
$dnsZone = "privatelink.servicebus.windows.net"
$resourceType = "Microsoft.ServiceBus/namespaces"
}
"registry" {
$dnsZone = "privatelink.azurecr.io"
$resourceType = "Microsoft.ContainerRegistry/registries"
}
"sites" {
$dnsZone = "privatelink.azurewebsites.net"
$resourceType = "Microsoft.Web/sites"
}
"Sql" {
$dnsZone = "privatelink.documents.azure.com"
$resourceType = "Microsoft.AzureCosmosDB/databaseAccounts"
}
"sqlServer" {
$dnsZone = "privatelink.database.windows.net"
$resourceType = "Microsoft.Sql/servers"
}
"table" {
$dnsZone = "privatelink.table.core.windows.net"
$resourceType = "Microsoft.Storage/storageAccounts"
}
"vault" {
$dnsZone = "privatelink.vaultcore.azure.net"
$resourceType = "Microsoft.KeyVault/vaults"
}
}
$resources = @()
az resource list --resource-type $resourceType -o json | ConvertFrom-Json | `
? { $_.name -match $ResourceNamePattern -and $_.resourceGroup -match $ResourceGroupNamePattern } | % {
$resources += @{id = $_.id; name = $_.name }
}
if ($resources.Count -eq 0) {
Write-Error "No resources found matching the pattern"
Exit
}
# --------------------------------------------------------------------------------
# detect VM metadata
# see https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=windows
$vmInfo = Invoke-RestMethod -Headers @{"Metadata" = "true" } -Method GET -NoProxy -Uri "http://169.254.169.254/metadata/instance?api-version=2021-02-01"
$nicId = az vm show --subscription $vmInfo.compute.subscriptionId --resource-group $vmInfo.compute.resourceGroupName --name $vmInfo.compute.name --query networkProfile.networkInterfaces[0].id --output tsv
$subnetId = az network nic show --ids $nicId --query ipConfigurations[0].subnet.id --output tsv
$vnetInfo = $subnetId.split('/')[0..8]
$vnetId = [string]::Join("/", $vnetInfo)
Write-Host "NIC :" $nicId
Write-Host "VNET :" $vnetId
Write-Host "SUBNET :" $subnetId
# --------------------------------------------------------------------------------
if (!$SkipDeletes) {
Write-Host "delete existing (VM's) virtual network links"
az network vnet peering list --vnet-name $vnetInfo[8] -g $vnetInfo[4] --subscription $vnetInfo[2] --output json | ConvertFrom-Json | % {
az network vnet peering delete --ids $_.Id
}
Write-Host "delete existing (VM's) private endpoint links"
az network private-endpoint list -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId --output json | ConvertFrom-Json | % {
az network private-endpoint delete --ids $_.Id
}
Write-Host "delete existing (VM's) private DNS links"
if ($(az network private-dns zone list -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId --query "[?name == '$dnsZone'].id" -o tsv)) {
az network private-dns link vnet list -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId --zone-name $dnsZone -o json | ConvertFrom-Json | % {
if ($_.virtualNetwork.id -eq $vnetId) {
Write-Host "deleting link: $($_.id)"
az network private-dns link vnet delete -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId --zone-name $dnsZone --name $_.name --yes
}
}
}
}
if (!$SkipCreate) {
Write-Host "create/check private DNS zone" $dnsZone "for group" $groupId
if (!$(az network private-dns zone list -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId --query "[?name == '$dnsZone'].id" -o tsv)) {
az network private-dns zone create -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId `
-n $dnsZone
}
Write-Host "create private DNS link"
az network private-dns link vnet create -g $vmInfo.compute.resourceGroupName --subscription $vmInfo.compute.subscriptionId `
-n $("vnet-" + $groupId + "-dns-link") `
-z $dnsZone -v $vnetId -e false
Write-Host "private link resources"
foreach ($resource in $resources) {
Write-Host "link" $resource.name
$linkName = $GroupId + "-" + $resource.name + "-" + $vmInfo.compute.name + "-link"
$endpointName = $GroupId + "-" + $resource.name + "-" + $vmInfo.compute.name + "-pep"
$groupName = $GroupId + "-" + $resource.name + "-" + $vmInfo.compute.name + "-zonegroup"
az network private-endpoint create --connection-name $linkName `
--name $endpointName `
-g $vmInfo.compute.resourceGroupName `
--subscription $vmInfo.compute.subscriptionId `
--private-connection-resource-id $resource.id `
--group-id $GroupId `
--subnet $subnetId
az network 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
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment