Protecting Azure Resources with Resource Locks

Azure makes it simple to spin up many different types of resources, and likewise it is fast and easy to remove resources. This is a great thing for proof-of-concepts, because it allows a really fast test cadence – it is one of the first selling points of the cloud. Instead of waiting for hardware to arrive and software to be configured, an Azure Website can be created, deployed, and removed inside of an hour. However, making changes – and deleting resources – is generally undesirable in a production environment. It is not difficult to accidentally run a script while logged into the wrong environment if strict separation of privilege is not followed – and most organizations do not have the resources for that. Additionally, in the event of an account compromise, it can reduce the impact of an attack.

Beyonce meme: if you liked it / you should have put a resource lock on it

Azure has a feature called Resource Locks, which can be used to protect production resources from changes. They can easily be applied or removed by an administrator, but they exist outside of the RBAC model, which means that there is no role or permission that can be granted that will bypass them. When a Resource Lock is changed, a log entry is created – this can be integrated with monitoring services, so that alerts are generated when a Resource Lock is changed.

There are two types of Resource Locks:

  1. ReadOnly. This blocksĀ all changes to the locked resources. You will not, for example, be able to resize a VM or change application settings on a website. You also will not be able to do some sensitive operations, such as viewing or setting a Storage Account API key.

    A partial screenshot of the Microsoft Azure Portal showing a Resource Lock applied, of type

    Read-Only Resource Lock

  2. CanNotDelete. This blocks the deletion of the resource but continues to allow access to make changes. This is a good starting point, but significant damage can still occur.

    Partial screenshot from Azure Portal, showing a resource group with a lock applied of type

    Do Not Delete Resource Lock

Resource Locks can be set through the usual methods – PowerShell, Resource Manager templates, CLI, REST API, and of course through the Portal. Only identities with Owner or User Access Administrator role can make changes, by default. However, the Azure RBAC model makes it possible to add custom roles with access to the Microsoft.Authorization/locks/* privileges.

    "type": "Microsoft.Web/sites/providers/locks",
    "apiVersion": "2016-09-01",
    "name": "[concat(variables('siteName'), '/Microsoft.Authorization/siteLock')]",
    "dependsOn": [
        "[resourceId('Microsoft.Web/sites', variables('siteName'))]"
    "properties": {
        "level": "CanNotDelete",
        "notes": "Site should not be deleted."

Assigning a lock through Azure Resource Manager is likewise straightforward – but with all automation, it is important to remember the roles and access rights that are required to apply and remove Locks. It is not helpful to automate a change to locks if it bypasses their intent, so locks may need to be applied as part of a separate template.

A key thing to remember about using Resource Locks is that to be useful, they must be removed with active user consent, so that the same mistakes cannot be repeated. An effective way to accomplish this is by making use of a separate account for this privilege. Separation of user duties – and privilege – is always an important part of the design when planning an operations model.

If your organization is investigating the use of Azure Blueprints, it’s important to note that the locks placed on Blueprint resources areĀ not the same as a Resource Lock. Microsoft’s official documentation on Resource Locking with Blueprints explains how it is different – the managed identity that deploys the Blueprint assigns a special RBAC role to the resource, effectively blocking changes even by identities with the Owner role assigned.

Leave a Reply

Your email address will not be published. Required fields are marked *