In our integration platform we have lots of developers continually developing multiple changes concurrently across many projects. It wouldnt be too difficult to accidently delete a resource. Obviously we mitigate this risk a lot by using devops pipelines for deployments to most environments but you know that Delete button is all to easily located next to the refresh button in the Azure portal.

We can mitigate this risk further by using Azure Resource Locks. I have round that simply applying a resource group level lock can be overly prohibitive so we wanted to add delete locks to certain resources in certain environments.

If ever we need to decommission a resource then we can remove its lock and delete it nice and safely but we also would usually use privileged identity manager so you can only delete a resource by elevating your permissions with an approval step.

Add Resource Locks

The below script can be used to add resource locks. Note that it has 2 lists where we can check for resource types and specific resources we want to exclude from the locks.



$mainEnvironmentName = $env:CommonSetting_EnvironmentName_LowerCase
$mainResourceGroupName = "Mike-RG-" + $mainEnvironmentName


function ApplyResourceLock([string] $resourceGroupName, [string] $resourceType, [string]$resourceName)
{       

    $existingLock = Get-AzResourceLock -ResourceName $resourceName -ResourceType $resourceType -ResourceGroupName $resourceGroupName
    if($existingLock -eq $null){

        $newLock = New-AzResourceLock -LockLevel CanNotDelete -LockName LockSite -ResourceName $resourceName -ResourceType $resourceType -ResourceGroupName $resourceGroupName -Force

        Write-Host 'New Lock Created, ID: ' $newLock.LockId  -ForegroundColor Green
    }
    else{
        Write-Host 'The Lock is already in place for resource' $resourceName ', Lock ID: ' $existingLock.LockId
    }
}

Write-Host $mainEnvironmentName
Write-Host $mainResourceGroupName


$resourcesToExclude = New-Object "System.Collections.Generic.List[System.String]"     
$resourcesToExclude.Add('my-resource-' + $mainEnvironmentName) 

$resourcesTypesToExclude = New-Object "System.Collections.Generic.List[System.String]"     
$resourcesTypesToExclude.Add('microsoft.alertsmanagement/smartdetectoralertrules') 
$resourcesTypesToExclude.Add('microsoft.insights/actiongroups') 
$resourcesTypesToExclude.Add('microsoft.insights/metricalerts')
$resourcesTypesToExclude.Add('microsoft.insights/workbooks')



$resources = Get-AzResource -ResourceGroupName $mainResourceGroupName
foreach($resource in $resources){
    Write-Host ''    
    Write-Host 'Processing Resource'  -ForegroundColor Green
    Write-Host '==================='  -ForegroundColor Green
    Write-Host 'Resource: ' $resource.Name
    Write-Host 'Resource Type: ' $resource.Type


    #If the resource type is not in the list of resource types to ignore then we will look to lock it
    if($resourcesTypesToExclude.Contains($resource.Type.ToLower()) -eq $false){
        
        #If resource is not in the specific list to exclude then we will lock it
        if($resourcesToExclude.Contains($resource.Name.ToLower()) -eq $false){

            #Check that a lock is applied to the resource
            ApplyResourceLock -resourceName $resource.Name  -resourceType $resource.Type -resourceGroupName $mainResourceGroupName 
        }
        else{
            Write-Host 'Skipping resource as its excluded'
        }
    }
    else{
        Write-Host 'Skipping resource as its excluded'
    }
}  


Remove Resource Locks

For troubleshooting we want to sometimes remove all resource locks on the resource group. Normally we would remove them individually just for the resources we need to delete but in a scenario where we want to make a bunch of changes we might remove the locks with the below script.



$mainEnvironmentName = $env:CommonSetting_EnvironmentName_LowerCase
$mainResourceGroupName = "Mike-RG-" + $mainEnvironmentName


Write-Host $mainEnvironmentName
Write-Host $mainResourceGroupName
 

$resourceLocks = Get-AzResourceLock -ResourceGroupName $mainResourceGroupName
foreach($resourceLock in $resourceLocks){
    Write-Host 'Remove: ' $resourceLock.LockId
    Remove-AzResourceLock -LockId $resourceLock.LockId
} 


 

Buy Me A Coffee