Accidentally deleting resources can cause some issues. Azure provides protection with resource lock, but remembering to enable this feature can be a burden. Luckily, you can use Azure Policy to audit and deploy resource lock to existing and new resources.

In this article, you will learn the basics of resource locks and Azure Policy. You will then follow a tutorial on creating a custom Azure Policy definition and assigning the definition to a subscription. The result will be resource groups having a do not delete resource lock associated with them.

What is a Resource Lock?

Resource locks prevent users from deleting or modifying Azure resources. The lock overrides any user’s permissions, so even owners cannot modify or delete the resource. There are two levels for resource locks.

  • CanNotDelete: Users can read and modify a resource but cannot delete it.
  • ReadOnly: Users can read a resource by not delete or update it. Similar to assigning users the Reader role.

You can apply resource locks to the management group, subscription, resource group, or individual resource. When you apply a lock at one of these parent scopes, all resources within the scope inherit the lock. For example, apply the lock at the resource group level if you want to protect all resources in a resource group. Each resource inherits the resource lock.

In general, you find resource locks by navigating to Settings > Locks on the resource. For example, here is a resource lock preventing deletion applied to a storage account.

azure resource lock
Resource lock preventing deletion applied to a storage account

One thing to note is the delete lock type does not prevent users from modifying or deleting data in the storage account. Resource locks only protect against modifications or deletions of the resource itself. The same idea applies to other resources like databases. Read more about other considerations before using resource locks here.

What is Azure Policy?

Azure Policy is a service that enforces standards and resource consistency in the Azure tenant. You can bring resources to compliance through remediation or audit the resource settings. Some common use cases for Azure Policy include enforcing regulatory compliance, security settings, and cost management.

Azure Policy uses a JSON format to create the evaluation logic, which determines whether the resource is compliant. The policy definition includes metadata, conditions, and policy rules. The rules definition includes functions, parameters, logical operators, and conditions.

Some example policy definitions include:

  • Enable Azure Monitor for VMs
  • Flow logs should be configured and enabled for every network security group
  • Configure Azure Defender to be enabled on SQL servers

Creating a Custom Azure Policy to Enforce Resource Lock

With the basics of resource locks and Azure Policy out of the way, let’s move on to creating a custom Azure Policy definition. The Azure Policy definition will look for resource groups, and if the resource group does not have a deny delete resource lock, the policy will create one.

To follow along with this tutorial, you will need:

  • PowerShell 5.1 or higher with the Az PowerShell module installed. This tutorial uses PowerShell v7.1.4 and Az module v6.6.0.
  • Access to an Azure tenant and subscription with Owner rights.

Step 1. Create an Azure Policy using JSON

To get started, create an empty JSON file named EnforceDoNotDeleteLock.json. This file contains information about the definition as well as the policy rule and action details. Below is the start of the definition. The full definition is enclosed in curly brackets { } followed by a properties block. The first properties you should define are the displayName and description of the policy.

The next property is mode. In general, you should set the mode to all as this mode evaluates against resource groups, subscriptions, and all resource types. Another option is indexed, which only evaluates resources types that support tags and location. Policy definitions created through the Azure portal are set to all.

The next section is metadata and stores information about the policy definition. You can define any properties and values that you might find helpful in tracking your custom policy definitions. This tutorial uses two metadata properties: the definition version and the category that determines how the Azure portal displays the definition.

Finally, you can define parameters. In this tutorial, the definition does not contain any parameters for passing in additional information, but the property is included if this changes in the future.

