Friday, August 28, 2026

Azure: Bicep template for load balancer

 The following Bicep template deploys a load balancer in Azure. It has two front-end IPs and two back-end pools with each two pre-allocated IPs. It can be deployed before any back-end resources are deployed. Once the back-end resources are deployed with the correct IPs, they will be automatically added in the pool.

It has a health probe that listens on port 80 and two load balancing rules that connects each of the front-end IPs with the respective back-end pool.

This LB setup can be used for various scenarios, one is for firewall appliances such as Palo Alto where you typically have two FWs running each with two interfaces for traffic (and an additional one for management traffic) and then an LB in front to manage traffic to the two appliances.

Loadbalancer.bicep

Loadbalancer.parameters.json

 

Monday, July 6, 2026

Azure: Convert ARM templates to Bicep and Bicep to ARM

 If you have some old ARM templates in your environment, it can make sense to update them to Bicep to benefit from newer features and simplified syntax.

There are some general guidelines on the Microsoft site here.

To convert the ARM templates to Bicep, you can use the Bicep tools. Bicep tools can be installed as an AZ CLI version, install info (cmd structure is: az bicep decompile) or as a Bicep CLI version, install info (where the cmd is e.g.: bicep decompile).

To create a Bicep file from an ARM template, use the following command:

bicep decompile <ARM template filename>

or

az bicep decompile --file <ARM template filename>

This will create a Bicep file and place it in the same folder as where the ARM template is located.

You can also convert from Bicep to ARM by using the bicep build command. This can be useful if you want to see what the Bicep is translated into before it is deployed. Note that this command does not account for a parameters file (if you have that), only the Bicep file itself.

bicep build <Bicep file name>

or

az bicep build --file <Bicep file name>

When you have converted a template, it is a good idea to run the deployment with the what-if option to check that nothing changes compared to what is already deployed. See here for more on using what-if.

Note that LLMs have gotten better at ARM templates and Bicep lately. Now, it is quite efficient at suggesting improvements and sanity checking code. This could be for example if you have repetitive code that can be optimized with a copy loop or if you want to optimize parameter naming with concat to construct names.

Thursday, July 2, 2026

Azure: VNet peerings to multiple VNets with Bicep and for-expression

 VNet peerings in Azure are slightly more complicated than other resources. The reason for this is that a single VNet peering consists of two distinct resources, a local peering and a remote peering - and the remote peering is often placed outside of the current resource group (or scope).

If both VNets are in the same resource group (RG), then it is straight forward. If, however, the remote VNet is in another resource group, but in the same subscription, or in another subscription altogether, then this must be handled separately.

With ARM templates, this can be done using nested templates.  For Bicep you must use a module (basically another Bicep file that is referenced from the main file).

In the template that I'll reference below, it has a for-expression, or a loop, so that multiple peerings can be created by just updating the parameters file.

If you specify just a VNet name and an RG, the template will assume the remote VNet is in the same subscription. If you add a subcriptionId to one or more objects in the array, it will look for the RG in that subscription.

Note that all VNets must already be deployed.



Below are the files including the module. Note that the module must not be deployed itself only referenced (that is if you have a pipeline set up for deployment).

bicep file

param file

module file




Friday, April 24, 2026

Convert column of data to string in Excel

 If you have a column of data in Excel, it can be converted to a string using TEXTJOIN.

This can be helpful e.g. if you have a script that only takes input in a certain format.

Simply add the data to be converted in column A and then add the following formular in cell B2:

="('" & TEXTJOIN("', '"; TRUE; A2:A1000) & "')"

In the below example, I have a list of IP ranges in column A and these are converted to a string. Single quotes are added around each IP range and the whole string is enclosed in parenthesis. This can be adapted as needed.



Tuesday, April 21, 2026

Azure: Bicep file for Infoblox vNIOS in HA Cluster mode

 Infoblox released a high availability (HA) cluster feature for their vNIOS marketplace image (DNS server and more) around August 2025.

This is an active/passive cluster and it works by adding an additional NIC to two Infoblox VMs and then adding permissions to the VMs so that they can move a virtual cluster IP between them. There is no witness server.

