Azure Policy Compliance Monitoring: A Solution in Bicep

Overview

  1. Create all resources except Event Grid Topic and Subscription
  2. Deploy the Azure Function (Manual or via AZ CLI / Azure Pipeline / VSCode)
  3. Create the Event Grid Topic and Subscription

Resources details

  • 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

Understanding the Code

targetScope = 'subscription'
param policyMonitorData object
module PolicyMonitorFunctionAppDep 'deploymentZone.bicep' = [for (rg, i) in policyMonitorData.resourceGroupArray: {
name: '${policyMonitorData.client}-PolicyMonitorFunctionAppDeployment-${i}'
params: {
commonTags: policyMonitorData.commonTagsForResources
customer: policyMonitorData.client
resourceGroup: rg
}
}]
"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)
}

Deploying the Function app

Deploying using Azure DevOps Pipeline

variables:
functionWorkingDirectory: 'function'
functionAppName: 'FN-PolicyMonitor'
- 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
- 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

Authenticate Azure CLI

Trigger Manually

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Exploring the IOTA signing process

The Observer Pattern

Do you know what .Net framework is ?

Why Software Engineering is really hard for introverts/socially anxious

Debugging is an Art

CyberKongz Weekly: November 15, 2021

Useful OSCP Notes & Commands

Value Type Vs Reference Type(Dive Deep) — Swift

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Arlan Nugara

Arlan Nugara

More from Medium

Luigi Manzi — Senior editor and director

Azure VPN P2S (OpenVPN with Azure AD) unable to resolve hostnames while connected to Azure VPN…

Add a Custom Domain to Azure Website

Retrospectives