ScenarioCert
AZ-104 ยท Deploy and manage Azure compute resources (20-25%)

Automate deployment of resources by using Azure Resource Manager (ARM) templates or Bicep files

Practice questions and explanations for the "Automate deployment of resources by using Azure Resource Manager (ARM) templates or Bicep files" objective of the Microsoft Azure Administrator exam. Skills measured as of 2026-04-17.

Skills in this objective

  • Interpret an Azure Resource Manager template or a Bicep file
  • Modify an existing Azure Resource Manager template
  • Modify an existing Bicep file
  • Deploy resources by using an Azure Resource Manager template or a Bicep file
  • Export a deployment as an Azure Resource Manager template or convert an Azure Resource Manager template to a Bicep file

Test yourself on this domain

Take the free 15-question test, or unlock all 150 questions and practice this domain on its own.

Sample questions

4 of the 10 questions we have for this objective, shown with the answer and the reasoning.

Automate deployment of resources by using Azure Resource Manager (ARM) templates or Bicep files

Oakridge Software wants a single Bicep deployment to create a new resource group named rg-billing and then deploy a storage account into it. The platform team writes: targetScope = 'subscription' resource rg 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: 'rg-billing' location: 'eastus2' } module storage './storage.bicep' = { name: 'storageDeploy' scope: rg params: { accountName: 'stoakbilling01' } } The file must be deployed from Azure CLI.

Which command should you run?

  1. Aaz deployment group create --resource-group rg-billing --template-file main.bicepA resource group deployment requires the resource group to exist already and cannot deploy a file whose targetScope is subscription.
  2. Baz deployment sub create --location eastus2 --template-file main.bicepA file with targetScope = 'subscription' must be deployed with az deployment sub create. The --location parameter specifies where the deployment metadata is stored and is required at subscription scope.
  3. Caz deployment mg create --management-group-id corp --template-file main.bicepThe file targets subscription scope, not management group scope. A management group deployment would reject the Microsoft.Resources/resourceGroups resource declared directly at that level.
  4. Daz deployment tenant create --location eastus2 --template-file main.bicepTenant-scope deployments are for tenant-level resources such as management groups and require different permissions; the file's targetScope is subscription.
Why: The deployment command must match the file's targetScope. Resource group, subscription, management group and tenant scopes each have their own az deployment subcommand, and scopes above resource group require a --location for the deployment metadata. Creating a resource group and then deploying into it from one file is the canonical subscription-scope pattern: the resource group is a resource at subscription scope, and a module with scope: rg deploys the storage account into it.
Automate deployment of resources by using Azure Resource Manager (ARM) templates or Bicep files

Pinecrest Medical uses a Bicep file named main.bicep that is deployed to the resource group rg-app-east. The file calls a module that creates a Log Analytics workspace: module logging './modules/workspace.bicep' = { name: 'loggingDeploy' params: { workspaceName: 'law-pinecrest' } } A new standard requires that all Log Analytics workspaces live in a dedicated resource group named rg-monitoring in the same subscription. The main.bicep file must continue to be deployed to rg-app-east, and the workspace module must not be rewritten.

Which change should you make to main.bicep?

  1. AAdd scope: resourceGroup('rg-monitoring') to the module declaration.A module can target a different scope than the parent file. Setting scope to resourceGroup('rg-monitoring') deploys the workspace into that resource group while the rest of main.bicep still targets rg-app-east.
  2. BAdd targetScope = 'subscription' to the top of main.bicep.Changing the file-level targetScope would require every resource in main.bicep to be valid at subscription scope and would break the existing resource group deployment of the file.
  3. CAdd targetScope = 'resourceGroup' to workspace.bicep and pass rg-monitoring as a parameter named resourceGroupName.targetScope = 'resourceGroup' is already the default, and a parameter named resourceGroupName has no special meaning; the module would still deploy into the parent's resource group.
  4. DReplace the module with a resource declaration that sets location: 'rg-monitoring'.The location property is an Azure region, not a resource group. A resource declaration always deploys into the scope of the file it is in.