Here is the start of the custom Azure Policy definition:

    "properties": {
        "displayName": "Deploy CanNotDelete Resource Lock on Resource Groups",
        "description": "Creates a resource lock at the resource group level for preventing resource deletion.",
        "mode": "all",
        "metadata": {
            "version": "1.0.0",
            "category": "General"
        "parameters": {},
        "policyRule": { ... }

Step 2. Create the Policy Rule

The next section in the policy definition is policyRule. This section consists of an if/then block that describes the conditions and actions. If one or more defined conditions are met, then the policy is enforced.

In this tutorial, the policy definition targets resource groups, so the if statement looks for resource types that equal Microsoft.Resources/subscriptions/resourceGroups. Here is the if statement:

"if": {
    "field": "type",
    "equals": "Microsoft.Resources/subscriptions/resourceGroups"

Next is the then statement, which has several properties. The first is effect, which describes what action the policy should take. In this case, the policy modifies an existing resource, so the effect is DeployIfNotExists. Read more about the available policy effects here.

Following the effect statement is the details section, which contains all the subproperties that define the related resources to match and the template deployment to execute. Here is a breakdown of the subproperties in the details section.

  • Type: Defines the type of related resource to match, in this case, the Microsoft.Authorization/locks resource.
  • ExistenceCondition: Tests to see if the resource already exists. Here the policy tests to see if an existing CanNotDelete resource lock exists on the resource group. If this condition evaluates to true, then the policy does not deploy the resource template.
  • RoleDefinitionIds: This section defines the Azure RBAC role required to deploy the template. The default RBAC groups Owner and User Access Administrator groups have permissions to modify resource locks. This policy uses the GUID associated with the Owner RBAC group.
  • Deployment: Contains the ARM JSON template code to deploy. The template deployment here creates a resource lock named DenyDelete with a lock level of CanNotDelete.

Here is the complete policy definition, including the then statement described above.

Step 3. Create the Custom Azure Policy Definition using PowerShell

With the policy file defined, it is time to create the policy. To make the policy definition:

  1. Open a PowerShell terminal and navigate to where the policy definition JSON file EnforceDoNotDelete.json is located.
  2. Connect to Azure using the Connect-AzAccount command.
  3. Use the New-AzPolicyDefinition command to create the policy. Specify -Name (DeployCanNotDeleteLock), -DisplayName, and -Policy with the path to the JSON file.
New-AzPolicyDefinition `
    -Name "DeployCanNotDeleteLock" `
    -DisplayName "Deploy CanNotDelete Resource Lock on Resource Groups" `
    -Policy .\EnforceDoNotDeleteLock.json

Step 4. Assign Definition to a Subscription

Finally, it’s time to assign the definition to a subscription. Assigning the definition to an entire subscription ensures that every existing and future resource group will have the lock enabled.

In the Azure portal, search for “policy” and select Policy from the results.

azure portal policy
Navigating to the Policy resource in the Azure portal

In Policy, navigate to Authoring > Definitions and search for “CanNotDelete.” Click on the matching policy name.

azure policy definitions
Searching for the custom policy

In the policy definition window, click on Assign. In the assign policy window, select the scope you want to apply the policy definition, such as an entire subscription. Ensure that Policy Enforcement is set to Enabled. Click Next.

azure policy assignment
Configuring Basics tab of policy assignment.

Since this policy definition does not have parameters, click Next to the Remediation tab. By default, the policy assignment only works on newly created resources. However, this subscription contains existing resources that Azure should remediate. To accomplish this, check the box for Create a remediation task.

Next, ensure the Create a Managed Identity is checked. The policy requires an identity with sufficient permissions to deploy the template as part of the remediation task. Choose a system or user-assigned managed identity and the identity location. The permissions should already be set to Owner, as you defined this earlier in the template. Click Next.

azure policy remediation task
Configuring a remediation action

On the Non-compliance messages tab, enter in any message you’d like. This message displays to users when the resource is non-compliant. Click Review + create, then Create after validation has completed.

Navigate back to Policy > Authoring > Assignments. Here you should see the new policy assignment in the assignment list.

azure policy assignments
Navigating to the new policy assignment

In the policy assignment window, select the Remediation tab. If any resources require remediation, this tab will display the task state. From here, select the three-dot context menu to the right and select View remediation task. This action displays any resources that match the policy definition and the state of its remediation. Once Azure completes the remediation, navigate to a resource group and resources in the subscription to verify the lock exists.

azure policy remediation tasks
Viewing remediation tasks
Viewing remedation task results


In this article, you learned how to use resource lock to prevent the modification or deletion of critical Azure resources. You then learned the basics of Azure Policy for enforcing organizational or compliance standards. Finally, you combined Azure Policy and resource lock to enforce a CanNotDelete policy on all resource groups in a subscription.

With this new knowledge, what other kinds of tasks do you think you can use Azure Policy to enforce?

Enjoyed this article? Check out more of my Azure content here!