A first look at Bicep

As a DevOops professional, I’m always excited to experiment with the latest tooling available. This week, we take a look at Bicep, which is a domain specific language (DSL) created by Microsoft to assist with the creation of Azure Resource Manager (ARM) templates.

What is a DSL?

At a very high level, there are two types of programming languages. General purpose languages (GPLs) are the programming languages you are most familiar with. Things like Ruby, Python, C#, Go, etc all fall in to this category. These programming languages are broadly applicable across various application domains, which is just a fancy way of saying you can use them to solve lots of problems in lots of contexts.

A domain specific language (DSL), on the other hand, is a language created fit for a small subset of purposes. The line between GPLs and DSLs is blurry at the best of times. Examples of DSLs would include things like Sed, Gawk, SQL, HTML, etc.

Bicep was created for one reason, to assist in the creation of ARM templates. This makes it a DSL for creating ARM templates. You can read the official docs here.

How does Bicep Work?

Bicep is effectively an application that converts templates written in the Bicep DSL to an ARM template. At this point, technically speaking, the ARM template becomes an Intermediate Language (IL) much like bytecode is for compiled languages. You can then work with the ARM template as you normally would (by submitting it to Azure for processing, or framing it on your wall).

At time of writing, bicep only has a single command build.

A Sample

Here is a sample bicep file that:

  • Creates a SQL server
  • Creates a SQL database
  • Configures Transparent Data Encryption
  • Sets the Azure Active Directory Login

You can read about the directives used here.

param location string = resourceGroup().location
param aadLoginName string
param aadLoginSid string
param aadLoginTenant string
param clientIpAddress string

// Generic DB Settings
var databaseName = 'sample-db-with-tde'
var databaseEdition = 'Basic'
var databaseCollation = 'SQL_Latin1_General_CP1_CI_AS'
var databaseServiceObjectiveName = 'Basic'
var sqlServerName = 'sqlserver${uniqueString(resourceGroup().id)}'

// Security Settings, no touchey!
var minTlsVersion = '1.2' // Should always be latest supported TLS version
var transparentDataEncryption = 'Enabled' // Why would you ever disable this?
var sqlAdministratorLogin = 'user${uniqueString(resourceGroup().id)}' // Using AAD auth, so create random user
var sqlAdministratorLoginPassword = 'p@!!${uniqueString(resourceGroup().id)}' // Using AAD auth, so create random pw

resource sqlServer 'Microsoft.Sql/servers@2019-06-01-preview' = {
  name: sqlServerName
  location: location
  properties: {
    administratorLogin: sqlAdministratorLogin
    administratorLoginPassword: sqlAdministratorLoginPassword
    version: '12.0'
    minimalTlsVersion: minTlsVersion

resource db 'Microsoft.Sql/servers/databases@2019-06-01-preview' = {
  name: '${}/${databaseName}' 
  location: location
  properties: {
    edition: databaseEdition
    collation: databaseCollation
    requestedServiceObjectiveName: databaseServiceObjectiveName

resource tde 'Microsoft.Sql/servers/databases/transparentDataEncryption@2014-04-01-preview' = {
  name: '${}/current' 
  properties: {
    status: transparentDataEncryption

resource aadLogin 'Microsoft.Sql/servers/administrators@2019-06-01-preview' = {
    name: '${}/aadLogin'
    properties: {
        administratorType: 'ActiveDirectory'
        login: aadLoginName
        sid: aadLoginSid
        tenantId: aadLoginTenant

resource fwRule 'Microsoft.Sql/servers/firewallRules@2015-05-01-preview' = {
    name: '${}/fwRule1'
    properties: {
        startIpAddress: clientIpAddress
        endIpAddress: clientIpAddress

As you can see from the above, Bicep feels like an interesting mix between YAML and some other object-like templating language. A couple of observations:


YAY! I can finally add comments in a useful way to my template files to communicate valuable information to others running it

  1. Variable/Parameter syntax seems clean

I like the lack of braces and other syntax elements required to create parameters and variables. While not shown in the example above, you can make your parameters complex (adding defaults and allowed values, etc). Just have a look at the docs.

  1. Variable/Parameter references are mixed

Bicep seems to auto calculate inputs to be either variables or parameters. This means you cannot have the same name defined in both sections (this generates a “compiler” error).


In conclusion, I plan to fool around a bit more with Bicep before I pass any judgment. By the end of the year Bicep should be ready for “production use” and be on feature parity with ARM, which will be nice.

If I had to give feedback right now, I’d say that I’d want to see the bicep code expanded so that I don’t have to deal with the intermediate ARM template files at all. Effectively, I’d want to be able to run

 New-AzResourceGroupDeployment -TemplateFile blah.bicep

and have it do all the build/conversion steps required.


Share This Article