February 23, 2021

Azure Resource Manager: IaC at Enterprise Scale

If you’re using Azure, Azure Resource Manager (ARM) is Microsoft’s native IaC solution. It provides a way to declaratively define infrastructure in JSON-formatted templates and deploy that infrastructure via the CLI, PowerShell, and the Azure Portal. It is well-integrated within Azure and supports rollbacks of failed deployments. ARM is very similar to CloudFormation in concept and execution. And while writing JSON isn’t fun, tools like the Visual Studio Code extension are quite good and make the process more bearable. And just like CloudFormation, ARM provides a few ways to promote code reuse.

Linked Templates

An ARM template can link to other templates to include them in a deployment operation. Like CloudFormation Nested Stacks, these templates allow you to compose a complex infrastructure architecture from smaller modules. With clear inputs and outputs and well-defined boundaries, linked templates are a good approach for driving code reuse.

Like any other ARM template, linked templates contain a contentVersion property that allows authors to version template changes. When adding a linked template, you can specify the contentVersion of the child template you expect to use. If the version you specified doesn’t match the contentVersion attribute of the template you linked to, ARM will fail the deployment, preventing you from deploying unknown changes. Use this feature in tandem with embedding version numbers in the name of published templates (i.e., only those intended for shared consumption). That way, consumers can use a variable in the templateLink uri property to dynamically pick the contentVersion and corresponding template file.

Unfortunately, linked templates aren’t completely without issues. When including a linked template in your code, the uri you specify must be an HTTP or HTTPS URI that’s reachable by Azure. You can’t link to templates on an on-premises GitHub Enterprise, for example. And making your templates publicly available on the web isn’t desirable either.

Azure’s official solution is to store templates in Blob Storage and then link to them there. To keep it secure, use a SAS token with an expiry set to provide ARM temporary access to the template. This process obviously has enough friction to impede adoption. But Microsoft has an improved solution: Template Specs.

Template Specs

Currently, in public preview status, Template Specs provide a way to securely store ARM templates as Azure resources. The Template Spec resources themselves can be protected with RBAC. And if the template used to create a Template Spec references other linked templates, the Template Spec will include those linked templates, as well.

Deployments can be created from the Template Specs themselves or an ARM template can link to a Template Spec as a child template by providing its resource ID in the templateLink property.

Template Specs are inherently versioned (attempts to publish a new version Template Spec with the same version number will present a warning and ask for confirmation—with the default response unfortunately set to overwrite…) improving the experience of consumers and giving them confidence that templates they link to won’t change without warning. A solid CI/CD pipeline to release Template Specs is crucial. And it’s wise to not build your enterprise IaC reuse strategy on this until it’s out of preview.

Azure Building Blocks

Azure Building Blocks (ABB) is a deprecated CLI tool that collected simplified resource inputs, combined them with best practices defaults, and then generated an ARM parameters file that could be used in conjunction with pre-defined ARM templates for common scenarios.

If you are using Azure and looking for options to scale your organization’s use of IaC there’s every reason to not begin using ABB. If you’re already using ABB, it’s the end of the line and you won’t be getting any more updates. Time to look at other options like Terraform, ARM Template Specs, or…Bicep?


Bicep is still in development and not recommended for production use, so it’s not a great option for now. But Microsoft expects to release a supported version in 1H21. Bicep is a DSL for Azure Resource Manager declarations. ("ARM", "Bicep", get it?) Bicep "compiles" to standard ARM JSON, so what’s possible with standard ARM is generally possible with Bicep, albeit with a less tedious syntax than ARM’s JSON. (Try out the Bicep Playground to get a sense of how they compare.) Bicep is capable of "decompiling" an ARM template into Bicep code. One of Bicep’s explicit intents is to treat ARM JSON as an intermediate language. For ARM, JSON is the new CIL.

Bicep combines some aspects of both the AWS CDK and Terraform. Like the CDK it’s a higher-level language that produces a standard output, so all of the same workflows and tooling still works. But unlike CDK, Bicep isn’t a library for existing languages; it’s a stand-alone DSL—seemingly inspired by Terraform’s HCL—that you’ll have to learn. The difference with Terraform is that instead of producing Terraform JSON from HCL, Bicep produces ARM JSON.

Bicep also implements modules similarly to Terraform—with a key caveat. A module is simply another .bicep file. While Bicep won’t automatically process any .bicep files it discovers in a directory, it does provide a module keyword that can be used to import modules by providing a relative path. The modules are included in the compiled JSON; the output is a single ARM template file with nested deployments.

Modules are a crucial feature, but how do you share those modules across your organization? Bicep falls very short here. Unlike Terraform, it lacks the ability to pull modules from a remote source like Git or a module registry. It’s still useful for code organization, but this is a big gap and until there’s a scalable solution for packaging and distributing modules Bicep will just be a less painful way to write ARM templates.

Bicep is new and incomplete, but it’s the future of ARM. It’s 2021 and writing JSON is barbaric. Bicep promises to improve IaC on Azure by combining a simpler, HCL-like language with the advantages of ARM (tight platform integration and state management). Bicep already has a VS Code extension and IntelliSense support, and even in preview state, the developer experience is greatly improved over ARM. If Microsoft brings Bicep’s module functionality to par with Terraform it will be a compelling solution for shops with a heavy ARM investment.

If you want to learn more about scaling your IaC approach, I wrote an article explaining some general guidelines and other available tools. SingleStone helps companies of all sizes, from start-up to Fortune 500, with getting into the cloud and using it to effectively drive real business agility—and results. If your company is ready to manage its infrastructure code like a high-performing organization, we can help.


Chris Belyea

Director & Principal Architect of Cloud
View profile