• Skip to main content
  • Skip to secondary menu
  • Skip to primary sidebar
The Blog of Jorge de la Cruz

The Blog of Jorge de la Cruz

Everything about VMware, Veeam, InfluxData, Grafana, Zimbra, etc.

  • Home
  • VMWARE
  • VEEAM
    • Veeam Content Recap 2021
    • Veeam v11a
      • Veeam Backup and Replication v11a
    • Veeam Backup for AWS
      • Veeam Backup for AWS v4
    • Veeam Backup for Azure
      • Veeam Backup for Azure v3
    • VeeamON 2021
      • Veeam Announces Support for Red Hat Enterprise Virtualization (RHEV/KVM)
      • Veeam announces enhancements for new versions of Veeam Backup for AWS v4/Azure v3/GVP v2
      • VBO v6 – Self-Service Portal and Native Integration with Azure Archive and AWS S3 Glacier
  • Grafana
    • Part I (Installing InfluxDB, Telegraf and Grafana on Ubuntu 20.04 LTS)
    • Part VIII (Monitoring Veeam using Veeam Enterprise Manager)
    • Part XII (Native Telegraf Plugin for vSphere)
    • Part XIII – Veeam Backup for Microsoft Office 365 v4
    • Part XIV – Veeam Availability Console
    • Part XV – IPMI Monitoring of our ESXi Hosts
    • Part XVI – Performance and Advanced Security of Veeam Backup for Microsoft Office 365
    • Part XVII – Showing Dashboards on Two Monitors Using Raspberry Pi 4
    • Part XIX (Monitoring Veeam with Enterprise Manager) Shell Script
    • Part XXII (Monitoring Cloudflare, include beautiful Maps)
    • Part XXIII (Monitoring WordPress with Jetpack RESTful API)
    • Part XXIV (Monitoring Veeam Backup for Microsoft Azure)
    • Part XXV (Monitoring Power Consumption)
    • Part XXVI (Monitoring Veeam Backup for Nutanix)
    • Part XXVII (Monitoring ReFS and XFS (block-cloning and reflink)
    • Part XXVIII (Monitoring HPE StoreOnce)
    • Part XXIX (Monitoring Pi-hole)
    • Part XXXI (Monitoring Unifi Protect)
    • Part XXXII (Monitoring Veeam ONE – experimental)
    • Part XXXIII (Monitoring NetApp ONTAP)
    • Part XXXIV (Monitoring Runecast)
  • Nutanix
  • ZIMBRA
  • PRTG
  • LINUX
  • MICROSOFT

Veeam: Veeam Backup for Azure – Workload Protection History Report

1st July 2025 - Written in: veeam

Greetings friends, over the years, I have been creating all sort of scripts, dashboards, or tiny applications to solve Customers problems, or Community requests.

A few months ago I got an interesting use-case. When you are running thousands of workloads in Microsoft Azure and you want to audit, or submit to compliance the task can become a bit manual, going through your VB Appliance, etc.The specific use-case was that sometimes the team receives requests about data protection with an existing random vm names, with random dates to audit. That example right there is great, but there is no report that can cover that.

But, of course we have the powerful REST API for Veeam Backup for Azure:

  • https://helpcenter.veeam.com/docs/vbazure/guide/overview.html?ver=8
  • https://www.veeam.com/veeam_backup_azure_8_rest_api_reference_map_ot.pdf

Why this is great for Administrators

Managing thousands of workloads across Azure can quickly become overwhelming — especially when dealing with ad-hoc audit requests or compliance checks. Often, backup admins are asked to validate protection for a handful of VM names with completely random time ranges. There’s no built-in report in the UI that can handle that level of granularity or flexibility.

That’s where this script shines.

With just a few lines of PowerShell, we can:

  • Instantly query Veeam Backup for Azure’s REST API for any workload
  • Filter results by workload name(s) and time window
  • Export the results into clean, human-readable HTML and CSV formats
  • Save hours of manual digging through policy history
  • Confidently respond to compliance, audit, or license optimization requests

And best of all? It’s API-driven, scriptable, and 100% under your control.

Custom script in PowerShell

When working with It professionals, I found much simpler to work with PowerShell, which by the way can handle perfectly fine querying API endpoints and operating with them right after. The only tricky part perhaps is to combine everything into an HTML later on, but more on that later, let’s dissect a bit the Script.

  • Download the Script from here: https://github.com/jorgedlcruz/veeam-html-reporting/tree/main/veeam-backup-for-azure/workload-protection-history

After all ran successfully, you should have something similar to this:

It also has a nice output in the console:

1.- Disable SSL verification

I know I know, you might think this is insecure, etc. But it is very common, and much more nowadays, that appliances that comes from vendors, like VB Azure, to just trust the SSL that comes with and omit the headache of maintaining a SSL. But if you want to resolve this, I got you covered with the next blog post using Let’s Encrypt.

# Ignore SSL certificate validation errors (Not recommended for production)
Add-Type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

2.- Variables for the script

This is where you will spend the most time right. Probably once for the user/pass, but coming often to edit the name of the VMs, and dates you want to audit on:

# PARAMETERS
$veeamAzureServer = "https://YOURVBAZURE"
$veeamUsername = "YOURUSERNAME"
$veeamPassword = 'YOURPASS'
$apiVersion = "v8"
$vmNames = @('VMNAME1','VMNAME2','VMNAME3')
$startDate = Get-Date "2025-06-01"
$endDate = Get-Date "2025-12-31"

3.- Preparing the HTML/CSV and Export

An script is not an script without a proper and valid output. In this case I thought it could be cool to export as HTML, and CSV. Using the current time when the script was ran:

# OUTPUT
if ($policySessionObjects.Count -gt 0) {
$htmlHeader = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Schedule-Based Policies Session Report</title>
    <style>
        body { font-family: 'Open-Sans', sans-serif; padding: 10px; }
        table { width: 100%; border-collapse: collapse; }
        th, td { border: 1px solid #ddd; text-align: left; padding: 8px; }
        th { background-color: #f2f2f2; }
        .success { background-color: #28a745; color: white; font-weight: bold; }
        .failed { background-color: #dc3545; color: white; font-weight: bold; }
        .warning { background-color: #ffc107; color: black; font-weight: bold; }
    </style>
</head>
<body>
    <h1>Schedule-Based Policies Session Report</h1>
    <table>
        <tr>
            <th>VM Name</th>
            <th>Policy Name</th>
            <th>Session Type</th>
            <th>Result</th>
            <th>Session ID</th>
            <th>Start Time</th>
            <th>Stop Time</th>
            <th>Duration (s)</th>
        </tr>
"@

$htmlFooter = @"
    </table>
</body>
</html>
"@

$rowsHtml = $policySessionObjects | ForEach-Object {
    $resultStyle = switch ($_.Result) {
        "Success" { 'class="success"' }
        "Failed"  { 'class="failed"' }
        "Warning" { 'class="warning"' }
        Default   { '' }
    }
    "<tr><td>$($_.'VM Name')</td><td>$($_.'Policy Name')</td><td>$($_.'Session Type')</td><td $resultStyle>$($_.Result)</td><td>$($_.'Session ID')</td><td>$($_.'Start Time')</td><td>$($_.'Stop Time')</td><td>$($_.'Duration (s)')</td></tr>"
}

# Write files
$currentDate = Get-Date -Format "yyyy-MM-dd"
$htmlPath = Join-Path $PSScriptRoot "$currentDate-PolicySessionReport.html"
$csvPath = Join-Path $PSScriptRoot "$currentDate-PolicySessionReport.csv"

($htmlHeader + ($rowsHtml -join "`n") + $htmlFooter) | Out-File -FilePath $htmlPath -Encoding UTF8
$policySessionObjects | Export-Csv -Path $csvPath -NoTypeInformation

Write-Host "`nHTML report saved to: $htmlPath" -ForegroundColor Cyan
Write-Host "CSV report saved to: $csvPath" -ForegroundColor Cyan
} else {
    Write-Host "`nNo policy session information found in the selected date range." -ForegroundColor Yellow
}

And that’s it. Most likely this logic, and the use-case will be added to Veeam ONE in the future, but meanwhile, solving real-use case scenarios with API, always makes me happy.

I hope this is useful for you, give it a try and let me know.

Filed Under: veeam Tagged With: veeam audit, veeam cloud report, veeam cloud reporting, veeam reporting

Reader Interactions

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Primary Sidebar

  • E-mail
  • GitHub
  • LinkedIn
  • RSS
  • Twitter
  • YouTube

Posts Calendar

July 2025
M T W T F S S
 123456
78910111213
14151617181920
21222324252627
28293031  
« Jun    

Disclaimer

All opinions expressed on this site are my own and do not represent the opinions of any company I have worked with, am working with, or will be working with.

Copyright © 2025 · The Blog of Jorge de la Cruz