Back to Checks
azure

Recovery Services backup policy has at least 30 days retention

recovery_vault_backup_policy_retention_adequate
Service: recoverySeverity: medium
OfficialBuilt-inVerified
Categories:forensics-ready
Resource Type:NotDefined

Azure Recovery Services backup policies are evaluated for adequate daily retention. Policies with fewer than 30 days of retention may not provide sufficient recovery points for incident investigation, compliance requirements, or ransomware recovery scenarios.

Risk

Short retention periods limit the ability to recover from delayed-discovery incidents such as ransomware that encrypts backups over time, data corruption that propagates across backup cycles, or compliance investigations requiring historical data. Insufficient retention may violate regulatory requirements.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler azure --checks recovery_vault_backup_policy_retention_adequate

Recommendation

Set daily backup retention to at least 30 days. For production workloads, consider 90+ days. Configure weekly, monthly, and yearly retention points for long-term compliance. Use immutable vaults to prevent backup deletion by compromised admin accounts.

Remediation

CLI

az backup policy set --resource-group <resource-group> --vault-name <vault-name> --name <policy-name> --policy @policy.json

Other

1Sign in to the Azure portal
2Go to Recovery Services vaults and select the vault
3Go to Backup policies
4Select the policy to modify
5Under Retention range, set Daily backup point retention to at least 30 days
6Click Save

Check Code

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

MINIMUM_RETENTION_DAYS = 30


class recovery_vault_backup_policy_retention_adequate(Check):
    """Check if vault backup policies retain backups for at least 30 days."""

    def execute(self) -> list[Check_Report_Azure]:
        """Execute the check across Recovery Services vault backup policies."""

        findings = []

        for subscription_name, vaults in recovery_client.vaults.items():
            for vault in vaults.values():
                if not vault.backup_policies:
                    report = Check_Report_Azure(
                        metadata=self.metadata(), resource=vault
                    )
                    report.subscription = subscription_name
                    report.resource_name = vault.name
                    report.resource_id = vault.id
                    report.location = vault.location
                    report.status = "FAIL"
                    report.status_extended = (
                        f"Recovery vault '{vault.name}' has no backup "
                        f"policies configured."
                    )
                    findings.append(report)
                    continue

                for policy in vault.backup_policies.values():
                    report = Check_Report_Azure(
                        metadata=self.metadata(), resource=vault
                    )
                    report.subscription = subscription_name
                    report.resource_name = f"{vault.name}/{policy.name}"
                    report.resource_id = policy.id
                    report.location = vault.location

                    if policy.retention_days is None:
                        report.status = "FAIL"
                        report.status_extended = (
                            f"Backup policy '{policy.name}' in vault "
                            f"'{vault.name}' has no daily retention configured."
                        )
                    elif policy.retention_days < MINIMUM_RETENTION_DAYS:
                        report.status = "FAIL"
                        report.status_extended = (
                            f"Backup policy '{policy.name}' in vault "
                            f"'{vault.name}' has {policy.retention_days}-day "
                            f"retention (minimum: {MINIMUM_RETENTION_DAYS})."
                        )
                    else:
                        report.status = "PASS"
                        report.status_extended = (
                            f"Backup policy '{policy.name}' in vault "
                            f"'{vault.name}' has {policy.retention_days}-day "
                            f"retention."
                        )

                    findings.append(report)

        return findings