Skip to main content

FinOps Azure Architecture

Architecture reference for the /finops:azure-monthly command. Documents the Azure-specific execution pipeline, Portal CSV as SSOT for EA billing, multi-tenant authentication pattern, and cross-validation approach — including the Vircom PAYG incident (API vs Portal discrepancy).


Diagram 1: End-to-End Phase Flow


Diagram 2: SSOT Decision Tree


Portal CSV as SSOT

For Enterprise Agreement tenants, the Azure Portal billing export is the authoritative data source. The API (az rest against Cost Management) is RBAC-scoped — subscriptions where the service principal lacks Reader access are invisible.

The Vircom PAYG Incident

SourceValue (NZD)Scope
API total (az rest)NZD 27,8906 RBAC-accessible subscriptions
Portal CSV exportNZD 43,4987 subscriptions + credits
DeltaNZD 15,608Vircom PAYG subscription (35.9% of total)

The Vircom PAYG subscription was not visible to az account list due to RBAC boundary. The API reported "30% under budget" when the actual spend was 8.7% over budget (pre-budget-update).

Rule: If a Portal CSV exists at cloudops/data/finops/azure/YYYY-MM/, it is the SSOT. API totals must include the caveat: "RBAC-scoped, may exclude ungoverned subscriptions."

Anti-pattern: FINOPS_API_SSOT_MISMATCH — presenting API-only totals without stating the RBAC caveat.


Multi-Tenant Authentication

Step 1: az account list
→ Returns all subscriptions in accessible tenants
→ Some tenants may require separate az login

Step 2: Identify tenant IDs
→ Group subscriptions by tenantId field
→ Flag subscriptions with inaccessible tenants

Step 3: Per-tenant token validation
→ az account get-access-token --tenant <tenantId>
→ Verify Cost Management scope access

Step 4: Run collection per tenant
→ Aggregate totals across tenants
→ Document inaccessible tenants in cross-validation.json

Never assume the AZURE_SUBSCRIPTION_ID environment variable represents the full tenant scope. Always enumerate all subscriptions via az account list before running cost queries.


Azure vs AWS Differences

DimensionAWSAzure
Billing SSOTCost Explorer (API = authoritative)EA: Portal CSV — PAYG/MCA: API
Auth modelIAM profiles with SSOService principal or az login per tenant
Multi-accountOrganizations API auto-enumeratesaz account list — tenants may be separate
CurrencyUSD (default)NZD for ANZ customers
Org hierarchyManagement account + linked accountsBilling account + subscriptions + resource groups
Recommendation sourceCost Explorer + Trusted AdvisorAzure Advisor (recommendationTypeId required)
RBAC visibility gapSCP boundaries (per-account)Subscription-level RBAC (per-subscription)
FOCUS 1.2+ outputaccount-costs.csvFOCUS 1.2 CSV with provider mapping
HITL gateReport total thresholdSame threshold, NZD currency

Live-Validated Results

Results from a 10-subscription Azure Landing Zone (2026-03-24):

MetricResultNotes
Subscriptions visible10az account list across 2 tenants
Tenants2 accessible + 2 inaccessibleDocument inaccessible tenants
Portal CSVSSOT for EA billingcloudops/data/finops/azure/YYYY-MM/
CFO modeWorkingNZD totals, spend vs budget
CTO modeWorkingService breakdown
FOCUS 1.2+ outputCSV generatedProvider field maps to Microsoft.Azure
HITL gateActiveTriggers when total exceeds threshold
Evidence pathtmp/cloud-infrastructure/finops/azure/Ephemeral

Quality Gates

GateCriteriaAction on Fail
G0az account list returns at least one subscriptionHALT, run az login
G1Cost Management API accessibleCheck RBAC role assignment
G2Portal CSV exists (EA only)Export from Azure Portal before running
G3API total vs Portal total gap documentedDocument RBAC-invisible subscriptions
G4Advisor recommendations include recommendationTypeIdRemove unverified savings estimates
G5FOCUS 1.2+ CSV writtenVerify provider field mapping
G6HITL gate passed for reports over thresholdBlock distribution

Quick Start
# Install
pip install runbooks

# Single subscription
uv run python -m runbooks.main finops azure-dashboard --subscription $AZURE_SUBSCRIPTION_ID

# Full tenant (recommended)
uv run python -m runbooks.main finops azure-dashboard --all --mode cfo

See the Azure quickstart guide for step-by-step instructions including Portal CSV export.

EA Billing — Portal CSV Required

For Enterprise Agreement tenants, run the Portal billing export BEFORE executing the command. Without the Portal CSV, the API-only total will miss RBAC-invisible subscriptions.

Export path: Azure Portal → Cost Management + Billing → Exports → Download CSV → save to cloudops/data/finops/azure/YYYY-MM/


Anti-Patterns

Anti-PatternDescriptionPrevention
FINOPS_API_SSOT_MISMATCHPresenting API total as authoritative for EA tenantsAlways check for Portal CSV; document RBAC gap
AZURE_SINGLE_SUBSCRIPTION_ASSUMPTIONTargeting single subscription without enumerating allRun az account list first
FINOPS_HALLUCINATED_SAVINGSSavings figures not sourced from Azure AdvisorAll savings must cite recommendationTypeId
NATO_VIOLATIONClaiming "report generated" without cross-validation.jsonRequire evidence file before completion claim

Architecture validated against CloudOps-S1 sprint, 2026-03-24. Component versions: runbooks v1.3.4, ADLC framework v3.7.2.