Why: Bicep modules are the mechanism for deploying part of a template to a different scope. The scope property on a module can point to another resource group, a subscription or a management group, subject to permissions, without changing the parent file's targetScope. This is how a single deployment places application resources in one resource group and shared monitoring resources in another. The distractors confuse the file-level targetScope with the module-level scope, and the region property with a resource group.
Automate deployment of resources by using Azure Resource Manager (ARM) templates or Bicep files

Cobalt Crafts has a Bicep file that starts with: @secure() param adminPassword string @allowed([ 'Standard_B2s', 'Standard_D2s_v5' ]) param vmSize string = 'Standard_B2s' @minLength(3) @maxLength(15) param vmName string An administrator deploys the file and supplies vmSize = 'Standard_D4s_v5' and vmName = 'vm'.

What happens when the deployment is submitted?

  1. AThe deployment is rejected during validation because vmSize is not an allowed value and vmName is shorter than 3 characters.The @allowed and @minLength decorators are validation constraints that Resource Manager enforces before any resources are created, so the deployment fails validation.
  2. BThe deployment proceeds, vmSize falls back to the default Standard_B2s, and vmName is padded to 3 characters.Defaults apply only when no value is supplied. An invalid supplied value causes validation failure; Resource Manager never silently substitutes or pads values.
  3. CThe deployment proceeds and the VM is created with size Standard_D4s_v5 because the value is a valid Azure VM size.The @allowed decorator restricts the parameter to the listed values regardless of whether other sizes exist in Azure.
  4. DThe deployment fails only because adminPassword was marked @secure() and must be passed from Azure Key Vault.@secure() prevents the value from being logged in deployment history; it does not require Key Vault. The failure is caused by the other two parameters.
Why: Bicep parameter decorators are validation rules that run before deployment. @allowed limits a parameter to an explicit list, @minLength and @maxLength bound string or array length, and @secure() marks a value so that it is not stored in deployment history or outputs. A default value is used only when the parameter is omitted. Recognising that both supplied values violate their decorators is the whole question; the distractors describe behaviours Resource Manager does not have.
Automate deployment of resources by using Azure Resource Manager (ARM) templates or Bicep files

Larkspur Insurance deployed a virtual machine and its networking into the resource group rg-claims from a parameterized ARM template two months ago. Since then an administrator attached an extra data disk and changed the VM size in the portal. The team now wants a Bicep file that reflects the current configuration of the resources, including the manual changes, as the starting point for infrastructure as code.

What should you do?

  1. AIn the portal, open the original deployment under Deployments for rg-claims, download its template, and run az bicep decompile on it.The deployment history contains the template as it was submitted two months ago. It does not include the data disk or size change made afterwards in the portal.
  2. BIn the portal, open rg-claims, select Export template, download the generated template, and run az bicep decompile on it.Export template on a resource group generates an ARM template from the current state of the resources, including portal changes. az bicep decompile then converts that JSON into a Bicep file.
  3. CRun az bicep build against the original ARM template in the repository.az bicep build compiles Bicep into ARM JSON; it is the opposite direction. The repository template also lacks the manual changes.
  4. DRun az deployment group what-if with the original template and copy the reported differences into a new Bicep file manually.What-if shows the differences between the template and current state but produces no template, and manual transcription is error-prone and unnecessary when export is available.
Why: There are two different exports in Azure. Exporting from the deployment history gives you the exact template that was submitted at the time, which is useful for reproducing a past deployment. Exporting from a resource group or resource generates a template from the live state, which is what you want when the resources have drifted through portal changes. Once you have ARM JSON, az bicep decompile converts it to Bicep; az bicep build goes the other way. Exported templates typically need clean-up (hard-coded names, missing secrets), but they are the correct starting point here.

Written from the public documentation. Not affiliated with Microsoft. Official study guide.