Back to Checks
azure

Virtual Machine is protected by Azure Backup

vm_backup_enabled
Service: vmSeverity: high
OfficialBuilt-inVerified
Categories:resilience
Resource Type:microsoft.compute/virtualmachines

Azure VMs are evaluated for protection by Azure Backup by confirming they exist as VM backup items in a Recovery Services vault.

VMs absent from any vault item indicate no configured backup coverage.

Risk

Unprotected VMs jeopardize availability and integrity. Deletion, corruption, or ransomware can wipe data, and without recovery points recovery is slow or impossible, causing extended outages, missed RPO/RTO, and cascading impact on dependent services.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler azure --checks vm_backup_enabled

Recommendation

Protect all VMs with Azure Backup in a Recovery Services vault under a standardized policy. Align schedules and retention to RPO/RTO, use GRS/ZRS and immutable vault features, enforce least privilege on backup operations, automate enrollment at provisioning, and regularly test restores.

Remediation

CLI

az backup protection enable-for-vm --resource-group <vault-resource-group> --vault-name <vault-name> --vm <vm-name> --vm-resource-group <vm-resource-group> --policy-name DefaultPolicy

Terraform

# Protect an existing VM with Azure Backup
resource "azurerm_backup_protected_vm" "<example_resource_name>" {
  resource_group_name = "<example_resource_name>"   # vault's resource group
  recovery_vault_name = "<example_resource_name>"
  source_vm_id        = "<example_resource_id>"     # critical: VM to protect
  backup_policy_id    = "<example_resource_id>"     # critical: policy that enables backup
}

NativeIaC

// Enable Azure Backup protection for an existing VM in an existing Recovery Services vault
param vmId string            // e.g., /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Compute/virtualMachines/<vm>
param vaultName string
param vaultRg string
param policyId string        // e.g., /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.RecoveryServices/vaults/<vault>/backupPolicies/<policy>

resource vault 'Microsoft.RecoveryServices/vaults@2023-04-01' existing = {
  name: vaultName
  scope: resourceGroup(vaultRg)
}

var vmRg = split(split(vmId, '/resourceGroups/')[1], '/')[0]
var vmName = split(vmId, '/virtualMachines/')[1]

resource protect 'Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems@2023-02-01' = {
  // critical: this resource creates the protected item, enabling backup for the VM
  name: '${vault.name}/Azure/protectionContainers/iaasvmcontainer;iaasvmcontainerv2;${vmRg};${vmName}/protectedItems/VM;iaasvmcontainerv2;${vmRg};${vmName}'
  properties: {
    protectedItemType: 'Microsoft.Compute/virtualMachines' // critical: VM backup item type
    sourceResourceId: vmId                                 // critical: target VM to protect
    policyId: policyId                                     // critical: associates the VM with a backup policy
  }
}

Other

1In Azure Portal, go to Virtual machines > <VM> > Backup
2Select a Recovery Services vault in the same region (or create one if prompted)
3Choose the DefaultPolicy (or an existing VM backup policy)
4Click Enable backup

Check Code

from azure.mgmt.recoveryservicesbackup.activestamp.models import DataSourceType

from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.recovery.recovery_client import recovery_client
from prowler.providers.azure.services.vm.vm_client import vm_client


class vm_backup_enabled(Check):
    """
    Ensure that Microsoft Azure Backup service is in use for your Azure virtual machines (VMs).

    This check evaluates whether each Azure VM in the subscription is protected by Azure Backup.

    - PASS: The VM is protected by Azure Backup (present in a Recovery Services vault).
    - FAIL: The VM is not protected by Azure Backup (not present in any Recovery Services vault).
    """

    def execute(self) -> list[Check_Report_Azure]:
        """Execute Azure VM backup enabled check.

        Returns:
            A list of reports containing the result of the check.
        """
        findings = []
        for subscription_id, vms in vm_client.virtual_machines.items():
            subscription_name = recovery_client.subscriptions.get(
                subscription_id, subscription_id
            )
            vaults = recovery_client.vaults.get(subscription_id, {})
            for vm in vms.values():
                found = False
                found_vault_name = None
                for vault in vaults.values():
                    for backup_item in vault.backup_protected_items.values():
                        if (
                            backup_item.workload_type == DataSourceType.VM
                            and backup_item.name.split(";")[-1].lower()
                            == vm.resource_name.lower()
                        ):
                            found = True
                            found_vault_name = vault.name
                            break
                    if found:
                        break
                report = Check_Report_Azure(metadata=self.metadata(), resource=vm)
                report.subscription = subscription_id
                if found:
                    report.status = "PASS"
                    report.status_extended = f"VM {vm.resource_name} in subscription {subscription_name} ({subscription_id}) is protected by Azure Backup (vault: {found_vault_name})."
                else:
                    report.status = "FAIL"
                    report.status_extended = f"VM {vm.resource_name} in subscription {subscription_name} ({subscription_id}) is not protected by Azure Backup."
                findings.append(report)
        return findings