Back to Checks
azure

Virtual Machine has a backup policy with a daily retention period meeting the configured minimum

vm_sufficient_daily_backup_retention_period
Service: vmSeverity: medium
OfficialBuilt-inVerified
Categories:resilience
Resource Type:microsoft.compute/virtualmachines

Azure virtual machines are evaluated for a backup policy in a Recovery Services vault with a daily retention period that meets the configured minimum. VMs lacking protection or using a shorter retention window are identified for review.

Risk

Insufficient or missing VM backups weaken availability and integrity. Short retention reduces recovery points, limiting rollback after ransomware, accidental deletion, or faulty changes. This increases RPO, extends RTO, and can force rebuilds, causing data loss and downtime.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler azure --checks vm_sufficient_daily_backup_retention_period

Recommendation

Enforce backup policies that provide daily retention aligned to business RPO/RTO for every VM. Apply defense in depth: isolate backups in a vault, enable immutability/soft delete, limit changes with least privilege and MFA, and regularly test restores. Use tiered retention (daily/weekly/monthly/yearly) based on data criticality.

Remediation

Terraform

# Backup policy with sufficient daily retention
resource "azurerm_backup_policy_vm" "<example_resource_name>" {
  name                = "<example_resource_name>"
  resource_group_name = "<example_resource_name>"
  recovery_vault_name = "<example_resource_name>"

  backup {
    frequency = "Daily"
    time      = "23:00"
  }

  retention_daily {
    count = 7 # CRITICAL: ensures daily retention meets minimum required days
  }
}

# Protect the VM with the compliant policy
resource "azurerm_backup_protected_vm" "<example_resource_name>" {
  resource_group_name = "<example_resource_name>"
  recovery_vault_name = "<example_resource_name>"
  source_vm_id        = "<example_resource_id>"
  backup_policy_id    = azurerm_backup_policy_vm.<example_resource_name>.id # CRITICAL: applies the policy to the VM
}

NativeIaC

// Create/ensure a VM backup policy with daily retention >= minimum
resource rv 'Microsoft.RecoveryServices/vaults@2023-01-01' existing = {
  name: '<example_resource_name>'
}

resource vmPolicy 'Microsoft.RecoveryServices/vaults/backupPolicies@2023-02-01' = {
  name: '${rv.name}/<example_resource_name>'
  properties: {
    backupManagementType: 'AzureIaasVM'
    schedulePolicy: {
      schedulePolicyType: 'SimpleSchedulePolicyV2'
      scheduleRunFrequency: 'Daily'
      scheduleRunTimes: ['2020-01-01T23:00:00Z']
    }
    retentionPolicy: {
      retentionPolicyType: 'LongTermRetentionPolicy'
      dailySchedule: {
        retentionTimes: ['2020-01-01T23:00:00Z']
        retentionDuration: {
          count: 7 // CRITICAL: sets daily retention to at least the minimum required days
          durationType: 'Days' // explains the unit
        }
      }
    }
  }
}

Other

1In Azure portal, go to Recovery Services vault <example_resource_name>
2Select Backup policies > Azure Virtual Machine > Edit (or Create new)
3Set Daily retention to at least 7 days and Save
4Go to Backup items > Azure Virtual Machine
5If the VM is unprotected: click Backup, select the policy from step 3, and Enable
6If the VM is already protected with an insufficient policy: select the VM > Change Policy > choose the policy from step 3 > Save

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_sufficient_daily_backup_retention_period(Check):
    """
    Ensure there is a sufficient daily backup retention period configured for Azure virtual machines.
    - PASS: The VM has a backup policy with sufficient daily retention period.
    - FAIL: The VM does not have a backup policy or the retention period is insufficient.
    """

    def execute(self) -> list[Check_Report_Azure]:
        findings = []
        min_retention_days = getattr(vm_client, "audit_config", {}).get(
            "vm_backup_min_daily_retention_days", 7
        )

        for subscription, vms in vm_client.virtual_machines.items():
            subscription_name = recovery_client.subscriptions.get(
                subscription, subscription
            )
            vaults = recovery_client.vaults.get(subscription, {})
            for vm in vms.values():
                backup_found = False
                retention_days = 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()
                        ):
                            backup_found = True
                            policy_id = backup_item.backup_policy_id
                            if policy_id and policy_id in vault.backup_policies:
                                retention_days = vault.backup_policies[
                                    policy_id
                                ].retention_days
                            break
                    if backup_found:
                        break
                if backup_found and retention_days:
                    report = Check_Report_Azure(metadata=self.metadata(), resource=vm)
                    report.subscription = subscription
                    if retention_days >= min_retention_days:
                        report.status = "PASS"
                        report.status_extended = f"VM {vm.resource_name} in subscription {subscription_name} ({subscription}) has a daily backup retention period of {retention_days} days (minimum required: {min_retention_days})."
                    else:
                        report.status = "FAIL"
                        report.status_extended = f"VM {vm.resource_name} in subscription {subscription_name} ({subscription}) has insufficient daily backup retention period of {retention_days} days (minimum required: {min_retention_days})."
                    findings.append(report)
        return findings