The main differences between a standalone Infoblox VM and an HA cluster Infoblox VM are:

  • 1 x additional NIC per VM. The standard is two NICs, so three NICs in total (included in bicep template)
    • Note that the virtual machine SKU must support 3 NICs. Standard_DS12_v2 will work but Standard_DS11_v2 will not, just as an example.
    • The new NIC should be added in the same subnet as LAN-1 (so the data interface, not the management interface)
  • Using a SAMI must be enabled for the VM (included in bicep template)
  • A custom RBAC must be created (separate step) and assigned to the Infoblox VMs via s SAMI (system-assigned managed identity) (included in bicep template).
  • If you are assigning the SAMI at resource group level, ensure that the RG containing the VNet is also added. This can be done in Bicep by referencing a module (as opposed to nested ARM templates (included in bicep template)
  • In NIOS (this is a post-deployment step once VM is up and running), configure a DNS resolver in the Grid Properties Editor, see link.
Previously, Infoblox had official ARM templates that could be used to deploy the marketplace images, but this is no longer the case. Their recommendation is to either deploy from portal via clickOps, use CLI, or alternatively go through the deployment steps in the portal and then export the automation templates at the last step immediately before deploying (this information we have gotten by asking the vendor directly).

However, these ARM templates include some unnecessary resources and checks which make them unnecessarily complex. The fact that they have a mandatory dedicated storage account for boot diagnostics and are not using managed storage accounts, indicates that they are not putting a lot of effort into these templates.

An alternative that we are trying out currently is to deploy the marketplace image via the portal using clickOps and then once deployed, we export the bicep file of what has actually been deployed. It takes a bit more effort to modify the template (NICs and NSGs have to be added manually) but it simplifies the templates in the end.

Bicep files

Here are examples of bicep file, param file, and a module that is used to add permissions to an additional resource group if required:
Note, that in the bicep file the NSG is commented out. This is because we already have an NSG associated at the subnet level which makes an additional NSG at NIC level redundant. But if you don't have an NSG already, then use the one in the file.

Links to documentation

In the following will be listed relevant links for installation instructions from Infoblox:


General info around vNIOS with High Availability option (including how to assign the custom RBAC to the SAMI)


Other info

The marketplace image terms and conditions must be accepted up front before vNIOS can be deployed. It is done at subscription level, see link for more info.





Wednesday, March 18, 2026

Azure: Enable and configure subnet peering

 Subnet peering in Azure is a feature that was introduced in April 2025. My guess is that not that many organizations are using it, as it has a quite specific/limited use case.

Subnet peering is enabled on the VNet peering resource. So you still have a local and remote VNet peering resource that peers two VNets but you specify a property in those peerings (peerCompleteVnets: false) that enables the subnet peering - and disables full VNet peering.

A VNet peering resource cannot be both a VNet peering and a subnet peering, it is either or.

Prerequisites

Before being able to deploy this feature, it has to be enabled at the subscription level. According to the documentation, a request form must be filled out first. But when you do that, Microsoft just replies with the instructions on how to enable the feature.

They do this because there are some hard limitations for the use currently, the most important one being the following:


Note: The following instructions to enable feature on subscription level use AZ CLI:

# Log in to Azure: 

az login

# Set the correct subscription: 

az account set –subscription <sub id>

# Verify correct sub is set:

Az account show

# Enable subnet peering on subscription

az feature register --namespace Microsoft.Network --name AllowMultiplePeeringLinksBetweenVnets

# You will be prompted to run this command as well to complete the registration:

az provider register -n Microsoft.Network

# Verify

az feature show --name AllowMultiplePeeringLinksBetweenVnets --namespace Microsoft.Network --query 'properties.state' -o tsv

# If done correctly, the command will output (see screenshot below): Registered


Enable subnet peering on VNet peering resource

You can enable subnet peering via az cli commands or directly in the ARM/Bicep template.

Example using AZ CLI (that I have tested):

az network vnet peering create --name vnet-conn-weu-001_to_vnet-conn-weu-004 --resource-group rg-deploymentstack-001 --vnet-name vnet-conn-weu-004 --remote-vnet vnet-conn-weu-005 --allow-forwarded-traffic --allow-gateway-transit --allow-vnet-access --peer-complete-vnet false --local-subnet-names snet-conn-weu-002 --remote-subnet-names snet-conn-weu-001

az network vnet peering create --name vnet-conn-weu-004_to_vnet-conn-weu-001 --resource-group rg-deploymentstack-001 --vnet-name vnet-conn-weu-005 --remote-vnet vnet-conn-weu-004 --allow-forwarded-traffic --allow-gateway-transit --allow-vnet-access --peer-complete-vnet false --local-subnet-names snet-conn-weu-001 --remote-subnet-names snet-conn-weu-002

Example using Bicep:

When configuring this via Bicep, there are two main changes to be done to the VNet peering resource:

1) The property peerCompleteVnets for the VNet peering must be set to false

