Managing Azure firewall and virtual networks with PowerShell

Using Azure Portal, we can easily manage virtual networks and firewall settings in any given Azure Storage Account, and we have a brief overview of the steps required to configure in the following section of this article. However, our focus will be creating a Runbook using Azure Automation to configure all Storage Accounts in any given subscription. All Storage Accounts will be set to use all existing virtual networks on their security, as well as static public IPs.

The idea behind the automation is to show how you could enforce compliance using your business requirements in this area.

Checking the firewall and virtual network feature using Azure Portal

Logged on the Azure Portal, select the desired Storage Account, click on Firewalls and virtual networks. In the new blade that opens up on the right side, we can turn it on by selecting Selected networks and then add new or existent virtual networks to the Storage Account. On the firewall section, add the IP addresses (all of them must be public) that can access this Storage Account.

Although it is not a requirement, because we can enable it automatically from the Storage Account side, we can always configure the desired virtual network to support service endpoints by adding it and selecting the subnets that will be supported.

When adding a new virtual network in any given Storage Account, we can see if the subnets will be configured. When the information service endpoint required is shown, then the process of adding that specific subnet will set it on the virtual network side as well.

Using a script

The first step is to create a simple JSON file containing two pieces of information: IPAddressorRange and Action. We are going to save that JSON file in a Storage Account that we are going to use a repository of our Azure Automation.

In the Azure Runbook, we will create a SAS Token to access the Storage Account for one hour. Then, we are going to download the PublicIPs.json file to the machine that is running the Azure Automation Runbook.

At the beginning of the script, we will load all the Public IPs required and define the endpoint by defining these two first lines of code. After that, we store all the virtual network in the same geopolitical region (in our case, Canada is comprised of Canada Central and Canada East) in the $VNETs variable.

$JSONPublicIPs = Get-Content -Raw -Path ((Get-Location).Path + "\PublicIPs.json") | ConvertFrom-Json
$vEndPoint = "Microsoft.Storage"
$VNETs = Get-AzVirtualNetwork | where { ($_.Location -eq "canadacentral") -or ($_.location -eq "canadaeast")}
The next piece of code is to loop through the virtual networks, find their subnets, and configure them to support Azure Storage endpoints.

