Boost your Azure Pipeline with Bicep's deployer() function
Overview
Context
Last month Microsoft released its newest Bicep version v0.32.4
which includes an interesting function called deployer()
. This function can retrieve the ObjectId and TenantId of the deploying Service principal. This can be very helpful in certain cases such as assigning tags to Azure resources or to assign a role to the deploying Service principal.
In my experience you have strong Infrastructure as Code (IaC) setup when you combine both Bicep with Azure Pipelines for deploying resources to Azure. Let's have a look what we can do with the new deployer()
function.
What’s the deal with the deployer()
function?
The deployer()
function, as per Microsoft's documentation, retrieves the object ID of the service principal, managed identity, or user initiating the deployment. It’s essentially like asking, “Who did this?” and Azure says, “It was them! 😄”
The output is the ObjectID of the service principal, which can be useful when tagging resources or for auditing purposes.
Why should you care?
Imagine the situation where multiple teams deploy resources every other minute, understanding who or what initiated a deployment is important. The deployer()
function helps by giving you that extra layer of visibility. You can then combine this with build tags in Azure DevOps, and you can trace resource deployments back to specific pipeline runs.
1. Setting Up Your Azure DevOps Pipeline
Link to GitHub project
First, let’s configure the Azure DevOps pipeline to pass the predefined Build.BuildNumber
to the Bicep deployment. I will also tag the pipeline run with the deployed resource information.
Here’s an example pipeline YAML:
1trigger: none
2
3pool:
4 vmImage: ubuntu-latest
5
6variables:
7 resourceGroupName: 'arash-shared-rg' # Resource group name. Change it to your own resource group name
8
9steps:
10- task: AzureCLI@2
11 displayName: 'Bicep Deployer function'
12 inputs:
13 azureSubscription: 'test-automatic' # Azure Resource Manager service connection. Change it to your own service connection
14 scriptType: 'pscore'
15 scriptLocation: 'inlineScript'
16 inlineScript: |
17 $deploymentName="pipeline-run-$(Build.BuildNumber)"
18 az deployment group create `
19 --resource-group $(resourceGroupName) `
20 --template-file ./infra/storageAccount.bicep `
21 --name $deploymentName `
22 --parameters tags="{'PipelineRunID':'$(Build.BuildNumber)'}"
23
24 # Add build tag to Azure Pipeline run
25 echo "##vso[build.addbuildtag]$deploymentName"
What’s happening here?
$(Build.BuildNumber)
provides the unique build number for the current pipeline run.az deployment group create
deploys the Bicep template with an additionalPipelineRunID
tag.##vso[build.addbuildtag]
adds a tag to the Azure DevOps build, linking the deployment name with the pipeline run.
2. Updating the Bicep template
In this example a Bicep module including an Azure storage account is used. The Bicep template will dynamically tag resources with both the pipeline run ID and the deploying identity.
Here’s an example main.bicep
:
1param tags object = {}
2
3param location string = resourceGroup().location
4
5module storageAccounts 'br/public:avm/res/storage/storage-account:0.15.0' = {
6 name: 'storageAccountDeployment'
7 params: {
8 // Required parameters
9 name: 'sa${uniqueString(deployment().name)}'
10 // Non-required parameters
11 allowBlobPublicAccess: false
12 location: location
13 skuName: 'Standard_LRS'
14 networkAcls: {
15 bypass: 'AzureServices'
16 defaultAction: 'Deny'
17 }
18 tags: union(tags, {
19 DeployerObjectID: deployer().objectId
20 Environment: 'Development'
21 })
22 }
23}
- The
tags
parameter accepts tags passed from the pipeline. - The
union()
function merges the provided tags with additional tags likeDeployerObjectID
.
When deployed, the resources will include:
- The
PipelineRunID
passed from Azure DevOps. - The deploying principal’s object ID retrieved using
deployer()
function.
3. Testing the deployment
After executing the Azure pipeline the Azure storage account will be deployed to Azure. When navigating to the new Azure storage account the tags should be visible:
The build in Azure DevOps is also tagged with the build number:
This provides a clear link between the Azure resources and the specific pipeline run that deployed them.
Notes
- Role assignments: Ensure the deploying service principal has the
Contributor
role or equivalent permissions on the resource group / azure subscription. - Tag overhead: Avoid overloading your resources with too many tags. Stick to meaningful ones.
- Multiple deployers: In multi-stage pipelines with different identities,
deployer()
reflects the identity of the current stage’s deployer.
Conclusion
Bicep’s deployer()
function, paired with Azure DevOps build tags, is for traceability and governance in Azure deployments. Whether you’re an DevOps Engineer or just starting your IaC journey, this combination is worth adding to your setup.
And remember, IaC isn’t just about infrastructure; it’s about making life easier for you and your team. 😊
Happy coding! 🚀