Using Azure CLI and PowerShell to secure your Storage Accounts

Keeping your cloud infrastructure safe can be tricky. This article shows how to make your environment more secure using Azure CLI and PowerShell for managing the configuration of resources in your subscriptions.

Krzysztof Demczuk 2024.01.17   –   5 MIN read

After constant persuasion and countless hours of planning, you took a big step and decided to leap from on-premises infrastructure to a public cloud. You were tempted by promises of instant flexibility, manageability, scalability, and security. On the Internet, you came across @lukaszbobrek’s article on the cloud shared responsibility model. You have learned that your duties related to ensuring security on your cloud infrastructure are strictly associated with your service model of choice. The more control you give up, the fewer things you will have to worry about – simple. However, at the end of the day, your list of worries is still not empty. You will always have to take care of access management, accounts, data, and endpoint security. This is the moment to ask you: are you sure you are using cloud services securely? Are you aware of popular misconfigurations and pitfalls that can be easily overlooked? You definitely should be! Take a look at the Gartner’s predictions from 2021:

Through 2025, 99% of cloud security failures will be the customer’s fault.”

Ok, we are here not to scare you. At least not too much. We are here to share our experience and help you make your infrastructure more secure. The good news is that some of the best practices and security concepts remain the same even after migration to the cloud.

Let me share a general statement that applies to any infrastructure regardless of its location – you can only protect things you are aware of. This is why, among other things, you should have clear information on what is an effective outcome of your current safeguards. When you know how your data can be accessed, you can implement appropriate strategies and incorporate the right tools to protect your assets. So, using the example of Storage Account in Azure, I will show you the benefits of using Azure CLI and PowerShell for managing the configuration of resources in your subscriptions.

Connect with the author on LinkedIn!

How to use Azure PowerShell and Azure CLI to check your configuration?

When you start the adventure with Azure, the Portal is the first place you visit. It is a web-based console that allows you to manage your subscriptions and resources using a graphical interface. It is a great place to explore Azure services or introduce configuration changes that are not required too often. But be careful! It can be tempting to be stuck at this point and not move further. Especially, when you are managing a small infrastructure – and you are not feeling comfortable with terminals. Let’s assume that you must identify and present a comprehensive list of all publicly available Storage Accounts. Every week. And there are over 100 of those. Unfortunately, there is no information on firewall settings in the summary view available in the Portal. Of course, you can do it manually by browsing each resource and spending a significant amount of your valuable time. Or you can simply execute one PowerShell command to get it done in a few minutes! I assume that I managed to convince you. If you want to use the PowerShell, you have to make sure that you have the Azure module installed and then connect it to your account. Now, you are one simple command away from your goal:

PS C:\Users\username> Get-AzStorageAccount | Select-Object StorageAccountName,ResourceGroupName,PublicNetworkAccess
StorageAccountName ResourceGroupName PublicNetworkAccess
------------------ ----------------- -------------------
st0r4ge1986        RG-Demo           Disabled
st0r4ge6891        RG-Demo           Disabled

That was fast, right? The same information can be extracted using Azure CLI. Once it is installed and authenticated, the following command can be executed to get the same information:

PS C:\Users\username> az storage account list --output table --query "[].{StorageAccountName:name,PublicNetworkAccess:publicNetworkAccess}"
StorageAccountName    PublicNetworkAccess
--------------------  ---------------------
st0r4ge1986           Disabled
st0r4ge6891           Disabled

Can we trust what Azure Portal shows?

I have presented only one benefit of using PowerShell and Azure CLI. What if I told you those tools can help you see things not visible in the portal – things that may be especially important to the security of your data? Let’s move to the network settings of the Storage Account. There are three settings regarding public access to such a resource:

  • Enabled from all networks,
  • Enabled from selected virtual networks and IP addresses,
  • Disabled.

As you see, in the output from the Azure PowerShell module and Azure CLI – both of my Storage Accounts had public access disabled. In this configuration, only private access to these resources should be allowed. Of course, there might be a situation where, for any reason, you will have to allow someone to access your data from the Internet. The best option in such a scenario would be to ask nicely for their public IP address, which can be allow-listed. Sometimes, it may not be possible, but for this exercise, let’s assume we have access to those IPs. So, you switch your setting from Disabled to Enabled from selected virtual networks and IP addresses and provide those specific IPs in the configuration:

Using Azure PowerShell and Azure CLI to check firewall configuration

Let’s take a quick peak on the configuration of the firewall settings from the other point of view:

  • Azure PowerShell module
