Add Private Link to an existing Azure storage account

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!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s