2) localSubnetNames and localSubnetNames values must be specified as well. The values are the subnet names, not the subnet IP ranges. See screenshot below:


When the subnet peering has been implemented, it can be viewed from the Azure Portal by going to the VNet peering itself (under VNets). Under Peering type, Subnet will be active, see below:




Friday, January 23, 2026

Enable VNet encryption in Azure

 It is possible to enable encryption on a VNet so that in-transit traffic between virtual machines within the VNet is encrypted (using DTLS). See MS article here for more info.

It is straightforward to enable, it can be done in different ways e.g. via the portal or via code.

To enable in Azure portal, go to the VNet -> Overview -> Properties tab -> click the Encryption link currently saying 'disabled' -> check the 'enabled' box -> save the changes


To enable it using Azure Verfied Modules, you just add vnetEncryption: true under VNet parameters, see below, or full example on GitHub.

module vnet 'br/public:avm/res/network/virtual-network:0.7.2' = {
  name: 'vnetDeployment'
  params: {
    name: vnetName
    addressPrefixes: vnetAddressPrefixes
    subnets: [
      {
        addressPrefix: subnetAddressPrefix
        name: subnet_01_name
        networkSecurityGroupResourceId: networksecuritygroup.outputs.resourceId
      }
    ]
    vnetEncryption: true
  }
}

If you look at the final ARM template result in the portal, the following section is added under VNet paramters:

"encryption": {
                    "enabled": true,
                    "enforcement": "AllowUnencrypted"
                }

The enforcement flag only allows AllowUnencrypted for now. MS mentions that an option to drop unencrypted traffic will be added later.

Note that there are certain requirements and limitations, for example, certain VM SKUs must be used for this to work, see more here.

Monday, November 3, 2025

Using Git rebase to sync latest changes in main branch to feature branch

You have a scenario where you create a feature branch from the main branch. Then you work for a while on the feature branch and want to merge these changes into main.

But in the meantime changes have also been made to main and you are unsure if there are now conflicts.

With Git rebase you can take all the latest changes from main and sync them into your current feature branch. And all your current commits will be added on top of those changes from main (this keeps the commit history clean). It is similar to if you started over on a fresh feature branch from main and then added all your changes again.

It is also described here and on YouTube here.

To use git rebase, run the following commands:

Go to main branch first and get latest changes:

git switch main

git pull

Then switch to your existing feature branch:

git switch feature/my-feature-branch

If others have worked on the same feature branch, you can pull the latest changes with:

git pull --rebase (optional)

If only you have worked on the feature branch you can skip that (as you know you have the latest changes) and then run the rebase command:

git rebase main

This will add all the latest changes to your local feature branch.

Then you need to push those changes to the remote feature branch (typically, so you can create a pull request and merge everything into main):

git push --force-with-lease

You cannot run a regular git push since the local and remote branch history are no longer the same (since changes from main have been interjected into the feature branch). Using --force-with-lease is safe as it checks that remote and local are still the same before pushing and if not it will fail.

That's it.

If you run into a merge conflict you can try and open the file and update as needed and then run: 

git add the-file-name-you-updated

git rebase --continue

Or if you want to cancel entirely, run:

git rebase --abort

To see more info on general Git usage and commands, see here.

Monday, September 22, 2025

Compare two columns in Excel

 If you have two large lists that you need to compare (to identify what items are missing in one of the lists), this can be done in excel.

Add the first list (the bigger of the two) in column A and the other list in column B.

For column C, add this formula in cell C2 and drag it all the way down to the bottom column C:

=IF(COUNTIF($B:$B; A2)=0; "Item in column A is missing in column B"; "Item exists in both lists")

What it does is for each cell in column A, it will run through all the items in column B and look for a match and note if it finds one, see screenshot below.

An example xlsx file is available on GitHub (choose download raw file).



Saturday, September 6, 2025

Create architecture diagrams with Mermaid and ChatGPT

 Mermaid is a practical tool that can create all sorts of diagrams as code. And if you combine it with an LLM, you can create it with a prompt.

To view the results, go to https://mermaid.live and add the code in the box on the left.

As an example, I had ChatGPT create a hybrid cloud architecture diagram with an on-prem location connected to Azure via an ExpressRoute. For encryption, VPN runs inside the ER circuit. The Azure setup is hub-spoke meaning the central networking components are in the hub and are connected to multiple spoke VNets. Traffic flows through an Azure Firewall.

