> ## Documentation Index
> Fetch the complete documentation index at: https://docs.costgraph.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Azure

> Connect an Azure billing scope to CostGraph from a FOCUS export in Blob Storage, with a Cloud Shell setup script

CostGraph reads your Azure spend from a **FOCUS billing export** in Blob Storage. You
create the export, the storage it lands in, and a read-only service principal, then
CostGraph ingests it as normalized, reconciled cost. The Azure integration asks for
Azure-named credentials (tenant, client, storage account); the generic Object Store
integration accepts the same setup with storage-level variable names.

One Cloud Shell script does all of it. Unlike Google Cloud, Azure exposes export
creation over its REST API, so there is no manual console step.

<Note>
  FOCUS exports need an **EA** or **MCA** billing scope (billing account, billing
  profile, invoice section, subscription, or resource group). Management groups and
  pay-as-you-go MOSP scopes do not support the FOCUS dataset.
</Note>

Azure savings recommendations are on by default. They are free and you can turn them off
by clearing **Show Azure savings recommendations** in the connect dialog. See
[Savings recommendations](#savings-recommendations).

## Step 1: Run the setup script

The connect dialog shows a one-line command. Open **Azure Cloud Shell** (Bash) and run
it:

```sh theme={null}
curl -sSL https://setup.costgraph.ai/integrations/azure.sh \
  | COSTGRAPH_EXTERNAL_ID="org_..." sh
```

Cloud Shell already carries your credentials, so there is no login step. The script is
idempotent, so rerun it safely after a partial failure. It needs permission to create
a resource group, a storage account, and an app registration in your directory.

It creates:

| Resource | Default | Purpose |
| - | - | - |
| Resource group | `costgraph-exports` | Holds the storage account |
| Storage account + container | `cgfocus<suffix>` / `focus-exports` | Destination for the export |
| Cost Management export | `costgraph-focus` | Daily FOCUS export, month-to-date, overwriting |
| Service principal | `costgraph-billing-reader` | Read-only credential CostGraph connects with |

The script also triggers the first export run. A first run can take up to 24
hours to produce files. If the connect check finds nothing to read yet, wait for
the first files in the container and connect again.

Set `COSTGRAPH_SUBSCRIPTION_ID`, `COSTGRAPH_RESOURCE_GROUP`, `COSTGRAPH_LOCATION`,
`COSTGRAPH_STORAGE_ACCOUNT`, or `COSTGRAPH_EXPORT_SCOPE` (for example
`/providers/Microsoft.Billing/billingAccounts/<id>`) to override the defaults. Set
`COSTGRAPH_EXPORT_DATA_VERSION` to `1.2-preview` for the preview FOCUS schema.

With recommendations on, the script also lets the service principal read Azure's
savings recommendations. It grants **Cost Management Reader** at your top management
group when you are allowed to, and otherwise on every subscription you can grant on. It
prints a `RECOMMENDATIONS` line with the result. When it could not cover every
subscription, it also prints the one command a management group admin runs to cover
the rest. Set `COSTGRAPH_ENABLE_RECOMMENDATIONS=0` to skip the grant; a rerun with it set
removes a grant an earlier run made.

The script also grants [network access](#network-access). Clear **Show how your
resources connect** in the connect dialog, or set `COSTGRAPH_ENABLE_NETWORK_INVENTORY=0`,
to leave it out.

## Step 2: Connect in CostGraph

The script ends by printing the values to paste into the connect form:

```
AZURE_TENANT_ID=<tenant id>
AZURE_CLIENT_ID=<client id>
AZURE_CLIENT_SECRET=<client secret>
AZURE_STORAGE_ACCOUNT=cgfocus....
AZURE_CONTAINER=focus-exports
AZURE_EXPORT_NAME=costgraph-focus
```

The Azure connect form asks for these by name, so each value has an obvious home.
Save the client secret when it is printed; it is not shown again. CostGraph validates it
can read the export, then starts the first sync.

## What it grants

Doing it by hand instead? These are the exact, least-privilege grants:

| Role | Scope | Why |
| - | - | - |
| `Storage Blob Data Reader` | the storage account | List and read the export blobs |
| `Cost Management Reader` | your top management group, or each subscription | Read Azure savings recommendations (optional) |
| `CostGraph Network Reader` (custom role) | your top management group, or each subscription | Read your network layout and shared file systems for Context (optional) |

The `CostGraph Network Reader` role holds only these permissions:

* `Microsoft.Network/networkInterfaces/read`
* `Microsoft.Network/loadBalancers/read`
* `Microsoft.Network/natGateways/read`
* `Microsoft.Network/routeTables/read`
* `Microsoft.ContainerService/managedClusters/read`
* `Microsoft.Compute/disks/read`
* `Microsoft.Network/privateEndpoints/read`

The service principal is the credential. No account key is stored, and access is
scoped to the one storage account rather than the subscription.

## Reservation and savings-plan utilization

CostGraph can also read how much of your reservation and savings-plan commitments is
actually used. That read lives on the billing account, not the storage account, so it
is an optional extra grant:

```sh theme={null}
az role assignment create --role "Billing Reader" \
  --assignee <client id> \
  --scope "/providers/Microsoft.Billing/billingAccounts/<billingAccountId>"
```

Reservation and savings-plan reads live on tenant-scoped resources, separate
from both the storage account and the billing-account scope earlier on this page. The exact
grants, by agreement type:

| What | MCA | EA |
| - | - | - |
| Reservation utilization | billing profile **Reader** role, or **Reservations Reader** (Entra, tenant or reservation-order scope) | Enterprise Administrator (read-only), or **Reservations Reader** (Entra, tenant or reservation-order scope) |
| Savings-plan utilization | billing profile Reader role, or **Savings plan Reader** (Entra, tenant scope) | Enterprise Administrator (read-only), or **Savings plan Reader** (Entra, tenant scope) |

For the Entra roles, assign the reader to the service principal, for example:

```sh theme={null}
az role assignment create --role "Reservations Reader" \
  --assignee <client id> \
  --scope "/"
```

Without these grants, cost ingestion works as usual and utilization is
not reported.

## Network access

Network access is the quickest way to fill in [Context](/costgraph/context) when only
your bill is connected. With it, CostGraph reads your Azure inventory and connects what
you run. Context shows each virtual network with its VMs and AKS clusters, and the
disks, Azure Files storage, NAT gateways, and load balancers they use. When network flow
tracing also runs, Context names the private traffic between them.

Network access is read-only and on by default. The script creates the
`CostGraph Network Reader` role and assigns it to the service principal. It assigns at
your top management group when you're allowed to, and otherwise on every subscription
you can assign on.

To also see workloads, usage, and live traffic, install the
[CostGraph Agent](/costgraph/agent) or the
[CostGraph Operator](/costgraph/operator/overview).

### Turn it on for an existing connection

Select **Grant network access** in Context to open the connect dialog with the command,
or rerun the setup command with `COSTGRAPH_ENABLE_NETWORK_INVENTORY=1`:

```sh theme={null}
curl -sSL https://setup.costgraph.ai/integrations/azure.sh \
  | COSTGRAPH_EXTERNAL_ID="org_..." COSTGRAPH_ENABLE_NETWORK_INVENTORY=1 sh
```

It prints a `NETWORK_INVENTORY_STATUS` line with one of `enabled`, `partial`, or
`not_enrolled`. Set the variable to `0` to remove the assignments, and the line reads
`disabled`. Without the variable, the script grants it. You don't need
to reconnect. CostGraph picks up the new access within the hour.

## Savings recommendations

With recommendations on, Azure's own cost recommendations appear in **Insights** next to
CostGraph's, for every subscription on your bill. Each one shows two numbers: "Azure
says" is Azure's estimate at list prices, and CostGraph's figure is calculated from your
bill.

* Reservation and savings plan recommendations show the on-demand spend on your bill
  they could cover, and the saving at the commitment rates in CostGraph's pricing.
* Recommendations CostGraph can't price yet show the monthly spend they affect, in
  Azure's own words, not a saving. They don't add to the savings total.
* The list follows your Azure Advisor settings: the CPU threshold you chose and any
  subscriptions or resource groups you excluded.

The connection card in **Settings > Integrations** tells you what to do if read access
is missing for every subscription.

### Turn them on for an existing connection

Re-run the setup command from the connect dialog with **Show Azure savings
recommendations** checked. If you cleared the box when you connected, also connect again
with it checked. Recommendations appear up to 24 hours later.

## What CostGraph does with it

* **Cost**: FOCUS line items normalized to a canonical model, keeping both billed and
  effective (amortized) cost, credits, and commitment attribution.
* **Reconciliation**: allocated plus unallocated cost is checked to equal the invoice
  per billing scope per month.
* **Allocation**: spend attributed by resource, resource group, subscription, and
  tags, with an explicit unallocated bucket for shared and commitment costs.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.