Azure Bicep Basics

· 5 min read

in-progress AzureBicep

What is Azure Bicep

Bicep is a declarative language that is used to deploy Azure recourses.

Bicep file sections

// 1. TARGET SCOPE (optional, defaults to resourceGroup)
targetScope = 'resourceGroup'

// 2. PARAMETERS (inputs to your template)
param parameterName type = defaultValue

// 3. VARIABLES (reusable values within the file)
var variableName = expression

// 4. RESOURCES (the actual Azure infrastructure)
resource symbolicName 'resourceType@apiVersion' = { ... }

// 5. OUTPUTS (values returned after deployment)
output outputName type = value

1. Target Scope

The target scopes defines at what level of the azure hierarchy the bicep file will operate at.

// Three possible values:
targetScope = 'resourceGroup'  // Default - deploys TO a resource group
targetScope = 'subscription'   // Deploys ACROSS subscriptions
targetScope = 'managementGroup' // Deploys across multiple subscriptions

2. Parameters

This is what makes the templates reusable, this allows the file to accept input values. Basically when deploying the parameters the console will ask for user input.

The basic Syntax of a parameter is:

param <name> <type> = <defualtValue>

parameter types available:

| Type | Description | Example | | ———— | ———————— | ————————- | | string | text values | ‘eastus’ | | int | Numbers | 100 | | bool | ture/false | true | | array | List of values | [‘value’,’value’] | | object | Dictionary of properties | {key: “value”} | | secureString | String encrypted at rest | used for passwords | | secureObject | Object encrypted at rest | used for sensitive values |

Decorators & Metadata decorators

Metadata decorators are basically comments and decorators constraint/validation rules you attach to a declaration. This is useful to control or limit the behavior of deployment or even block wrong value deployments. Some common decorators are:

Decorator Description
@allowed([…]) Restricts the parameters to specific values
@minValue( ) Create a minimum value for int input
@maxValue( ) Create a maximum value for int input
@minLength( ) Create a minimum value for string input
@maxLenght( ) Create a maximum value for string input
@secure( ) Makes a parameter a secret. (never logged, stored, and is encrypted in deployment state)
@discriminator(‘type’)  

Pure metadata decorators:

Decorator Description
@decription( ) Helps create humen readable docs and shows up as text when you run a interactive deployment.
@metadata({ }) Key value pairs that basically work as tags to key information and infrastructure organized

3. Variables

Variables are named values used inside a template to improve readability and to avoid repetition. The basic syntax of a variable is:

var <name> = <experesion>

Example:

//retreves the resourcesGroupes location and assigns it to the veriable location
var location = resourceGroup().location 

Common built-in Functions used with variables

| Function | Purpose | Example | | — | — | — | | resourceGroup() | Gets info about current resource group | resourceGroup().location | | subscription() | Gets subscription info | subscription().subscriptionId | | uniqueString() | Creates unique string | uniqueString(resourceGroup().id) | | toLower() / toUpper() | Case conversion | toLower('NAME') → ‘name’ | | concat() | Joins strings | concat('prefix-', 'suffix') | | length() | Gets array/string length | length(arrayVar) | | if() | Conditional expression | if(condition, trueValue, falseValue) |

4. Resources

This is where you declare the azure infrastructure. The basic syntax for declaring a resource:

resource <symbolicName> '<resourceType>@<apiVersion>' = {
  name: '<resourceName>'
  location: '<location>'
  <properties>: {...}
}

5. Child Resources

Child recourses are resources that are part of another resource and are dependent that the parent resource exists. For example a Virtual network and a subnet. The subnet can’t exist without the virtual network.

resource sqlServer 'Microsoft.Sql/servers@2022-05-01-preview' = {
  name: sqlServerName
  location: location
  properties: {
    administratorLogin: adminUser
    administratorLoginPassword: adminPassword
  }
  
  // Child resource nested inside parent
  resource database 'databases' = {
    name: databaseName
    location: location
    sku: {
      name: 'Basic'
    }
  }
}

6. Modules

Modules allow you to break down complex deployments into smaller more manageable files. In other works instead of declaring all the whole deployment in one file, you can declare them in multiple smaller files. The basic module structure is:

// main.bicep (parent)
module storageModule './storage-account.bicep' = {
  name: 'deploy-storage-${uniqueString(resourceGroup().id)}'
  params: {
    storageAccountName: storageName
    location: location
    sku: 'Standard_LRS'
  }
}