I love Azure work - I think it is a great platform. Even so, whilst working in it over the years, you occasionally come across a few random things that make you stop and go “huh”?! Some of these are just not as well-known, and others are just downright weird. In this article, we will explore a few of them!
Know even more fun facts? Share your favourites with a comment below 😊.
Public Disks
I see this one a lot. Organisations go to the effort of ensuring they have private endpoints for their storage accounts, SQL servers, Key Vaults, but their Virtual Machine disks are left there open to the world. Ok… I’m being a little dramatic, but it’s kind of true.
As you may well know, managed disks in Azure (not the older classic disks) are actually just VHDs stored in Azure Storage account that is managed by Microsoft. By default, these are publicly accessible when the VM is deallocated.
Don’t believe me? Go and take a look at the network settings of one of your disks and see for yourself…
With this public setting, anyone with the correct authentication and authorisation (which in itself reduces the risk here a lot) can export the disk when the VM is deallocated.
Even more interestingly, is that the Virtual Machine API (which creates the OS disks) doesn’t expose this as a setting, so you cannot set it as part of the VM creation - https://learn.microsoft.com/en-us/rest/api/compute/virtual-machines/create-or-update.
Once the OS disk is created however, you are able to set it retrospectively on the disk resource. I’vepersonally utilised Azure policies in environments to ensure this is set on all disks as a belt and braces approach. An example of such a policy (in this case using Contributor for remediation - this could be scoped down) is shown below:
{
"name": "Disk-No-Public-Access",
"properties": {
"displayName": "Configure managed disks to disable public network access",
"policyType": "Custom",
"mode": "Indexed",
"description": "Disable public network access for your managed disk resource so that it's not accessible over the public internet. This can reduce data leakage risks. Learn more at: https://aka.ms/disksprivatelinksdoc.",
"metadata": {
"version": "2.0.0",
"category": "Compute"
},
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy"
},
"allowedValues": [
"Modify",
"Disabled"
],
"defaultValue": "Modify"
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/disks"
},
{
"anyOf": [
{
"allOf": [
{
"field": "Microsoft.Compute/disks/publicNetworkAccess",
"equals": "Enabled"
},
{
"field": "Microsoft.Compute/disks/networkAccessPolicy",
"notEquals": "DenyAll"
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/disks/networkAccessPolicy",
"equals": "AllowAll"
},
{
"field": "Microsoft.Compute/disks/publicNetworkAccess",
"notEquals": "Disabled"
}
]
}
]
}
]
},
"then": {
"effect": "[parameters('effect')]",
"details": {
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"conflictEffect": "deny",
"operations": [
{
"operation": "addOrReplace",
"field": "Microsoft.Compute/disks/networkAccessPolicy",
"value": "DenyAll"
},
{
"operation": "addOrReplace",
"field": "Microsoft.Compute/disks/publicNetworkAccess",
"value": "Disabled"
}
]
}
}
}
}
}
The same limitation doesn’t exist for data disks, as you create these separately to the VM, though they are still public by default.
It isn’t an all or nothing setting however, you can also disable public access and enable private access via a “disk access” resource, though for me I’d rather just set it to disabled, and enable it briefly if I ever need it - which is pretty rare.
Subscription Policies
I was working with Palo Alto Prisma Cloud (which has now been absorbed under the Cortex name) on a previous project, and saw an alert flag up I wasn’t aware of. It was referencing the ability for subscriptions to be moved between tenants. Sure enough, by default this is set to “Allow everyone” by default (if they have permissions of course), but this can be changed to lock it down further.
Under subscriptions, you’ll see a “manage policies” button. Opening this will allow you to disable whether subscriptions can be moved in or out of the tenant, as well as any users that can bypass:
I’ve never personally had a need to move subscriptions between tenants, so seems sensible to turn this off for me! But of course, there will be scenarios you may need this - perhaps in certain mergers and acquisitions.
Private DNS Zone Redundancy
Adam Stuart over at Microsoft has a great article on the approaches to private DNS zone architecture options which can be found here.
The TL;DR for what we’re talking about here is…
- Private DNS zones and the records they contain are globally resilient, so you don’t need the multi-zone architecture strictly for this.
- With a single region approach, you have to update DNS records during a failover event of certain services such as Azure SQL and Storage Accounts.
Now, having implemented both approaches, I can say this:
- The multi-zone architecture is a bit of a pain in the arse and results in private endpoints all over the place, even if you don’t really need them.
- But, no one really wants to be updating DNS records during a failover event.
On the latter though, this could be automated. But this got me thinking. Microsoft recommendations are that Azure resources should be in a resource group in the same location…
To minimize the effect of regional outages, we recommend that you place resources in the same region as the resource group. For more information, see Resource group location alignment. 1
Which makes sense. If a region is blown out of the water, you may not be able to update even the metadata relating to the resource group. However, if our private DNS zones live in a single resource group, won’t they too be fallible to this, and prevent us from actually making the necessary updates during a disaster?
I raised an issue on Adam’s repository, and he kindly came back with…
The team responsible for Private DNS is in the process of updating this doc, which should answer your question when its released Azure Private DNS zone resiliency | Microsoft Learnhttps://learn.microsoft.com/en-us/azure/dns/private-dns-resiliency
At the time of writing, the article still hasn’t been updated, so I’ll eagerly continue to give it a refresh once in a while and probably stick with the multi-zone architecture till I have a concrete answer!
The Ever Randomly Changing Case of Resource Groups!
Ok, so this probably isn’t a “did you know” - everyone knows this! In API responses (both in the portal and Terraform), Microsoft will seemingly make resource group names uppercase from time to time. WHY MICROSOFT?! WHY IS THIS!!!
This has been this way for as long as I can remember. I don’t know why. I’d love to know why. Someone please tell me why.
The Polymorphic VirtualNetwork Tag
You’ll have noticed that by default in your Network Security Groups, you have rules that reference “VirtualNetwork”. It would be a sensible assumption to think this means “this virtual network”, but that would be incorrect!
This tag essentially means:
- This virtual network…
- …and any peered virtual networks…
- …and various routes learned in the peered virtual network…
- …and any routes in this VNets User-Defined Routes (UDRs)
When I first came across this, I was perplexed! I happened to be looking at the effective rules and couldn’t understand why 0.0.0.0/0 was in there.
This behaviour is described in the docs here - https://learn.microsoft.com/en-us/azure/virtual-network/service-tags-overview#:~:text=Yes-,VirtualNetwork,No,-Note and there is another blog on it here from someone else that had the same “WTF” moment - https://journeyofthegeek.com/tag/routing/.
Now, in the architecture in question, it wasn’t an issue. We were routing 0.0.0.0/0 up to a hub firewall, so the spoke wouldn’t directly expose anything to the Internet anyway, even if it had a public IP.
I also don’t use UDRs to replicate firewall rules - I only use them to microsegment spokes. So, allowing everything inbound or outbound isn’t really a problem - as the firewall has already filtered it.
That being said, I just don’t like relying on those default rules. I always place explicit rules above them to ensure I am 100% clear on what I’m controlling. My typical spoke NSGs look like this…
- Inbound Rules:
- Permit rules for intra-VNet traffic
- Deny intra-VNet traffic (prevent subnet to subnet comms in the spoke unless I explicitly want them)
- Permit anything inbound (this will already have been filtered by a firewall)
- Note: This actually causes issues with certain Azure policies - it is typically actually “permit RFC1918 and specific public IPs if needed” rather than “any”
- Outbound Rules:
- Permit rules for intra-VNet traffic
- Deny intra-VNet traffic (prevent subnet to subnet comms in the spoke unless I explicitly want them)
- Permit anything outbound (this will then be filtered by the upstream firewall)
Weirdly, when I tried to get a snip of this effective security rule output for this article, the portal no longer seems to show it. Instead, it just says “no additional prefixes” when looking at the details for the tag - something must have changed.
Conclusion
There are plenty more than this, and maybe I will do a part two soon. Just thought I’d quickly share some of these whilst they were top of mind! I’d love to hear what little gems you’ve come across.