PS C:\Users\username> Get-AzStorageAccountNetworkRuleSet -ResourceGroupName RG-Demo -Name st0r4ge1986
Bypass              : AzureServices
DefaultAction       : Deny
IpRules             : [73.12.157.35,...]
VirtualNetworkRules :
ResourceAccessRules :

Get-AzStorageAccountNetworkRuleSet cmdlet allows you to get information on the network rules applying to specific Storage Accounts. In this case, public access is enabled but limited to the addresses on the IpRules list. Any other connection from not explicitly allowed IP address will be automatically rejected, and only Azure services can bypass it.

  • Azure CLI
PS C:\Users\username> az storage account list --query "[].{name:name,publicNetworkAccess:publicNetworkAccess,networkRuleSet:networkRuleSet}"
[
  {
    "name": "st0r4ge1986",
    "networkRuleSet": {
      "bypass": "AzureServices",
      "defaultAction": "Deny",
      "ipRules": [
        {
          "action": "Allow",
          "ipAddressOrRange": "73.12.157.35"
        }
      ],
      "resourceAccessRules": [],
      "virtualNetworkRules": []
    },
    "publicNetworkAccess": "Enabled"
  },
[…]

Here, we can see pretty much the same information as the one returned by PowerShell cmdlet.

As time passes by, you become informed that you can disable public access to your storage account. Since you are already signed into the Azure Portal, you decide to change it there.

May the commands be with you! Commands to secure your Storage Account

Just two clicks – and it’s done. Public access to your resource is blocked once again, right? At least, it is something that you could assume by looking at the configuration in the Portal. After all, there is nothing that would indicate otherwise. Let’s see what Azure PowerShell and CLI have to say:

  • Azure PowerShell module
PS C:\Users\username> Get-AzStorageAccount -ResourceGroupName RG-Demo -Name st0r4ge1986 | Select-Object StorageAccountName,ResourceGroupName,PublicNetworkAccess
StorageAccountName ResourceGroupName PublicNetworkAccess
------------------ ----------------- -------------------
st0r4ge1986        RG-Demo           Disabled
PS C:\Users\username> Get-AzStorageAccountNetworkRuleSet -ResourceGroupName RG-Demo -Name st0r4ge1986
Bypass              : AzureServices
DefaultAction       : Deny
IpRules             : [73.12.157.35,...]
VirtualNetworkRules :
ResourceAccessRules :

So, my best buddy, PowerShell, told me that public access to my Storage Account is disabled. However, those IP addresses allowed before are still there. Maybe we should ask Azure CLI for a second opinion on this?

  • Azure CLI
PS C:\Users\username> az storage account list --query "[].{name:name,publicNetworkAccess:publicNetworkAccess,networkRuleSet:networkRuleSet}"
[
  {
    "name": "st0r4ge1986",
    "networkRuleSet": {
      "bypass": "AzureServices",
      "defaultAction": "Deny",
      "ipRules": [
        {
          "action": "Allow",
          "ipAddressOrRange": "73.12.157.35"
        }
      ],
      "resourceAccessRules": [],
      "virtualNetworkRules": []
    },
    "publicNetworkAccess": "Disabled"
  },
[…]

We have pretty much the same information here. So, what does it actually mean? What happened after we changed the firewall setting from Enabled from selected virtual networks and IP addresses to Disabled? Effectively, from the network connection perspective, nothing changed. When you restrict Storage Account public access only to a defined list of addresses, you actually create an exception that takes higher priority over firewall restriction blocking public access. As a result, any user connecting to your resource from the network with a public IP that you allow-listed before, will still have access to your data! If you want to make sure that all connections are blocked, you should remove all exceptions that are no longer necessary. On the Azure portal you can just switch back to Enabled from selected virtual networks and IP addresses, delete the exceptions, and switch back to Disabled. This will solve the case.

Connect with the author on LinkedIn!

Trust but verify your cloud environment configuration

What I have just presented in this article is an example of a challenge you will face when using a public cloud. It is not really a bug in the Azure Storage Account firewall – just the way it is designed – this behavior is intentional and well-documented. The public cloud must balance between speed of deployment, ease of configuration, and security. This is why there is no ultimate default configuration suitable for every case and every scenario. Sometimes, having a Storage Account publicly accessible is perfectly fine, and sometimes it can be a catastrophic mistake. According to the shared responsibility model, it will be your task to find the perfect set and prevent any misconfigurations.

Krzysztof Demczuk
Krzysztof Demczuk IT Security Consultant