Connecting Azure Cost Management
Factor Fifty imports Azure cost and usage details from customer-owned Azure Cost Management exports. The recommended setup writes daily FOCUS 1.2-preview Parquet files to a dedicated Blob container. For managed CSP, a dedicated Billing identity reconciles the exports and reads only that container.
For CSP customer tenant (all subscriptions), Factor Fifty discovers the subscriptions in the tenant and maintains one export per subscription. Subscriptions can be added or removed without repeating onboarding.
The CSP connection imports the retail costs Azure exposes to the customer. It does not include CSP discounts, credits, partner-earned credit (PEC), or partner invoice pricing. A partner billing integration is required to reconcile those amounts.
Azure identity model
Keep the following identities separate. A Factor Fifty Admin credential is not required for billing ingestion.
| Identity | Purpose | Ongoing Azure access |
|---|---|---|
FactorFifty-reader | Resource inventory, posture, monitoring, and reporting | Reader and optional read-only permissions for the environments that use it |
FactorFifty-billing | Azure cost export control and cost-file ingestion | Factor Fifty Billing Export Operator at the tenant root for managed CSP, plus Storage Blob Data Reader on the exact export container |
FactorFifty-admin | Optional Factor Fifty operations that change Azure resources | Contributor and Role Based Access Control Administrator only on subscriptions where managed operations are enabled |
| Onboarding operator | Runs the generated PowerShell once | Enough access to create the storage resources, custom role, and role assignments; this sign-in is not stored by Factor Fifty |
The Billing identity combines the two permissions required by the ingestion pipeline: narrow Cost Management export control and read access to the exported files. It is not a general Azure administrator and receives no workload-management permissions.
What is covered
| Agreement and source | Coverage |
|---|---|
| CSP customer tenant + Create a dedicated export | Every discoverable, operable subscription in the Billing credential's tenant; membership is reconciled automatically |
| CSP customer tenant + Reuse an existing FOCUS export | Only the subscription scope of that existing export |
| EA or MCA | The Microsoft Billing scope entered during onboarding |
Use the managed CSP option when complete tenant coverage is required. Azure does not support FOCUS exports at management-group scope, so Factor Fifty creates subscription-scoped exports and combines their files during ingestion. This preserves the complete FOCUS dataset instead of substituting the more limited management-group usage export.
Factor Fifty treats incomplete discovery or export reconciliation as an error. It does not silently report a partial tenant total as healthy.
Here, complete coverage means every FOCUS cost-and-usage line item Azure exposes to the customer across every operable subscription. It does not mean every Azure billing dataset, nor does it include the CSP partner invoice items excluded above.
Before you begin
You need:
- A dedicated, active Billing Azure credential in Factor Fifty
- PowerShell 7.2 or later with
Az.Accounts,Az.Resources, andAz.Storage - A storage subscription in the same Microsoft Entra tenant as the Billing credential
- An onboarding operator who can create the resource group, Storage account, and container in that subscription
- For managed CSP, permission to create a custom role and role assignment at the tenant root management group
- For CSP, customer cost visibility enabled by the CSP partner
The onboarding operator and Billing identity are different. The operator authorizes the initial setup through device-code sign-in; Factor Fifty stores only the dedicated Billing credential for ongoing work.
Create the Billing credential
Do not reuse FactorFifty-reader or FactorFifty-admin.
Do not add Microsoft Graph Application permissions, an Entra directory role, subscription Reader, Contributor, or Owner to FactorFifty-billing. The Billing connection uses Azure RBAC assigned to the app registration's enterprise application (service principal), not permissions from the API permissions page.
The generated PowerShell grants the service principal exactly what the selected connection needs:
| Connection | Azure RBAC role | Scope | Granted by |
|---|---|---|---|
| Managed CSP tenant | Factor Fifty Billing Export Operator | Tenant root management group | Generated PowerShell |
| Every Azure Billing connection | Storage Blob Data Reader | Exact export Blob container | Generated PowerShell |
The custom export role lets Factor Fifty discover subscriptions and read or manage Cost Management exports. The Blob role lets it list and download the manifests and Parquet files. Neither role permits general Azure workload administration.
- In the Microsoft Entra admin center, open App registrations and select New registration.
- Name it
FactorFifty-billing, select Accounts in this organizational directory only, and leave the redirect URI empty. - Copy its Application (client) ID and Directory (tenant) ID.
- Under Certificates & secrets, create a client secret. Copy the secret Value immediately and record its expiry date.
- In Factor Fifty, open Azure Credentials, select Add Azure Credential, and enter those values.
- Select Billing as the credential type and save it.
At this point, it is expected that the new app registration has no manually assigned Azure role. Generate and run the onboarding script in the next steps; it creates and verifies the required assignments. See Permissions granted to the Billing identity for the exact custom-role actions.
Permissions required by the onboarding operator
The person running the generated script needs more access temporarily because that person—not FactorFifty-billing—creates the Azure resources and assignments:
| Scope | Required capability |
|---|---|
| Tenant root management group for managed CSP | Create a custom role definition and assign it (Microsoft.Authorization/roleDefinitions/write and Microsoft.Authorization/roleAssignments/write) |
| Storage subscription | Create or inspect the resource group, Storage account, and container; register Microsoft.CostManagementExports |
| Exact export container | Create the Storage Blob Data Reader assignment |
| EA or MCA billing scope | Create, update, and run Cost Management exports |
Owner at the tenant root management group and storage subscription is sufficient for the managed CSP setup, but a customer can instead combine narrower roles containing the listed capabilities. EA and MCA billing scopes use their own agreement-specific billing roles; subscription Owner alone does not necessarily grant access to those scopes. These elevated permissions belong only to the onboarding operator and are not stored by Factor Fifty.
Complete the Factor Fifty form
Open the customer, select Billing Connections, choose Microsoft Azure, and complete the three steps.
1. Choose the Azure billing source
| Field | What to enter |
|---|---|
| Display name | A recognizable name such as Production Azure billing |
| Agreement type | Microsoft Customer Agreement (MCA), Enterprise Agreement (EA), or CSP customer tenant (all subscriptions) |
2. Configure the customer-owned export
| Field | What to enter | Notes |
|---|---|---|
| Export source | Create a dedicated export (recommended) or Reuse an existing FOCUS export | Managed CSP requires the dedicated option for automatic all-subscription coverage. |
| Azure Billing credential | The non-expired FactorFifty-billing credential for this tenant | Only credentials with type Billing are listed. |
| Billing scope resource ID | The relevant Azure billing resource ID | Disabled for managed CSP because the tenant is taken from the Billing credential. |
For EA and MCA, use one of these billing-scope formats:
| Agreement type | Billing scope format |
|---|---|
| MCA | /providers/Microsoft.Billing/billingAccounts/{account}/billingProfiles/{profile} |
| EA | /providers/Microsoft.Billing/billingAccounts/{enrollment-number} |
For managed CSP, do not enter a subscription ID as the billing scope. Factor Fifty records the tenant coverage internally and discovers subscriptions with the Billing identity.
Create a dedicated export
| Field | What to enter |
|---|---|
| Storage subscription ID | The subscription where the dedicated Storage account should be created |
| Storage region | An Azure region identifier such as westeurope |
The generated setup uses:
| Azure resource | Generated value |
|---|---|
| Resource group | factor-fifty-finops |
| Storage account | fffinops plus the first 16 hexadecimal characters of the connection UUID |
| Blob container | factor-fifty |
| Root directory | factor-fifty/{customer-uuid}/{connection-uuid} without UUID hyphens |
| Export prefix | ff-finops-{connection-uuid} without UUID hyphens |
The account blocks public Blob access and the container's public-access setting is None. The requested history window is 12 months including the current month.
For EA and MCA, the script creates the scoped recurring and historical exports. For managed CSP, the script creates storage and permissions; after the receipt is saved, Factor Fifty discovers subscriptions and creates the recurring and historical export set in the background.
Reuse an existing FOCUS export
| Field | What to enter | Example |
|---|---|---|
| Storage account resource ID | The complete Azure Resource Manager ID | /subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Storage/storageAccounts/{account-name} |
| Export container | The configured Blob container | cost-exports |
| Export directory | The root folder without a leading or trailing slash | exports/focus |
| Cost Management export name | The exact Azure export name | daily-focus-cost |
The export must use the following contract:
| Setting | Required value |
|---|---|
| Dataset | Cost and usage details (FOCUS), version 1.2-preview |
| Format and compression | Parquet with Snappy |
| Partitioning | Enabled |
| Schedule | Active and daily |
| Timeframe | Month to date |
| Update behavior | Overwrite previous report |
| Destination | Exactly the account, container, and directory entered in Factor Fifty |
The adoption script validates this contract and grants the Billing identity container-scoped read access. It does not modify or delete the customer's export.
3. Run PowerShell and save the receipt
- Select Generate PowerShell.
- Copy the entire script.
- Run it as the onboarding operator in Azure Cloud Shell PowerShell or local PowerShell 7.2+.
- Copy the final one-line JSON receipt printed by the script.
- Paste it into PowerShell JSON receipt and select Save connection.
The receipt binds the connection to the selected tenant, Billing credential, storage destination, and role assignments. Factor Fifty validates these identifiers before saving.
Azure produces exports asynchronously. The connection remains PROVISIONING while Factor Fifty reconciles the export set and waits for the first valid manifest and all referenced Parquet parts. You can close the modal after saving.
Where to run PowerShell
Azure Cloud Shell
- Open Azure Cloud Shell and select PowerShell.
- Confirm that you are signing into the tenant of the selected Billing credential.
- Create
onboarding.ps1, paste the complete generated script, and save it. - Run
./onboarding.ps1. - Follow the device-code prompt with the onboarding operator account.
Do not change the tenant or storage subscription embedded in the script. Change the Factor Fifty form and regenerate the script if either value is wrong.
Local macOS
Install PowerShell 7 and the Azure PowerShell modules, then run the saved script:
Install-Module -Name Az -Repository PSGallery -Force
pwsh ./onboarding.ps1
Permissions granted to the Billing identity
Export control for managed CSP
The script creates Factor Fifty Billing Export Operator at the tenant root management group. It contains only these management-plane actions:
Microsoft.Resources/subscriptions/read
Microsoft.Management/managementGroups/read
Microsoft.Billing/billingPeriods/read
Microsoft.Billing/billingProperty/read
Microsoft.Consumption/*/read
Microsoft.CostManagement/*/read
Microsoft.CostManagement/exports/write
Microsoft.CostManagement/exports/delete
Microsoft.CostManagement/exports/action
Microsoft.CostManagement/exports/run/action
The role has no data actions and cannot create, update, or delete customer workloads. Factor Fifty uses it to discover subscriptions and create, update, run, or retire only Cost Management exports.
Export-file access
The script assigns Storage Blob Data Reader to FactorFifty-billing at exactly:
/subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Storage/storageAccounts/{storage-account}/blobServices/default/containers/{container}
Azure management-plane Reader does not grant access to Blob contents. Do not broaden this assignment to the Storage account, resource group, or subscription.
Automatic CSP subscription reconciliation
After onboarding, Factor Fifty regularly compares the tenant's subscription set with its managed export set.
- Enabled and Past Due subscriptions receive a current daily export and the configured historical exports.
- A newly discovered subscription is added automatically. Azure notes that Cost Management features can take up to 48 hours to become available for a new subscription.
- A subscription removed from the tenant is retired from the managed export set.
- Existing historical coverage is retained when a previously covered subscription becomes non-operable.
- A newly discovered non-operable subscription produces a coverage error instead of being silently omitted.
The connection is healthy only when subscription discovery and the required export reconciliation complete successfully. This is what prevents a one-subscription result from being presented as an all-subscription total.
Verify the connection
In Factor Fifty
| Status | Meaning |
|---|---|
| PROVISIONING | Setup is saved; Factor Fifty is reconciling subscriptions or waiting for Azure RBAC and export delivery. |
| ACTIVE | Factor Fifty has validated and staged at least one export run and background imports are enabled. |
| ERROR | Authentication, subscription coverage, export control, Blob access, networking, or file validation failed. |
After Azure delivers data, allow up to one collector interval—currently 15 minutes—for Factor Fifty to discover it. A large history import can take longer.
In Azure
For managed CSP, inspect Cost Management → Exports on several subscriptions rather than checking only the storage subscription. Managed export names begin with ff-finops-; history exports also include their month.
For each checked export:
- Confirm the recurring schedule is Active and Daily.
- Open Run history and look for Completed.
- Confirm the destination matches the Factor Fifty Storage account, container, and directory.
- Open the run folder in Blob Storage and confirm it contains a manifest plus every
.parquetpart named by that manifest.
Azure can take up to 24 hours to complete the initial export. Once a run begins, Microsoft says the data should normally be available within four hours. Daily timing is not fixed.
Migrate an older subscription-scoped CSP connection
Use a new connection UUID so the tenant-wide stream has its own storage directory and export names.
- Create and save a dedicated Billing credential.
- Start a new Azure Billing connection and choose CSP customer tenant (all subscriptions) and Create a dedicated export.
- Generate and run the new PowerShell script.
- Immediately before saving the new receipt, disconnect the old subscription-scoped connection to prevent overlapping imports.
- Save the new receipt and monitor it until the tenant-wide connection is healthy.
Do not point the new connection at the old connection's directory. Previously imported data remains subject to the configured retention policy after disconnecting.
Disconnecting
Disconnecting blocks new Factor Fifty deliveries immediately and deactivates the connection's active imported streams.
For a Factor Fifty-managed connection, use the generated offboarding details to remove its export-control and Blob-reader assignments and retire its managed exports. For an adopted export, do not delete or change the customer's export; remove only the recorded Storage Blob Data Reader assignment.
Troubleshooting
Only one subscription appears
Confirm that the connection uses CSP customer tenant (all subscriptions) with Create a dedicated export, not an adopted subscription-scoped export. Then verify that the Billing identity has Factor Fifty Billing Export Operator at:
/providers/Microsoft.Management/managementGroups/{tenant-id}
Do not solve this by adding subscriptions manually. The reconciler should discover them; a discovery or permission problem should put the connection in error.
PowerShell cannot create the custom role or assignment
The onboarding operator lacks role-definition or role-assignment permission at the tenant root management group. Ask a tenant administrator to run the script or temporarily grant the operator the required access. Do not grant general administration to FactorFifty-billing.
Azure rejects CSP export creation
Ask the CSP partner to enable customer cost visibility for the tenant. Storage and RBAC permissions cannot replace this policy.
Factor Fifty cannot read the container
Verify that Storage Blob Data Reader is assigned to the FactorFifty-billing service principal at the exact container scope, the secret is current, Azure RBAC has propagated, and the Storage network allows the collector to reach the Blob endpoint.
An export succeeded but the connection is still provisioning
Confirm that the completed run produced its manifest and every referenced Parquet part under the saved directory. For managed CSP, also check for a subscription coverage error; one successful subscription does not prove complete tenant coverage.