Optimizing Bicep Templates
One of the best ways to optimize a bicep template, first would be to have proper reusable parameters along with making them secure. Since bicep is using Azure resource manager, we can pull in any data that the azure has and use them in the template, which allows us to reduce number of parameters we need in any given template.
As mentioned before, parameters provides information to a bicep template during deployment. Whenever we are going to assign a value to a parameter during parameter decleration, it will be considered as a default value of that parameter. But this can overriden by use if needed.
There are different parameter types we can use within Bicep:
- String
- Bool
- Integer
- Objects and
- Arrays
Objects and Arrays
Object parameters can be used to combine structured data together in one place. For Example:
1
2
3
4
5
param appServicePlanSku object = {
name: 'F1'
tier: 'free'
capacity: 1
}
Array’s are a list of objects that we can specify within bicep. This looks something like:
1
2
3
4
5
6
7
8
9
10
11
param cosmosDBAccountLocations array = [
{
locationName: 'westus1'
}
{
locationName: 'westus2
}
{
locationName: 'westus3
}
]
Decorators
Decorators helps us to attach constraints and metadata to a parameters, which makes it easier for user to understand what is expected within the parameter. @allowed
in the previous template is a decorator, which during deployment will ask for an environment type.
Few more examples of the such decorators:
- @minLength(i) – Minimum length of the parameter
- @maxLength(i) – Maximum length of the parameter
- @description – Document the purpose of the parameter for the user to understand
Most of the names in Azure have a charecter length and we can use the first two mentioned decorators to achieve this.
1
2
3
@minLength(5)
@maxLength(24)
param storageAccountName string
To provide a simple description to the use when user input is needed for a parameter, hepling him understand the functionality of the parameter
1
2
@description('The location into which the resource group is deployed into')
parameter location string
Parameter Files
Instead of including all the parameters have in the same template along with all the resources, it is best to use a seperate parameter file. This helps use with multi environment deployment.
The parameter files are usually JSON and you can pass the parameter file using the --parameter
flag. We do not have to have all the parameters in a parameter file. Its more like the parameter should be declared in any one of the places. But there is an order of Precedence.
1
az deployment group create main.bicep --parameter parameter.json
Default values provided in the template will be overriden by the values provided in the parameter file. The parameter file can inturn be overriden by the passing values using command line.
In the order of Precedence, command line parameters takes the highest Precedence, followed by the parameter files and finally default values take the least Precedence.
Secure credentials
We can use @secure
decorator to any parameter that might contain any credentials or secret values. When using output, Avoid including any sensitive data
. as any one with access to deployments, they can get access to all the sensitive data that we have output.
Also avoid using credentials or secrets in parameter files, as these will be visible in our git history
1
2
@secure
param sqlAdministratorLogin string
To avoid all these, we can directly integrate with azure key vault and reference the secret. We can refer any key vault in any resource group or any subscription. These vaults doesn’t have to be in the same subscription or resource group as the deployment.
We can refer the secrets in the key vault using the following json paramter syntax
1
2
3
4
5
6
7
8
...
"sqlAdministratorLogin": {
"reference": {
"keyVault": "<keyVault resource ID>"
},
"secretName": "AdminLogin"
}
...
We can also an existing key vault using the resource block within the template. Here we are using resource block to read an existing key vault. if we want to create a new key vault, we just have to change the keyvault resource block.
1
2
3
4
5
6
7
8
9
10
resource keyVault 'Microsoft.keyVault/vaults@2024-04-01' existing = {
name: keyVaultName
}
module applicationModule 'application.bicep' = {
name: 'application-module'
params: {
apiKey: keyVault.getSecret('ApiKey') // Function to retrieve a secret from the key vault.
}
}
Now, Lets Create a keyVault using CLI to use for secure password authentiation
1
az keyvault create --name $keyVaultName --location $location --enabled-for-template-deployment true -g $resourceGroupName
Set the secrets in the key vault(Before setting the secret, make sure you have key vault administrator permissions to make changes to key vault.)
1
az keyvault secret set --vault-name $vaultName --name sqlAdminLoginUsername --value $value
Similarly, set the password of the server as well.
1
az keyvault secret set --vault-name $vaultName --name sqlAdminLoginPassword --value $value
Finally, Here’s what my parameters file looks like
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appServicePlanSku": {
"value": {
"name": "F1",
"tier": "Free"
}
},
"sqlDatabaseSku": {
"value": {
"name": "Standard",
"tier": "Standard"
}
},
"sqlAdminLoginUsername": {
"reference": {
"keyVault": {
"id": "/subscriptions/12f45d09-4f98-4478-be03-8d095fe89fe2/resourceGroups/BicepTest/providers/Microsoft.KeyVault/vaults/TestBicepKeys"
},
"secretName": "sqlAdminLoginUsername"
}
},
"sqlAdminLoginPassword": {
"reference": {
"keyVault": {
"id": "/subscriptions/12f45d09-4f98-4478-be03-8d095fe89fe2/resourceGroups/BicepTest/providers/Microsoft.KeyVault/vaults/TestBicepKeys"
},
"secretName": "sqlAdminLoginPassword"
}
}
}
}
and my bicep template looks something like
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@description('The enviroment where this code is going to be deployed. Choose one from npe or prd')
param environmentName string = 'npe'
@description('Name of the appSolution and it has a minimum length of 1 to max length of 24')
@minLength(1)
@maxLength(24)
param solutionName string = 'appSolution${uniqueString(resourceGroup().id)}'
param appServicePlanInstanceCount int = 1
param appServicePlanSku object = {
name: 'F1'
tier: 'Free'
}
@secure()
@description('Administrator login username for the database')
param sqlAdminLoginUsername string
@secure()
@description('Administrator login password for the database')
param sqlAdminLoginPassword string
// We have declared this parameter in the paramters file.
@description('The name and tier fo the SQL database SKU')
param sqlDatabaseSku object
@description('Location should be in which location you want these resources to be deployed')
param location string = 'westus2'
var appServicePlanName = '${environmentName}-${solutionName}-plan'
var appServiceAppName = '${environmentName}-${solutionName}-app'
var sqlServerName = '${environmentName}-${solutionName}'
var sqlDatabaseName = 'Employess'
resource appServicePlan 'Microsoft.Web/serverfarms@2024-04-01' = {
name: appServicePlanName
location: location
sku: {
name: appServicePlanSku.name
tier: appServicePlanSku.tier
capacity: appServicePlanInstanceCount
}
}
resource appServiceName 'Microsoft.Web/sites@2024-04-01' = {
name: appServiceAppName
location: location
properties: {
serverFarmId: appServicePlan.id
httpsOnly: true
}
}
resource sqlServer 'Microsoft.Sql/servers@2024-05-01-preview' = {
name: sqlServerName
location: location
properties: {
administratorLogin: sqlAdminLoginUsername
administratorLoginPassword: sqlAdminLoginPassword
}
}
resource sqlDatabase 'Microsoft.Sql/servers/databases@2024-05-01-preview' = {
parent: sqlServer
name: sqlDatabaseName
location: location
sku: {
name: sqlDatabaseSku.name
tier: sqlDatabaseSku.tier
}
}
My Gitlab Repository for more templates and documentation
References
- MicrosoftLearn
- Youtube series: Introduction to Bicep