ARM Templates: Using resourceID function and dependsOn element

If you are an IT professional focused on infrastructure, you probably already realize the importance and beauty of ARM Templates, where we have a declarative way to build out our Azure environments. If you are a developer, it is just another JSON file that you know inside out.

At the end of the day, it doesn’t matter what your cup of tea is (dev or infra), you will see the benefits of using ARM Templates. And if you can combine that with Azure DevOps, the sky is not the limit because you can have pipelines for your several environments, which could be spread among different subscriptions. You will have a consistent deployment no matter what.

In this article, I want to focus on one of the most important functions, which is the resourceID and how we can leverage that to create some order in the deployment process using the dependsOn element. We are going to use a simple scenario: First, we are going to create a virtual network using ARM Templates. Later on, we will create network security groups and associate them with the virtual network.

Using resourceID function

When referencing other resources in ARM Templates, we need to provide their unique identifier to locate the resource. Using the ResourceID function we can provide a few pieces of information and retrieve the resource ID of any given resource.

The function is simple to use. In its basic form, we need to provide just two pieces of information which are the resource type and resource name, however, in some situations we need more details to find the resource, and we can add subscription id, resource group name (in situations where the resource is in a different resource group) and so forth.

resourceId(<subscriptionID>,<ResourceGroupName>,<Resource-Type>, <ResourceName1>,<ResourceName2>)

You may be wondering, where do I find the Resource Type? There are several ways to do that. The first way is to look for it on this Microsoft Azure resource page here; the second option is when using ARM Templates, just look at the type line of the resource and you will find it there; a third and easy way to spot the option is to check the id of the object. It provides you the resource type on it. (We will find out how to retrieve the ID in the next section.)

Using Resource Explorer to identify the ID of any given resource

There are several methods to find out the ID of any given resource. My favorite is using Resource Explorer, where we can navigate in the subscription and find the exact resource and on the right side, we will have all properties in a JSON format. In the example below, we can see the ID in the second line.

resourceId function

The format of the ID is defined with some dynamic data such as subscription ID and the virtual network name. Here is the text retrieved from the first lines of the virtual network that we created for this article.

"name": "VNET",
"id": "/subscriptions/3c062fc8-2da3-4704-9dbb-8f91ffb43902/resourceGroups/Network-VNET/providers/Microsoft.Network/virtualNetworks/VNET",
"etag": "W/\"2e119f6f-de11-4a5f-b08c-679136ca7fea\"",
"type": "Microsoft.Network/virtualNetworks",
"location": "eastus",
"tags": {
"displayName": "VNET"

When using ARM Templates, we can use the Outputs section of the ARM template to display the resource ID of a resource. In our scenario, we knew the name of the virtual network, so we used with the ResourceID function.

"outputs": {
"VNET-ResourceID": {
"type": "string",

resourceId function

Associating a network security group to a subnet

In our ARM Template, we created two resources: a Virtual Network with two subnets and we named them Servers and Quarantine, and a network security group , which has its name defined by the variable nsgName.

I’ve shared the entire ARM Template as a blog here at TechGenix, but the most important portion of the code is highlighted in the image depicted below.

resourceId function

The code required to add an existent network security group to a subnet is listed below. We are taking advantage of the resourceID function that we explored in the previous section. We are passing the resource type (Microsoft.Network/networkSecurityGroups) and the name of the NSG (defined by the parameters nsgName).

"networkSecurityGroup": {
"id": "[resourceId(‘Microsoft.Network/networkSecurityGroups’, parameters(‘nsgName’))]"

The result will be the network security group being associated with the servers subnet, as depicted in the image below.

resourceId function

That is great, but it fails when I run the ARM Template for the first time!

If you are running the ARM Template that creates a virtual network and a network security group, it is certain that it will fail at the first time. The main reason is that the virtual network will be created and it will try to use the network security group that is also being created at the same time, thus an error will be displayed. When we run a second time, then it will work, and that happens because in the second round the network security group will be already in place.

By default, Azure Resource Manager (ARM) will create resources in parallel. When we need to have some order in the process, then we need to play with dependsOn element for resources being provisioned within the same template.

To solve this problem, and make our ARM Template bulletproof, we need to use dependsOn at the virtual network resource level, where we are going to add the network security group as a requirement, before creating the virtual network resource.

resourceId function

Here is the code required to force the creation of a Network Security Group that is located in the ARM Template before creating the virtual network. Note that we are taking advantage of the resourceID function again.

"dependsOn": [

When executing the ARM Template, we can see the difference where the first resource to be provisioned is the network security group (Item 1), and once it is completed (Item 2), the Virtual Network provision kicks in.

resourceId function
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