I have put the code in a markdown file on Github (click Raw to view code).

Result looks like below:


If saving the mermaid code in a markdown file (.md) it will render the diagram directly in Github as long as it is wrapped with ```mermaid at the beginning and ``` at the end.

And if you copy raw code to mermaid.live, only use the text inside the wrapper.

Here's what it looks like at mermaid.live:



You can also preview the diagram in Visual Studio Code if you install the Markdown Preview Mermaid Support extension (and save file as .md). To view diagram, just right-click the .md file and choose "Open preview". It looks like this:


The native Mermaid file format extension is .mmd and there are extensions for VS Code for that as well.



Tuesday, April 15, 2025

Azure Bastion Developer - shared Bastion pool

 The Azure Bastion is useful for connecting securely to virtual machine without exposing the VMs to the internet using public IP's.

This however, requires a dedicated Bastion instance to be deployed and an AzureBastionSubnet.

With Bastion Developer, test/dev users can connect to the local IP of the VM via Bastion using a shared pool, so no dedicated setup required. The features are limited though. See here for more info.

To use, in the portal simply go to the VM -> Connect -> Bastion.

Add credentials and click Connect. This will open a remote session in the browser, see below:








Azure: Troubleshoot connectivity to a key vault with a private endpoint

 If you have a key vault that you can't reach there can be multiple reasons for this. Two of the main ones are DNS issues and firewall blocks.

This post will go over those two issues and show a couple of ways to test for connectivity.

When working in hybrid setups with an on-prem location connected to Azure either via VPN or ExpressRoute then it happens that you can create and see the key vault (this also goes for e.g. storage accounts and other PaaS services) but you get an error when trying to add a secret or other content to it. The error can mention e.g. "the connection to the data plane failed".

To troubleshoot, first we ensure that the local IP of the private endpoint can be resolved.

nslookup myown-keyvault.vault.azure.net

On Linux you can use the command dig to get slightly better lookup details than with nslookup:

dig myown-keyvault.vault.azure.net

This should resolve to a local IP. If it doesn't resolve at all or if it returns a public IP, there is something wrong with the DNS setup.

More info on troubleshooting DNS can be found here.

If that works, you can check for connectivity from your source. This can be done in a couple of ways and either of them is fine.

From Windows run:

tnc myown-keyvault.vault.azure.net -port 443

From Linux run (netcat and nc is same command):

nc -zv myown-keyvault.vault.azure.net 443

All data to a key vault goes over port 443, so if you have connectivity on that port and it can resolve the IP, then you should be good.

Alternatively try:

