Skip to content

J8 — Client Overview Dashboard — Test Runbook

Asset: J8 — client-facing, read-only Grafana dashboard (modules/azure/grafana-dashboards/dashboards/snowops-client-overview.json) + the client_grafana_viewers access hook + folder-aware deploy. Extends J5; no new module. Owner: SH · Milestone: M4.

J8 is the Tier-1, live client posture surface — the real-time counterpart to the periodic V5 posture report. It reuses the J5 instance, Monitoring Reader grant, offline gate, and deploy script.


Part A — Offline gate (~3 min, $0)

The J5 dashboards-as-code gate covers the new client dashboard automatically.

cd modules/azure/grafana-dashboards
./scripts/validate.sh            # or: python3 scripts/validate_dashboards.py

Acceptance: - [ ] Gate reports all 3 dashboards valid, including snowops-client-overview.json. - [ ] The client dashboard has the required datasource (scoped to grafana-azure-monitor-datasource) and workspace template variables, and every non-row panel binds to the Azure Monitor datasource with an Azure query — so it is portable across J5 instances like the ops dashboards. - [ ] Offline terraform validate of the J5 module still passes with the new client_grafana_viewers input — TestGrafanaDashboardsValidate (tests/terratest/modules/azure/grafana_dashboards_validate_test.go); the fixture now grants a client viewer.


Part B — Dashboard shape review (~3 min, $0)

Confirm the dashboard is organized by SnowOps deliverable, not raw metrics (the same taxonomy as V5):

  • Your guardrails row → Policy compliance % (AzureActivity/Policy) + Defender Secure Score % (SecureScores).
  • Your data is protected row → backup job status + restore operations (AddonAzureBackupJobs, the L1 backup + L4 restore evidence).
  • Security operations row → open Sentinel incidents by severity (SecurityIncident, the J3 feed).
  • No cost panel — cost has no SnowOps producer yet (U4/U5 postponed); like V5, J8 omits it honestly rather than showing a fabricated figure.

Part C — Live (client sees only the client folder) (~15 min, requires a deployed J5 instance)

  1. Grant the client AAD group instance access and deploy:
    client_grafana_viewers = [var.client_aad_group_object_id]
    
    ./scripts/deploy-dashboards.sh <grafana-name> <rg> "$(terraform output -raw workspace_id)"
    
  2. snowops-client-overview lands in the "SnowOps Client" Grafana folder; the ops dashboards stay in General.
  3. In Grafana, set folder permissions so the client group has Viewer on the "SnowOps Client" folder only (Managed Grafana RBAC) and no access to the ops folders.
  4. Sign in as a client-group member: the client sees only the client overview dashboard, read-only; panels query the J1 workspace (no Unauthorized — the instance identity already has Monitoring Reader).
  5. Confirm the client cannot edit or see internal-ops dashboards.

Notes

  • Why instance-level grant + folder permission: Azure RBAC Grafana Viewer is instance-scoped (sees all folders); true isolation is a Grafana folder permission applied once at deploy time. The README documents this clearly so it isn't mistaken for a Terraform-only guarantee.
  • No multi-tenant work: each client's J5 instance is already isolated (B-series per-client subscription model). A shared multi-tenant portal (W5) remains deferred (D35/D65).