Recently I had a need to clone secrets in one Key Vault into another Key Vault in a different subscription. I wasn’t sure if it was even possible to do but with a bit of PowerShell and the Azure CLI it turns out you can, here’s the script:
Recently I was looking into others ways to provide inputs to Bicep. In previous posts I have used various techniques to pass parameters in via Azure Pipelines, either updating a parameters JSON file or creating the whole file in the pipeline (I bundled those techniques into one post if you want to take a look).
If you are not sure about creating a parameters file to use with Bicep I recommend the Visual Studio Code extension Azure Resource Manager (ARM) Tools as this provides an easy way to create them. Also there is a PowerShell module written by Stefan Ivemo (and others) that has a command ‘New-BicepParameterFile’ that creates a parameter file from a Bicep file (see github and/or the PowerShell gallery)
In other Infrastructure as Code (IaC) frameworks like Terraform, there are ways to load variable files in and they are usually in the same language as the framework. Bicep however doesn’t currently support variables files in the Bicep language, but as I discovered, it does have a function called loadTextContent, this coupled with the json function allows JSON files to be loaded in and therefore could be used as variable files.
So, in this post I am going to explore using these functions to load variables into Bicep.
NOTE: I will be using az bicep version 0.6.1
The Code
Let’s start with something small like creating a storage account.
First create some settings for the account, name, sku, etc. in a JSON file (vars_storage.json) e.g.
Next create the bicep file (deploy.bicep) to create the storage account and load in the variables from the json file using loadTextContent and json functions:
Often when we use IaC we are deploying to multiple environments. Can files be dynamically loaded by a parameter value? something like this?
param location string = resourceGroup().location
param env string
var storageConfig = json(loadTextContent('vars_${env}_storage.json'))
var networkConfig = json(loadTextContent('vars_${env}_network.json'))
Unfortunately this is not a supported configuration in Bicep
The reason for this is that Param is determined at runtime and loadTextContent is determined at compile time
It is possible however to define environments in the file and load the desired section at runtime.
NOTE: One downside of using this way of loading environments is that Visual Studio Code loses intellisense on the JSON properties due to the runtime env parameter
Let’s change the JSON files to support multiple environments
As before this can now be deployed into Azure via the Azure CLI adding the env parameter
Dev
az deployment group create --resource-group rg-varsdemo-dev-weu --template-file deploy.bicep --parameters env=dev
Prod
az deployment group create --resource-group rg-varsdemo-prod-weu --template-file deploy.bicep --parameters env=prod
Conclusion
You can of course provide all the variables inside the Bicep file including multiple environments and that is a valid way of defining values. However if you have a lot of variables, using a separate file whether that be a parameters file or following this technique can reduce the noise inside the Bicep file. Separate files also allow values to be overridden by a CI/CD pipeline, share variables between multiple Bicep files and it might be easier to maintain configuration if it is in separate files.
I think loading files in is a nice way of injecting values into Bicep, its a shame that other file formats like YAML are not currently supported or using Bicep style variable/parameters files. Hopefully these features will become part of Bicep in the future.
Well I hope you found this useful and discovered another way to get inputs into Bicep. Bicep is certainly improving more and more and I look forward to future releases.