ForEach ($SingleVNET in $VNETs){
$Subnets = Get-AzVirtualNetwork -Name $SingleVNET.Name | Get-AzVirtualNetworkSubnetConfig
ForEach ($SingleSubnet in $Subnets){
$tmp = Set-AzVirtualNetworkSubnetConfig -Name $SingleSubnet.Name -VirtualNetwork $SingleVNET -AddressPrefix $SingleSubnet.AddressPrefix -ServiceEndpoint $vEndPoint
Msgbox "Updating Virtual Network:" $SingleVNET.Name 0
$tmp = $SingleVNET | Set-AzVirtualNetwork

Now that all the virtual networks are supporting Storage Accounts endpoints, our first stage is going to store all Storage Accounts in a variable called $StorageAccounts. We are going to look for all storage accounts in our geopolitical region, the Storage Account supporting the Azure Automation, and any Storage Account being used by the system (if a storage account contains ms-resource-usage tag we are going to skip it).

$StorageAccounts = Get-AzStorageAccount | Where-Object { (($_.Tags.Keys -notcontains "ms-resource-usage") -and ( ($_.Location -eq "canadacentral") -or ($_.Location -eq "canadaeast"))) -and ($_.StorageAccountName -ne ’devopsstgaccount’) }

The script is comprised of two stages. In the first one we are going to enable the firewall and configure all IP addresses that we are gathering from the JSON file. The code also checks to see if there are invalid entries in the JSON files and clean up unused entries.

ForEach ($SingleStorageAccount in $StorageAccounts){
Msgbox "Updating Storage Account: " $SingleStorageAccount.StorageAccountName 0
$tmp = Update-AzStorageAccountNetworkRuleSet -ResourceGroupName $SingleStorageAccount.ResourceGroupName -Name $SingleStorageAccount.StorageAccountName -DefaultAction Deny
If ($tmp) {Msgbox "Storage Account (Default Action): " "Configured to Deny (required when using Virtual Network" 0}
$tmp = Update-AzStorageAccountNetworkRuleSet -ResourceGroupName $SingleStorageAccount.ResourceGroupName -Name $SingleStorageAccount.StorageAccountName -IPRule $JSONPublicIPs -ErrorVariable tmpErrorVar -ErrorAction SilentlyContinue
If ($tmp) {
Msgbox "Storage Account (Public IPs Action): " "All IPs from the PublicIPs.json were published" 0
} Else {
If ($tmpErrorVar) {
If ($tmpErrorVar[0].Exception.Message.Contains("networkAcls.virtualNetworkRules[*].id(unique)")) {
Msgbox "Storage Account (Public IPs Action): " "There are duplicated entries on the list. Check the JSON file" 2
If ($tmpErrorVar[0].Exception.Message.Contains("networkAcls.ipRule[*].value")) {
Msgbox "Storage Account (Public IPs Action):" "There are wrong IPs/Subnets in the JSON file." 2

The second stage of the script is to loop through all Storage Accounts and for each storage account, all virtual networks/subnets will be checked against the Storage Account, and if they are not there already, they will be added.

ForEach ($SingleStorageAccount in $StorageAccounts){
Msgbox "Virtual Network Updates on the following Storage Account: " $SingleStorageAccount.StorageAccountName 0
$tmpSTGRules = $null
$tmpStgRules = Get-AzStorageAccountNetworkRuleSet -ResourceGroupName $SingleStorageAccount.ResourceGroupName -Name $SingleStorageAccount.StorageAccountName
ForEach ($SingleVNET in $VNETs){
$Subnets = Get-AzVirtualNetwork -Name $SingleVNET.Name | Get-AzVirtualNetworkSubnetConfig
ForEach ($SingleSubnet in $Subnets){
If ($tmpSTGRules.VirtualNetworkRules.Count -ne 0) {
If ($tmpStgRules.virtualNetworkRules.VirtualNetworkResourceId.Contains($SingleSubnet.Id) -eq $False ) {
$tmpOperation = Add-AzStorageAccountNetworkRule -ResourceGroupName $SingleStorageAccount.ResourceGroupName -Name $SingleStorageAccount.StorageAccountName -VirtualNetworkResourceId $SingleSubnet.Id -ErrorVariable tmpErrorVar -ErrorAction SilentlyContinue
} Else{
$tmpOperation = Add-AzStorageAccountNetworkRule -ResourceGroupName $SingleStorageAccount.ResourceGroupName -Name $SingleStorageAccount.StorageAccountName -VirtualNetworkResourceId $SingleSubnet.Id -ErrorVariable tmpErrorVar -ErrorAction SilentlyContinue

Managing your Azure firewalls and virtual networks: Tweaking and tags

In this article, we went through the process of managing Azure firewalls and virtual networks in a Storage Account and how to use Azure Automation to enforce security in an entire subscription. Based on your environment, you may want to tweak which virtual networks or Storage Accounts will have their security configured by the script. We can do that efficiently managing the query in the Storage Account and virtual network variables. Bear in mind that tags are your friend when automating stuff. You may even create a logic to read a tag of a Storage Account to identify which virtual network could be associated.

You can check out the entire script file here.

Featured image: Shutterstock

Anderson Patricio

Anderson Patricio is a Canadian MVP in Cloud and Datacenter Management, and Office Server and Services, besides of the Microsoft Award he also holds a Solutions Master (MCSM) in Exchange, CISSP and several other certifications. Anderson contributes to the Microsoft Community with articles, tutorials, blog posts, twitter, forums and book reviews. He is a regular contributor here at,, and Anderson (Portuguese).

Published by
Anderson Patricio

Recent Posts

New Mexico sues Google for violating privacy of minors

New Mexico is suing Google for alleged privacy violations against minors, specifically that it uses…

5 hours ago

Exchange 2019: Peaceful coexistence with Exchange 2016

Exchange coexistence has been around for a long time. This can be having Exchange 2010…

9 hours ago

How to check the VM sizes available on your Azure Region

If you want to check VM sizes available to any given region, Azure Portal is…

12 hours ago

Cybersecurity 101: Close the door on open network shares

If you have open network shares on your network, you are opening the door to…

1 day ago

Spear-phishing email results in U.S. gas pipeline ransomware attack

A spear-phishing email has resulted in a U.S. gas pipeline ransomware attack. Making the attack…

1 day ago

Planning your Azure reserved instances and flexibility groups

To really lower your Azure costs, you need actionable information. Get info on flexibility groups…

2 days ago