Commit Graph
14 Commits
Author SHA1 Message Date
kyleandClaude Opus 5.5 c5fe69a813 Add a Pester test suite for the collectors
84 tests in collectors/tests, run with Invoke-CollectorTests.ps1 (~15 s,
PowerShell 7.2+ and Pester 5.5+):

- Module.Tests: the shared module (property lookup, time format,
  config/lookback, sent-run state and pruning, dry runs, exit codes,
  401 detection)
- Veeam/Mars/Wsb/Vb365.Tests: each collector run in its own process
  against its mock and a stand-in ingest API, asserting the behaviours
  confirmed on real servers: VBR 13 live schedule, copy jobs, MARS UTC
  times and ErrorCode 0, WSB culture-formatted times and nested VMs,
  VB365 organization mapping, log prefixes and retries, state and
  resending, rejected keys
- Installers.Tests: config, files and scheduled task from each
  installer, with stand-ins for icacls / Task Scheduler / the key prompt

Collectors run under the test runner's PowerShell, or another shell via
-CollectorShell (e.g. powershell.exe, to test under Windows PowerShell
5.1 like the MARS, WSB and VB365 servers). The mocks take their "now"
from MOCK_NOW so expectations can't drift with the clock; the WSB mock
gains -RunningJobFinished for the running-to-finished case.

Each of 12 past bugs, put back one at a time, fails the test for its
behaviour (and the runner exits 1).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 13:36:27 -06:00
kyleandClaude Opus 5.5 2fa9eea274 Replace basic auth with Microsoft 365 sign-in
nginx now checks every dashboard and API request with oauth2-proxy
(auth_request), which signs users in with Microsoft Entra ID. Who may
sign in is controlled in Entra: a single-tenant app registration with
"Assignment required", so only assigned users/groups get through.

- deploy/oauth2-proxy.cfg (entra-id provider, auth-only mode, secure
  cookie, trusted proxy = localhost) and deploy/oauth2-proxy.service
