Azure Backup: Do I have resources NOT protected by backup?

This blog will show you how you can automate an overview using Kusto queries against Azure Resource Graph (ARG) to show specific resources NOT being protected by Azure backup services.

As part of Azure Backup services, Microsoft are offering 2 services which will keep your backups in a manageable vault: Azure Recovery Services Vaults and Azure Backup Vaults

Supported data sources by Azure Backups vaults:

Recovery Services VaultBackup Vault
Azure Virtual machines
SQL in Azure VM
Azure Files (Azure Storage)
SAP HANA in Azure VM
Azure Backup Server
Azure Backup Agent
DPM
 Azure Disks
 Azure Blobs (Azure Storage)
 Azure Database for PostgreSQL servers
 Kubernetes Services (Preview)

Of course you can choose to protect a resource by other 3rd party solutions – or you can choose not to protect it. But things can also be forgotten, if your environment is not managed through automation.

How to see resources NOT protected using the GUI?

Go into Azure Backup Center, and choose Protectable datasources – and now you can filter data source type and see resources NOT configured for backup.

How to see resources NOT protected using Kusto query?

As the data is stored inside Azure Resource Graph (ARG), you can query for the results, which means that you can use it as part of monitoring for non-protected resources.

If you continue reading, I have included modified kusto queries, which will cover 4 scenarios:

Azure VMs with no SQL databases configured for backup
Azure Virtual machines not configured for backup
Storage accounts with no Azure Blobs configured for backup
Managed Kubernetes Clusters with no resources configured for backup
You can find more scenarios using the ‘Open Query’ in the GUI for the specific workloads you are interested in.

Azure VMs with no SQL databases configured for backup

Resources 
    | where type in~ ('microsoft.compute/virtualmachines','microsoft.classiccompute/virtualmachines','microsoft.compute/virtualmachines/extensions')
    | extend armResourceId = id  
    | where name =~ 'SqlIaasExtension' 
    | where properties.type == 'SqlIaaSAgent' 
    | extend armResourceId = split(armResourceId,'/extensions/')[0] 
    | extend name = split(armResourceId, '/virtualMachines/')[1]
    | extend resourceId=tolower(armResourceId) 
    | join kind = leftouter ( RecoveryServicesResources
            | where type == "microsoft.recoveryservices/vaults/backupfabrics/protectioncontainers/protecteditems"
            | where properties.backupManagementType == "AzureWorkload"
            | where properties.workloadType in~ ("SQLDataBase")
            | project resourceId = tolower(tostring(properties.sourceResourceId)), backupItemid = id, isBackedUp = isnotempty(id) )
        on resourceId
    | extend isProtected = isnotempty(backupItemid) | where (isProtected == (0))
    | join kind=inner (resourcecontainers
            | where type == "microsoft.resources/subscriptions"
            | project subscriptionId, subscriptionName=name )
        on $left.subscriptionId == $right.subscriptionId

Azure Virtual machines not configured for backup

Resources 
| where type in~ ('microsoft.compute/virtualmachines','microsoft.classiccompute/virtualmachines') 
| extend armResourceId = id  
| extend resourceId=tolower(armResourceId)
| join kind = leftouter ( RecoveryServicesResources
        | where type == "microsoft.recoveryservices/vaults/backupfabrics/protectioncontainers/protecteditems"
        | where properties.backupManagementType == "AzureIaasVM"
        | where properties.workloadType in~ ("VM")
        | project resourceId = tolower(tostring(properties.sourceResourceId)), backupItemid = id, isBackedUp = isnotempty(id) )
    on resourceId
| extend isProtected = isnotempty(backupItemid) 
| where (isProtected == (0))
| join kind=inner (resourcecontainers
        | where type == "microsoft.resources/subscriptions"
        | project subscriptionId, subscriptionName=name )
    on $left.subscriptionId == $right.subscriptionId

Storage accounts with no Azure Blobs configured for backup

Resources 
| where type in~ ('microsoft.storage/storageAccounts') 
| extend armResourceId = id  
| where properties.isHnsEnabled != true 
| where properties.isNfsV3Enabled != true 
| where kind =~ 'StorageV2' and isnotnull(sku) and sku.tier =~ 'Standard'
| extend resourceId=tolower(armResourceId) 
| extend extendedLocationName=extendedLocation.name 
| join kind = leftouter ( RecoveryServicesResources
        | where type in~ ("microsoft.dataprotection/backupvaults/backupinstances", "microsoft.dataprotection/backupvaults/deletedbackupinstances")
        | where properties.dataSourceInfo.datasourceType == "Microsoft.Storage/storageAccounts/blobServices"
        | project resourceId = tolower(tostring(properties.dataSourceInfo.resourceID)), backupItemid = id, isBackedUp = isnotempty(id) ) 
    on resourceId
| extend isProtected = isnotempty(backupItemid) | where (isProtected == (0))
| join kind=inner (resourcecontainers
        | where type == "microsoft.resources/subscriptions"
        | project subscriptionId, subscriptionName=name )
    on $left.subscriptionId == $right.subscriptionId

Managed Kubernetes Clusters with no resources configured for backup

Resources 
| where type in~ ('Microsoft.ContainerService/managedClusters') 
| extend armResourceId = id   
| extend resourceId=tolower(armResourceId) 
| extend extendedLocationName=extendedLocation.name 
| join kind = leftouter ( RecoveryServicesResources
        | where type in~ ("microsoft.dataprotection/backupvaults/backupinstances", "microsoft.dataprotection/backupvaults/deletedbackupinstances")
        | where properties.dataSourceInfo.datasourceType == "Microsoft.ContainerService/managedClusters"
        | project resourceId = tolower(tostring(properties.dataSourceSetInfo.resourceID)), backupItemid = id, isBackedUp = isnotempty(id) ) 
    on resourceId
| summarize backupInstancesCountByServer = count(isBackedUp) by resourceId, id, subscriptionId, name, resourceGroup, location, tostring(tags)  
| where backupInstancesCountByServer == 0 
| join kind=inner (resourcecontainers
        | where type == "microsoft.resources/subscriptions"
        | project subscriptionId, subscriptionName=name )
    on $left.subscriptionId == $right.subscriptionId

Leave a Reply