What a lock is
A resource lock is a guard rail on the Azure Resource Manager (ARM) control plane. It stops people (and pipelines) from deleting or changing a resource, even if their RBAC role allows it. An Owner can still be blocked by a lock until the lock is removed.
There are two levels:
| Lock level | Portal name | Blocks | Allows |
|---|---|---|---|
CanNotDelete | Delete | Delete of the resource (and the resource group / subscription if applied there) | Read, update, scale, restart |
ReadOnly | Read-only | Delete and any write (PUT/PATCH/POST) through ARM | Read (GET) only |
Locks are inherited. A lock on a resource group applies to every resource in it, including resources created later.
Tip
Use
CanNotDeletefor production resource groups, shared networking, Key Vaults and Log Analytics workspaces. UseReadOnlyrarely and on purpose; it breaks more than people expect (see below).
Add a lock
Azure CLI
# Lock a whole resource group against deletion
az lock create \
--name rg-prod-nodelete \
--resource-group rg-prod-app \
--lock-type CanNotDelete \
--notes "Production. Raise a change before removing."
# Lock one resource
az lock create \
--name kv-nodelete \
--resource-group rg-prod-app \
--resource-name kv-prod-app01 \
--resource-type Microsoft.KeyVault/vaults \
--lock-type CanNotDelete
PowerShell
New-AzResourceLock -LockName "rg-prod-nodelete" -LockLevel CanNotDelete `
-ResourceGroupName "rg-prod-app" -LockNotes "Production" -Force
Bicep
resource rgLock 'Microsoft.Authorization/locks@2020-05-01' = {
name: 'rg-prod-nodelete'
properties: {
level: 'CanNotDelete'
notes: 'Production. Raise a change before removing.'
}
}
Deploy that at resource-group scope and every resource in the group is covered.
Who can create and remove locks
You need Microsoft.Authorization/locks/* permissions. Built-in roles that have them: Owner and User Access Administrator. Contributor does not, which is the point: a Contributor can manage resources but cannot remove the guard rail.
List and find locks
# All locks in a subscription
az lock list --output table
# Locks that apply to one resource group (including inherited)
az lock list --resource-group rg-prod-app --output table
Resource Graph query to see every lock across subscriptions you can read:
resources
| where type =~ 'microsoft.authorization/locks'
| project name, level = properties.level, notes = properties.notes, id
Run it with az graph query -q "<query>" (needs the resource-graph extension).
Remove a lock
az lock delete --name rg-prod-nodelete --resource-group rg-prod-app
When someone gets "The scope ... cannot perform delete operation because following scope(s) are locked", the error text names the lock scope. Check there first.
Side effects of ReadOnly (read before you use it)
A ReadOnly lock blocks every ARM write, and many things that look like reads are actually POST operations.
| Operation | Why it fails under ReadOnly |
|---|---|
| Storage account: list keys, portal Storage Browser | listKeys is a POST |
| App Service: view publishing profile, some config blades | POST / write calls |
| VM: start, stop, restart | Write actions on the VM |
AKS: scale, upgrade, node pool changes, sometimes even az aks get-credentials | Write / POST (listClusterUserCredential) |
| Azure Backup: protecting a VM in a locked resource group | Backup service creates restore point collections |
| Resource group: creating any new resource | PUT on the group scope |
Data-plane operations (reading a blob with a SAS, querying a SQL database) are not blocked, because locks only apply to ARM.
Side effects of CanNotDelete
CanNotDelete is safer but still has gotchas:
- Azure Backup cleans up old restore points by deleting
RestorePointCollectionsresources. A delete lock on the VM's resource group can make backups fail after the collection limit is reached. Keep restore point collections in a separate, unlocked resource group if you lock the VM's group. - AKS node resource group (
MC_*): don't lock it. AKS needs to delete and recreate VMSS instances, disks and load balancer rules. - Databricks managed resource group: same rule; it is managed by the service.
- Terraform:
terraform destroyor a replacement (-/+) of a locked resource fails halfway through. Manage the lock in the same Terraform code, or exclude locked resources from destroy plans.
Warning
Don't put locks on resource groups owned by a service (AKS
MC_*, Databricks managed RG, Synapse managed RG). Use Azure Policy or deny assignments for those instead.
A simple standard to adopt
CanNotDeleteon every production resource group, created by the landing zone pipeline.- No
ReadOnlylocks except on frozen resources (for example, a decommissioned storage account kept for legal hold). - Only Owner / User Access Administrator (ideally through PIM) can remove locks.
- Lock notes say who to ask and why it exists.
- Weekly Resource Graph report of production resource groups without a lock.
Prevent it next time
- Enforce locks with Azure Policy (
deployIfNotExistson resource groups taggedenv=prod) so new groups get one automatically. - Alert on lock deletion: in Azure Monitor, create an Activity Log alert on the operation
Microsoft.Authorization/locks/delete. - Document the service-managed resource groups that must stay unlocked, so nobody "helpfully" locks them later.