Skip to main content
Jorge Bernhardt Jorge Bernhardt
  1. Posts/

Bicep - Assigning Azure Policy Initiatives to Enforce Compliance

·800 words·4 mins· 100 views · 5 likes ·
Azure CLI Azure Cloud Shell Microsoft Microsoft Azure

Hi all! Today I want to talk to you about “Policy as Code” Just as “Infrastructure as Code” changed how we handle infrastructure deployment, “Policy as Code” gives us consistency, traceability, and rapid implementation in policy management.

For this guide, I’ll use Bicep, Microsoft’s open-source language explicitly designed for the declarative description and implementation of Azure resources, including Azure policies.

With Azure Policy, you can ensure that your resources comply with security and operational standards by setting and enforcing rules. Additionally, you can manage a group of policies known as “Initiatives” together.

The built-in Azure Policy initiatives are specifically designed to ensure compliance and help meet industry standards and regulations. This guide offers thorough direction on executing built-in Azure Policy initiatives using Bicep.

Prerequisites>

Prerequisites #

Before you start, you’ll need the following to deploy and manage resources with Bicep:

  • You need Azure CLI version 2.20.0 or later to deploy Bicep files on your local machine.
  • A text editor or IDE of your choice (Visual Studio Code with Bicep extension is my recommendation)
Create the Bicep file>

Create the Bicep file #

The first step in implementing a Bicep template is to create the Bicep file that defines its resources. Create a new file named assignment.bicep. This file will contain the code necessary to assign a list of initiatives.

targetScope = 'subscription'

@description('Array of policy initiatives. Each object should include an ID and a name.')
param initiatives array = [
  {
    id: '' // Replace with an initiative id
    name: '' // Replace with an initiative name
  }
]

@description('Deployment Location')
@allowed([
  'westeurope'
  'northeurope'
])
param location string = 'westeurope'

resource policyAssignments 'Microsoft.Authorization/policyAssignments@2022-06-01' = [for initiative in initiatives: {
  name: initiative.name 
  properties: {
    displayName: initiative.name
    policyDefinitionId: initiative.id 
  }
  identity: {
    type: 'SystemAssigned' 
  }
  location: location 
  scope: subscription() 
}]

// Output block to return the ids of each created policy assignment
output policyAssignmentIds array = [for initiative in initiatives: reference(initiative.name).policyDefinitionId]

Assigning a managed identity to a policy assignment is required when using specific Azure Policy effects that need to interact with other Azure services. For example, the ‘DeployIfNotExists’ and ‘Modify’ effects require a managed identity to perform the deployment or modification action. The identity property in the code snippet you’ve provided is used to assign a managed identity to the Azure resource, in this case, the policy assignment.

Deployment scope>

Deployment scope #

In Bicep, you can target your deployment to a resource group, subscription, management group, or tenant. When assigning built-in policy initiatives, the valid deployment scopes are Azure Resource groups, Subscriptions, or Management groups. By default, when deploying a Bicep template, the scope where the resource should be deployed is a resource group. For this example, I will use a subscription as the scope.

Deploy the Bicep template using Azure CLI>

Deploy the Bicep template using Azure CLI #

Once your Bicep template is prepared, and you’ve selected your desired scope, you can proceed to deploy the template through the Azure CLI. To do so, execute the following commands.

Parameters>

Parameters #

Personalization is key to making your template reusable. With the parameters, you can easily tailor the template to your specific needs. You can use either inline parameters or a parameter file to pass parameter values. In my case, I will use a file to pass the parameters; here is an example.

 {
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "initiatives": {
        "value": [
          {
            "id": "/providers/Microsoft.Authorization/policySetDefinitions/89c6cddc-1c73-4ac1-b19c-54d1a15a42f2",
            "name": "ISO 27001-2013"
          },
          {
            "id": "/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8",
            "name": "Microsoft cloud security benchmark"
          }
        ]
      },
      "location": {
        "value": "westeurope"
      }
    }
}

Important: Please note that the parameter file stores parameter values in plain text format. If you need to include a parameter with sensitive data, it’s recommended to store the value in a secure key vault.

Preview changes>

Preview changes #

Before deploying a Bicep file, you can preview the changes that will occur to your resources. Using what-if operations does not change existing resources; it simply shows you an output that includes color-coded results that allow you to see different changes.

az deployment sub what-if \
--template-file <filename>.bicep \
--parameters @<filename>.parameters.json \
--location <location>
Deploy the Azure resource>

Deploy the Azure resource #

Finally, to deploy the template, run the following command.

az deployment sub create \
--template-file <filename>.bicep \
--parameters @<filename>.parameters.json \
--location <location>
Validate the deployment>

Validate the deployment #

To verify that the budget resource was created correctly, you can either use the Azure Portal or the Azure CLI to check the created resources and their configurations. For Azure CLI, use the following command.

az policy assignment list \
--query "[].{Name:name, Location:location, Scope:scope}

References and useful links #

Thank you for taking the time to read my post. I sincerely hope that you find it helpful.