Policy as Code (PoC): Deploying and Managing Azure Policy in Bicep

What is Azure Policy ? As Per Official Microsoft Article


Understand evaluation outcomes

  • A resource is created or updated in a scope with a policy assignment.
  • A policy or initiative is newly assigned to a scope.
  • A policy or initiative already assigned to a scope is updated.
  • During the standard compliance evaluation cycle, which occurs once every 24 hours.

Control the response to an evaluation

  • Deny the resource change
  • Log the change to the resource
  • Alter the resource before the change
  • Alter the resource after the change
  • Deploy related compliant resources

Remediate non-compliant resources

Azure Policy vs Azure RBAC

Azure Policy Objects

Policy definition

Initiative definition


Going through the Bicep code

  • The main.bicep calls the policy.bicep file.
  • The policy.bicep in returns calls the modules in modules/policies directory and creates the policies.
  • The main.parameters.json file is passed to the command which contains all the key value pair of the variables. You need to exchange “” with your values.

Understanding Policy code

targetScope = 'subscription'
param policyInitiativeArray array
module policyM 'modules/policy.bicep' = [for (pol, i) in policyInitiativeArray: {
name: 'Policy-${i}'
params: {
policyData: pol
module allowedRegionsModule './policies/allowed_regions.bicep' = {
name: '${policyData.client}-${policyData.allowed_regions_policy.name}'
params: {
client: policyData.client
policyInputData: policyData.allowed_regions_policy
targetScope = 'subscription'param policyInputData object
param client string
output policyId string = allowed_regions_policy.id
resource allowed_regions_policy 'Microsoft.Authorization/policyDefinitions@2021-06-01' = {
name: '${client}-${policyInputData.name}'
properties: {
displayName: '${client}-${policyInputData.displayName}'
policyType: 'Custom'
mode: 'All'
description: policyInputData.description
metadata: {
category: 'General'
policyRule: {
if: {
allOf: [
field: 'location'
notIn: '[parameters(\'regAllowedRegions\')]'
field: 'location'
notEquals: 'global'
field: 'type'
notEquals: 'Microsoft.AzureActiveDirectory/b2cDirectories'
then: {
effect: policyInputData.effect
resource policyDefSet 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = {
name: '${policyData.client}-${policyData.name}'
dependsOn: [
properties: {
policyType: policyData.policyType
displayName: policyData.policySetDefinitionDisplayName
parameters: {}
policyDefinitions: [
policyDefinitionId: allowedRegionsModule.outputs.policyId
parameters: {}
resource policyAssign 'Microsoft.Authorization/policyAssignments@2021-06-01' = {
name: '${policyData.client}-${policyData.name}-Assignment'
properties: {
displayName: '${policyData.client}-${policyData.policyInitiativeDisplayName}'
enforcementMode: 'Default'
policyDefinitionId: policyDefSet.id
parameters: {}
"allowed_regions_policy": {
"name": "Allowed-Azure-Regions",
"displayName": "Allowed Azure Regions",
"description": "This policy allows resources to be created in the allowed locations.",
"listOfAllowedLocations": ["canadaeast", "canadacentral"],
"effect": "Audit"

Policies that are created

  1. Allowed Regions
  2. Allowed Resource Types
  3. Allowed SQL Version
  4. Allowed Storage Account SKU
  5. Allowed VM Extensions
  6. Allowed Subnets for Public IP
  7. Allowed VM OS and version
  8. Allowed VM SKU
  9. DDOS Protection
  10. Diagnostics Settings
  11. Diagnostic settings logs to be send to Log Analytics WOrkspace
  12. Firewall Internet Traffic
  13. Key Vault Purge Protection
  14. Key Vault soft delete
  15. VM NIC IP Forwarding
  16. Enable Network Watchers
  17. NSG for every Subnet
  18. NSG Inbound rules
  19. SQL Database Private endpoint
  20. SQL Database TLS version
  21. SQL server public network access
  22. Storage Account Secure Transfer Settings
  23. Storage Account Key Expiry
  24. Storage Account Network Access
  25. Mandatory Tags
  26. Optional Tags
  27. Internet facing VM NSG
  28. VM managed disk
  29. VM management port
  30. VM encryption

Run the code

Authenticate Azure CLI

Trigger Manually




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

Recommended from Medium

How to build a simple Python pip package ??

Create Your Own Coins and Make Simple Transactions With Solidity

What is Considered a Single Microservice?

How To Determine The Best SHTF Truck For You

Pickle Rick writeup from TryHackMe

[Tech] Testing Guidelines

NFT opensea bidding bot using opensea’s API

Using Devices with ADF (Amazon Device Farm) and Browserstack for Automation testing

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

Azure Hierarchy Support

How to configure Azure DevOps with Terraform Enterprise ?

💪Deploy NGINX Plus with NGINX App Protect Premium Edition in Azure using Bicep Language

Creating a Custom Role for an Azure Managed Identity

Azurerm resource block to create a custom role for a managed identity