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.

Azure firewall

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.

Azure firewall

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.

Azure firewall

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

Leave a Comment

Your email address will not be published.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top