Streamlining Azure Non-Compliance Monitoring with Bicep Automation
- Arlan Nugara
- Jun 11, 2024
- 3 min read
In today’s rapidly evolving cloud environment, ensuring compliance across your Azure resources is critical. In this blog post, we explore how to leverage Bicep – Azure’s declarative language for deploying infrastructure – to automate the deployment of a non-compliance resource monitoring solution. This solution is designed with a split deployment strategy, where the core resource provisioning is decoupled from event grid configuration to promote flexibility and control.
We will walk through the architecture and key components, including a Log Analytics Workspace, Function App, Storage Account, Key Vault, and more. The deployment sequence begins by provisioning essential resources, such as the Log Analytics Workspace and Azure Monitor Alert Rules, and then proceeds to deploy an Azure Function before finally configuring the Event Grid Topic and Subscription. This structured approach not only simplifies resource management but also facilitates multiple deployment pathways—whether through Azure CLI, DevOps pipelines, or manual steps via VSCode.
Throughout this post, you will find detailed explanations of the Bicep files—main.bicep, deploymentZone.bicep, and main.eventgrid.bicep—as well as code snippets illustrating how to set up parameters and automate deployments with both command line and continuous integration pipelines. Whether you’re a seasoned DevOps professional or just getting started with infrastructure-as-code in Azure, this guide provides actionable insights to help you implement a robust non-compliance resource monitoring solution.
Overview
This bicep code is developed to automate deployment of a Azure Non-Compliance resource monitoring solution. The solution is a split solution with bicep code creating the solution with the following sequence
Create all resources except Event Grid Topic and Subscription
Deploy the Azure Function (Manual or via AZ CLI / Azure Pipeline / VSCode)
Create the Event Grid Topic and Subscription
Resources details
The list of resources created by this Bicep Project are as follows : -
Log Analytics Workspace
Event Grid Topic and Subscription
Function App (Triggered Manually using AZ CLI or from VSCode)
Azure Monitor Alert Rule
Storage Account
Azure Monitor Metrics
Key Vault
Diagram
Here's a rough diagram of the resources it creates

Understanding the Code
The main.bicep file targets the scope
targetScope = 'subscription'
It defines the parameter from parameter file
param policyMonitorData object
It calls the deploymentZone.bicep file with parameters. The deploymentZone.bicep file creates the required resources defined within
module PolicyMonitorFunctionAppDep 'deploymentZone.bicep' = [for (rg, i) in policyMonitorData.resourceGroupArray: {
name: '${policyMonitorData.client}-PolicyMonitorFunctionAppDeployment-${i}'
params: {
commonTags: policyMonitorData.commonTagsForResources
customer: policyMonitorData.client
resourceGroup: rg
}
}]
A glance at the parameter file
"storageAccountArray": [
{
"name": "logs",
"skuName": "Standard_LRS",
"logAnalytics": {
"logStorageAccountNameRef": "logs",
"logWorkSpaceNameRef": "PolicyMonitor"
},
"tags": {
"App": "Storage"
}
},
{
"name": "pmfn",
"skuName": "Standard_LRS",
"logAnalytics": {
"logStorageAccountNameRef": "logs",
"logWorkSpaceNameRef": "PolicyMonitor"
},
"tags": {
"App": "Storage"
}
}
]
resource rgs 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: 'RG-${customer}-${resourceGroup.rgName}'
location: resourceGroup.rgLocation
tags: union(commonTags, resourceGroup.tags)
}
Similarly the main.eventgrid.bicep files creates the resources defined within
Deploying the Function app
Deploying using Azure DevOps Pipeline
Define the variable. Change the functionAppName as per your requirement
variables:
functionWorkingDirectory: 'function'
functionAppName: 'FN-PolicyMonitor'
Archive the function directory
- task: ArchiveFiles@2
displayName: 'Archive Function directory'
inputs:
rootFolderOrFile: $(functionWorkingDirectory)
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/monitor.zip
replaceExistingArchive: true
- publish: $(Build.ArtifactStagingDirectory)/monitor.zip
artifact: drop
Deploy the Function App
- task: AzureFunctionApp@1
displayName: 'Azure functions app deploy'
inputs:
appType: functionAppLinux
appName: $(functionAppName)
package: '$(Pipeline.Workspace)/drop/monitor.zip'
Deploy using AZ cli
az functionapp deploy --resource-group <Reosurce group Name> --name <Function App Name> --src-path <Path to the zip file> --type zip
Deploy using Powershell
$creds = Invoke-AzureRmResourceAction -ResourceGroupName <Reosurce group Name> -ResourceType Microsoft.Web/sites/config -ResourceName <App Name>/publishingcredentials -Action list -ApiVersion 2015-08-01 -Force
$username = $creds.Properties.PublishingUserName
$password = $creds.Properties.PublishingPassword
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password)))
$apiUrl = "https://<yourFunctionApp>.scm.azurewebsites.net/api/zip/site/wwwroot"
$filePath = "<yourFunctionName>.zip"
Invoke-RestMethod -Uri $apiUrl -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method PUT -InFile $filePath -ContentType "multipart/form-data"
Install Azure CLI
You can install Azure CLI from here
Authenticate Azure CLI
Hit the command az login from Comamnd Prompt or Terminal depending upon your OS. More details can be found here
Trigger Manually
Fire the below command to create the resources using Bicep script
az deployment sub create --location WestUS --name PolicyAlertDeployment1 --template-file main.bicep --parameters main.parameters.json
Deploy the Function App here
az deployment sub create --location WestUS --name PolicyAlertDeployment2 --template-file main.eventgrid.bicep --parameters main.eventgrid.parameters.json
Comments