$(Invoke-WebRequest -UseBasicParsing -Uri https://myown-keyvault.vault.azure.net/healthstatus).Headers

Or from Linux:

curl -i https://myown-keyvault.vault.azure.net/healthstatus

There is more info on troubleshooting behind a firewall here.

Thursday, April 10, 2025

Azure: Adding KQL queries as Resource Graph queries

 Using the Resource Graph Explorer can be helpful to retrieve information about your Azure environment using KQL. If you have certain queries that you run on a frequent basis and want to save, this can be done under Resource Graph queries.

If they are saved as 'shared' queries they can be viewed and run by others. Private queries can only be seen by you.

Resource Graph queries can be added via code and it is also supported by Azure Verified Modules.

The below screenshot shows what it looks like, when a few queries have been added:


If you click one of the queries, it will show the query itself in a new window:


And on the Results tab, you can run the query directly:


The Bicep AVM files are available on Github, see link.

The queries can be placed in any resource group.

Here are some examples of more queries from MS.




Tuesday, April 8, 2025

Retrieve custom DNS server settings on VNets using Kusto (KQL)

 You can use Kusto Query Language (KQL) to retrieve information about your Azure environment across subscriptions.

It's a fast tool and very useful in larger environments with many subscriptions and resources.

The following example shows how to list all VNets in the environment including their custom DNS server settings.

Go to Azure Portal -> Azure Resource Graph Explorer

In the query window, add the following KQL:

Resources
| where type == "microsoft.network/virtualnetworks"
| extend dnsServers = properties.dhcpOptions.dnsServers
| project id, name, dnsServers

Click: Run query

Result will look like below (custom DNS only set on one VNet):



You can download the content as a csv and import into xls for sorting and filtering.



Wednesday, November 20, 2024

Azure: Creating a route table in Bicep and addressing linter rule warning

 I was creating a route table in Bicep and using an example from MSFT, see example here.

The example uses the 'contains' function which throws a warning when deploying with a suggestion to simplify the syntax. Below you can see the warning:


The warning links to the Linter rule - use safe access page.

The suggested change can be seen below. It still performs the same function - it checks if the value exists, if it does, it uses it, if not it sets the value to null.


The updated example can be found on Github here (it uses routes for Databricks as an example, but can be replaced with your own routes).

Tuesday, November 5, 2024

Azure: Creating a naming convention for cloud resources

 Creating a maintaining a well functioning naming convention can be surprisingly difficult. And it can lead to many a heated discussion. One of the reasons for this is that there isn't necessarily one right answer and in the end it's about convention and just making a decision and sticking to it.

To help out with the standardization of naming resources in Azure, MSFT has a good article, under the Cloud Adoption Framework, which has suggestions for most of the Azure resources. It's a good starting point:

https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming

Friday, October 4, 2024

Azure: Create a Workbook for centralized NSG log search - using VNet flow logs

 NSG flow logs will be retired in 2025, see more details here, and replaced by VNet flow logs.

This article will describe how to install a new Azure Workbook that enables centralized NSG log search using VNet flow log data. Note that to be able to retrieve and view logs with this workbook, VNet flow logs must deployed and configured in advance (you can deploy the workbook up front, but it will return empty queries).

The workbook is based on an existing workbook for NSG log search that uses NSG flow log data (see NSG workbook here). The logic is the same in the new workbook, it just retrieves data from another source (or another table in the Log analytics workspace, to be precise).

First, let's view the final result. Below you can see a screenshot of the workbook:


To install the workbook, do the following:

Download the workbook file from Github.

Go to Azure Portal -> Monitor -> Workbooks -> Click '+New'

Click on the Advanced editor, see below:


Choose Gallery template, then paste in the workbook code and click apply, see below:


That's it, this will create the workbook.

To ensure that you can find the workbook via Portal -> Monitor -> Workbooks, you have have to go into settings and choose Azure Monitor as a resource, see below (this might be set by default):



If you link it only to the log analytics workspace, then you have to navigate to the workspace first and then choose the workbook menu to see it.

If done right, you can navigate to Portal -> Monitor -> Workbooks -> Workbooks tab -> Click workbook to view, see below:


Below you can see the main Kusto query that the workbook uses (this is also included in the workbook file itself):


Note that if you run this as a query it won't return any results.

If you want to run a Kusto query directly (that returns a similar result), do the following:

Go to Portal -> Monitor -> Logs - Choose Kusto mode (instead of simple mode) -> paste in the below query and click run:

NTANetAnalytics
| where SubType == "FlowLog"
| extend Protocol = case(L4Protocol == 'T', "TCP", L4Protocol == 'U', "UDP", L4Protocol)
| extend TimeGenCET = datetime_utc_to_local(TimeGenerated, 'Europe/Stockholm')
| extend TimeGeneratedCET = format_datetime(TimeGenCET,'dd/MM/yyyy [HH:mm:ss]')
| project-rename NSGFL_Version = FaSchemaVersion
| project-rename AllowedOrDenied = FlowStatus
| project TimeGeneratedCET, VNet = split(TargetResourceId,"/")[2], NSG = split(AclGroup,"/")[8], SrcPublicIps, SrcIp, DestIp, DestPort, Protocol, L7Protocol, FlowDirection, AllowedOrDenied, AclRule, NSGFL_Version, FlowEncryption, Source_subnet = split(SrcSubnet,"/")[2], Destination_subnet = split(DestSubnet,"/")[2]  

You can see an example below:



Azure: NSG flow logs will be retired in June 2025

 On September 26, 2024 it was announced by MSFT that NSG flow logs will be retired in 2025. More specifically no new NSG flow logs can be created after June 30, 2025 and existing NSG flow logs will be retired on September 30, 2027, see link here or screenshot below:


The recommendation is to switch to VNet flow logs which covers the same as NSG flow logs plus some more things, see more info here. It also simplifies the setup somewhat as there will only be one flow log resource per VNet as opposed to one per NSG.

If you want to read more about how VNet flow logs work, which tables it creates in log analytics workspace, and how to query data (using Kusto queries), I can recommend this great article from cloudtrooper.net.

Depending on how NSG flow logs have currently been configured in your environment, this can be a bit complicated to address and involves multiple steps. At current client the NSG flow logs are deployed via an Azure policy (using the DeployIfNotExist effect). Logs are shipped both to a storage account and to a log analytics workspace. An Azure workbook is in place which reads data from the LA workspace so that NSG flow logs can be viewed and sorted in an easy manner (specifically this relates to all traffic in and out of the NSGs, source/dest, port, protocol, etc.).

Before retiring NSG flow logs, a similar setup has to be in place for VNet flow logs. The good news is that both these flow log types can run in parallel. They store data in the LA workspace in two different tables. So VNet flow logs can be set up and verified before retiring NSG flow logs.

There are two main items to be addressed (will depend on your specific setup). These will be described in separate posts:

  • An Azure policy that deploy VNet flow logs for all VNets (there is a built-in policy, but we had to modify it a bit to allow for multiple subscriptions. Update 2024.10.07: The built-in policy actually works, it's just a bit unclear that it will work across subscriptions since a strongType parameter is used for choosing a the network watcher resource)
  • An Azure workbook to view/search through NSG logs using the VNet flow logs data, see article here.

Friday, September 13, 2024

Using Azure Verified Modules (AVM) - Bicep

 In January 2024 Microsoft launched a new initiative called Azure Verified Modules (AVM). It's a collection of official and supported Bicep and Terraform modules that makes it easier to deploy resources in a standardized fashion as-code.

It's easy to use and fast to get started. And I was actually surprised at how well it works. One of the reasons for this initiative is that until now there hasn't been a formal, centralized repository for modules or templates so people have been relying on either there own or some public repo that might not be maintained over time.

The link for AVM is: http://aka.ms/avm

And the getting started guide (which is quite good) is here: http://aka.ms/avm/using

You should have VS Code installed and the Bicep extension. And Azure CLI, see install info here for Windows or here for MacOS.

And then you just follow the guide.

To use the modules you have to have internet connection from your source. If not, you can download a local copy of all the content and reference them locally.

For each resource module there is a basic version and an extended version with more options. You can copy the additional parameters from the extended version into the basic version or start with the extended version and remove the parts you don't need.

The good thing about modules is that most of the code (or the Bicep file) is managed/written by MSFT and you only have to reference the module in your Bicep file and fill in the relevant parameters. Below you can see a file for a basic blob storage account. 


There are several ways to deploy the code, but one is using Azure CLI, see below:

From VS Code, open a terminal and login to Azure:

> Az Login

If you are using the newest version of Azure CLI, you will be presented with a list of subscriptions available, choose the relevant subscription (alternatively run: az account set <sub name> see more info here).

Navigate to the folder where your Bicep files are located.

Deploy the Bicep with a what-if first (optional):

> az deployment group what-if --resource-group "<resource group name>" --template-file "<bicep file.bicep>"

And to deploy:

> az deployment group create --resource-group "<resource group name>" --template-file "<bicep file.bicep>"

I tried tested out a few of the modules, and they all worked fine. These are:
  • Blob storage account
  • Private DNS zone (for key vaults)
  • Private endpoint with privateDnsZoneGroup (adds A record in PDNS zone), requires existing PDNS zone for blob storage
  • Simple Windows virtual machine with public IP
  • VNet with one subnet and a VNet peering (requires existing Hub VNet)
The files can be found on GitHub, see link here.






Friday, August 30, 2024

Azure: ARM template for resource health alerts

 Azure keeps track of the general resource health of a number of components. This information can be viewed under the resource -> Help -> Resource health. However, this information is available only in the portal. To receive alerts around resource health, this must be configured separately.

Resource health alerts belongs, in my opinion, in the category of essential monitoring. You want to know if any of your key components become unavailable or degraded. Once this is setup and running, then implementing utilization based alerts would be the natural next step. See here for example of a VPN tunnel bandwidth utilization alert.

Resource health alerts can be defined on a per component type level. This means that you don't have to have any of the components deployed or specified in advance. If you deploy a health alert for e.g. VPN gateways, then all existing and future VPN gateways will be included in the scope (this will also include ExpressRoute virtual network gateways).

The ARM template in this example (Based on this MSFT ARM template) is useful for a connectivity hub where you have components such as VPN gateways, connections, firewalls, and load balancers.

If you want to add or remove components, it is done in following section of the code:



Once the alert is deployed, it can be viewed in the portal under Monitor -> Alerts -> Alert rules, see below:



The ARM template also deploys an action group which sends the alerts as emails to the specified address in the parameters file.

The files are available on GitHub:

alert-ResourceHealthAlert-weu-001.json

alert-ResourceHealthAlert-weu-001.parameters.json