Recently I needed to help somebody to use private link for an existing Azure Storage account. I came up with a Bicep template that helped them achieve the goal. I thought, let’s just the share the code, in case somebody (or maybe even my future self) would need that for inspiration.
Bicep templates
I have started with the assumption that we already have:
- A storage account (General Purpose V2)
- A virtual network
Note that you need to have a V2 storage account for this to work.
Let’s start the bicep file with the required parameters and variables
@description('Location for all resources.')
param location string = resourceGroup().location
@description('Your subscription id.')
param subscriptionId string
@description('Resource group Name.')
param groupName string
@description('VNet Name.')
param vnetName string
@description('Storage account Name.')
param storageAccountName string
var vnetId = '/subscriptions/${subscriptionId}/resourceGroups/${groupName}/providers/Microsoft.Network/virtualNetworks/${vnetName}'
var dnsZoneName = 'privatelink.blob.core.windows.net'
var endpointName = 'privlinkmoimhawe'
var subnetId = '/subscriptions/${subscriptionId}/resourceGroups/${groupName}/providers/Microsoft.Network/virtualNetworks/${vnetName}/subnets/default'
var nsgId = '/subscriptions/${subscriptionId}/resourceGroups/${groupName}/providers/Microsoft.Network/networkSecurityGroups/${vnetName}-default-nsg-${location}'
var storageAccountId = '/subscriptions/${subscriptionId}/resourceGroups/${groupName}/providers/Microsoft.Storage/storageAccounts/${storageAccountName}'
...
With these variables, we can start creating the resources that we need.
Subnet config
The following block will reconfigure the subnet for private endpoint.
resource subnet 'Microsoft.Network/virtualNetworks/subnets@2022-01-01' = {
name: 'gaga-vnet/default'
properties: {
addressPrefix: '10.0.0.0/24'
delegations: []
serviceEndpoints: []
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
networkSecurityGroup: {
id: nsgId
}
}
}
...
Private Endpoint
Let’s create the private endpoint:
resource privateEndpoint 'Microsoft.Network/privateEndpoints@2022-01-01' = {
dependsOn: [
subnet
]
location: location
name: endpointName
properties: {
subnet: {
id: subnetId
}
customNetworkInterfaceName: '${endpointName}-nic'
privateLinkServiceConnections: [
{
name: endpointName
properties: {
privateLinkServiceId: storageAccountId
groupIds: [ 'blob' ]
}
}
]
}
}
...
Private DNS Zone
resource dnszone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
name: dnsZoneName
location: 'global'
}
resource vnetLinks 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
name: '${dnsZoneName}/${uniqueString(vnetId)}'
location: 'global'
properties: {
registrationEnabled: false
virtualNetwork: {
id: vnetId
}
}
}
resource dnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2022-01-01' = {
dependsOn: [
privateEndpoint
]
name: '${endpointName}/default'
properties: {
privateDnsZoneConfigs: [
{
name: 'privatelink-blob-core-windows-net'
properties: {
privateDnsZoneId: dnszone.id
}
}
]
}
}
...
That’s all we need in our bicep file. Let’s say, we saved all the above in a file named template.bicep
.
Deploy to Azure
We can use Azure CLI to deploy this file to Azure.
az deployment group create --resource-group NAME--template-file .\template.bicep
...
That’s all we need for Private endpoint to be ready to use. One last thing we want to do is to disable the access form all other networks via Storage account firewall. We can do that by running the following Azure CLI command:
az storage account update --name StorageAccountNAME --resource-group NAME --public-network-access Disabled
...
That’s all!