- nginx: pages redirect to Microsoft sign-in and back to the same URL;
  API calls get a plain 401 (the page already asks to reload);
  /api/v1/ingest stays key-only for collectors; /oauth2/auth is
  internal; the signed-in user is passed to the API in headers nginx
  sets (so browsers can't spoof them); dashboard files are served with
  Cache-Control: no-cache so updates show up at once
- GET /api/v1/me; the top bar shows the signed-in user and a Sign out
  that also signs out of Microsoft (otherwise SSO signs straight back in)
- README: Entra and server setup steps

Tested locally with oauth2-proxy 7.15.5 and nginx 1.31 running the
deploy configs (TLS, self-signed): redirects to the tenant's sign-in
with the return URL kept, 401s, ingest bypass, sign-out allow-list,
cookie flags, security headers. The signed-in path was tested with a
stand-in for oauth2-proxy's auth answer; a real Entra sign-in wasn't.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 11:31:35 -06:00
kyleandClaude Opus 5.5 8d0e6dca71 Move code shared by the collectors into one module
The Veeam, MARS, WSB and VB365 collectors each carried identical copies
of logging, ISO time conversion, property lookup, posting to the API,
config loading, TLS setup, the sent-runs state file and the 401 check,
and their installers repeated the same key prompt, locked-down config,
file copy and scheduled-task registration. These now live in
collectors/common/BackupDashboard.Collector.psm1:

- Initialize-Collector / Test-RunSent / Send-JobReport /
  Test-AuthRejected / Complete-Collector for collector runs
- Write-Log, Get-ErrorText, ConvertTo-IsoTime, Get-FirstValue
- Install-CollectorTask for the shared half of each installer

Collectors find the module next to themselves (installed) or in
..\common (repo); installers copy it into Program Files beside the
collector. The diagnostic scripts stay standalone single files.

No behavior change: a harness ran each collector against its mock
(12 scenarios: dry run, two real runs against a stub API, state file,
logs, exit codes, rejected key, en-GB, backfill) before and after, and
all 84 outputs are identical. Installers, run with stand-ins for the
Windows-only commands, write identical configs and tasks; the only
differences are the module being copied and the summary line naming
the shell's path.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 11:09:01 -06:00
kyleandClaude Opus 5.5 3f407ba76e Add Veeam Backup for Microsoft 365 collector
PowerShell script for the VB365 server, run hourly as a SYSTEM scheduled
task (Windows PowerShell 5.1 by default, -PwshPath for PowerShell 7).
One dashboard job per VB365 backup job and backup copy job.

- Sessions from Get-VBOJobSession (and Get-VBOCopyJobSession where
  available) within the lookback window; status from session Status,
  message from the session log's warning/error lines, size from
  Statistics.TransferredData ("1.5 GB" -> bytes)
- One VB365 server can protect several Microsoft 365 organizations, so
  the dashboard company is chosen per job: OrganizationTenants mapping,
  else Tenant, else the organization's name
- Next run from the job's NextRun; empty for disabled jobs
- Get-Vb365CollectorDiagnostics.ps1 dumps jobs and sessions, showing
  each DateTime's Kind (local vs UTC); installer adapted from MARS

Not yet run against a real server.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 10:31:43 -06:00
kyleandClaude Opus 5.5 a14b1b0dc9 Add Windows Server Backup collector
PowerShell script for servers using Windows Server Backup, run hourly as
a SYSTEM scheduled task under Windows PowerShell 5.1. Each server is one
dashboard job.

- Backup jobs from Get-WBJob (in progress and -Previous) within the
  lookback window; restores are ignored. WSB jobs have no ID, so runs
  are keyed on start time, which also merges a Running report with the
  finished one
- Error HRESULT -> failed; detailed error or a failed item -> warning;
  messages include the error description, codes as 0x8XXXXXXX, failed
  items and the failure log path
- Next run from Get-WBSummary's NextBackupTime
- Get-WsbCollectorDiagnostics.ps1 dumps the cmdlets' real objects and
  recent Microsoft-Windows-Backup events (to check whether job times
  are local or UTC); installer adapted from the MARS one

Not yet run against a real server.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 15:56:04 -06:00
kyleandClaude Opus 5.5 10181e014b Add Azure Backup (MARS agent) collector
PowerShell script for servers running the MARS agent, run as a SYSTEM
scheduled task (hourly) under Windows PowerShell 5.1, which the
agent's MSOnlineBackup module targets. Each server is one dashboard job.

- Backup jobs from Get-OBJob (in progress and -Previous) within the
  lookback window; restores are ignored. Completed with failed bytes
  or an error reports as warning
- Next run computed from the backup and System State policy schedules;
  left empty for every-N-weeks schedules to avoid false Overdue alarms
- Property reads tolerate unknown names, since the agent's object
  model isn't documented; Get-MarsCollectorDiagnostics.ps1 dumps the
  real structure for checking
- Install-MarsCollector.ps1 mirrors the Veeam installer; tests/MockMars.ps1
  provides stand-in cmdlets

Not yet run against a real MARS agent.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 15:23:46 -06:00
kyle 067b714678 Upload files to "/" 2026-10-07 20:10:11 +00:00
kyle ae574fa2b6 Delete README.md 2026-10-07 20:08:58 +00:00
kyle 8fd17e3817 Upload files to "/" 2026-10-07 20:05:28 +00:00
kyle b8452e1fbb Upload files to "/" 2026-10-06 00:55:03 +00:00
kyle 33c1613ef9 Update collectors/vveam/README.md 2026-10-06 00:54:38 +00:00
kyle be23e03c5f Upload files to "/" 2026-10-06 00:53:21 +00:00
kyle 996fe33a40 initial upload 2026-10-05 03:57:48 +00:00
kyle a8364930fb Initial commit 2026-10-04 04:31:49 +00:00