tool
Azure backup coverage audit
A read-only CLI that answers "what isn't backed up?" across many subscriptions and tenants, and grades the backups that do exist.
Why
Backup coverage drifts. A VM gets built outside the usual pipeline, a SQL Server workload is registered with a vault but no database is ever protected, or a backup job starts failing and the alert goes unread. Answering “what isn’t backed up?” for one subscription means joining the resource inventory against what every vault protects. For a dozen subscriptions across several tenants, nobody does it by hand often enough.
What it does
- Inventory with Resource Graph. One set of queries pulls Recovery Services vaults, VMs, file shares, and SQL Server on VMs for every subscription in scope, paging through results with skip tokens.
- Protection from each vault. For every vault it lists the protected items and policies, eight vaults at a time, and marks policies that nothing uses.
- Derive what’s unprotected. Inventory is matched against protected items by resource ID, case-insensitively. SQL on VMs takes an extra step: a protected item’s source is sometimes the database and sometimes the VM, so the tool maps through the workload container back to the VM before deciding. The result is three findings: a VM that is not backed up, a SQL workload that was never registered, and a SQL workload that is registered with no protected database.
- Grade what exists. Each protected item is Clean, Warn, or Bad, and Bad wins. A failed or unhealthy last backup, an invalid or error state, or health that says action required is Bad. Completed-with-warnings, suspended backups, or action suggested is Warn.
Built to run unattended
Every run writes a timestamped directory with data.json (versioned schema, findings, and a non-fatal errors[] list), CSV views of each table, and a summary.md for people. The exit code is 0 for clean, 1 for findings, and 2 for an incomplete capture, so the same command works in a terminal, a scheduled job, or a pipeline gate.
It only reads. Reader or Backup Reader is enough. Missing permissions are recorded as capture errors and counted in the summary instead of being skipped, so a clean report can’t hide an RBAC gap.
By default it authenticates with DefaultAzureCredential. To cover several tenants, a TOML file lists one service principal per tenant and names the environment variable that holds each secret. The tool refuses to start if one is missing, and runs one worker per credential.
How it’s put together
- Python package with an argparse CLI that is a thin wrapper over a
run()function, so a later tool can aggregate several audits in-process. - 31 pytest tests covering the unprotected-resource logic, config parsing, and the severity rules, with fixtures instead of live Azure calls.
- ruff, pre-commit with gitleaks and shellcheck, and a devcontainer with the Azure CLI.
Not yet
Version 0.1 covers Recovery Services vaults. The newer Backup vaults, which protect blobs, managed disks, PostgreSQL, and AKS, are out of scope for now. SQL sub-policies are captured but not yet summarised.