CostLensAzure Accounts

Azure Accounts

Connect an Azure subscription to CostLens with a dedicated App Registration granted Cost Management Reader — least privilege, no agents.

Updated July 20266 min read

CostLens reads your Azure cost data and resource configuration through a dedicated App Registration (service principal) granted the read-only Cost Management Reader role. Setup takes about 5 minutes, requires no agents, and never modifies your resources during scanning.

Multi-cloud from one workspace

Azure subscriptions sit alongside your AWS and GCP accounts in the same CostLens organization. Spend, recommendations, and fixes are filterable per cloud and rolled up across all of them.

How it works

StepWhat happens
1. You create an App RegistrationA dedicated Entra ID app + service principal that CostLens authenticates as.
2. You grant Cost Management ReaderRead-only access to cost data at the subscription (or management-group) scope.
3. CostLens scans automaticallyBilling data syncs every 6 hours via the Azure Cost Management Query API; optimisation checks and AI explanations run every 12 hours.

What you'll paste into CostLens

CostLens stores only non-secret identifiers plus one encrypted secret bundle:

FieldWhere it comes from
Tenant IDYour Entra ID directory ID
Client IDThe App Registration's Application (client) ID
Client secretThe secret you generate for the app (encrypted at rest with AES-256)
Subscription ID(s)The subscription(s) you want CostLens to analyse

The Add Account → Azure dialog generates this script with your IDs pre-filled and offers a one-click copy/download. Run it in Azure Cloud Shell or any terminal with the az CLI signed in as a user who can create app registrations and assign roles.

bash
#!/usr/bin/env bash
# CostLens — Azure connection setup (Cost Management Reader, least privilege)
set -euo pipefail
 
SUBSCRIPTION_ID="<SUBSCRIPTION_ID>"
APP_NAME="costlens-cost-reader"
 
az account set --subscription "$SUBSCRIPTION_ID"
 
# 1. Create an app registration + service principal
APP_ID=$(az ad app create --display-name "$APP_NAME" --query appId -o tsv)
az ad sp create --id "$APP_ID" >/dev/null
 
# 2. Create a client secret (valid 12 months) — copy the printed value
CLIENT_SECRET=$(az ad app credential reset --id "$APP_ID" --years 1 --query password -o tsv)
 
# 3. Grant Cost Management Reader (read-only cost data) at the subscription scope
az role assignment create \
  --assignee "$APP_ID" \
  --role "Cost Management Reader" \
  --scope "/subscriptions/$SUBSCRIPTION_ID"
 
TENANT_ID=$(az account show --query tenantId -o tsv)
 
echo ""
echo "Paste these into CostLens:"
echo "  Tenant ID:       $TENANT_ID"
echo "  Client ID:       $APP_ID"
echo "  Client secret:   $CLIENT_SECRET"
echo "  Subscription ID: $SUBSCRIPTION_ID"

Paste the four printed values into the CostLens connect dialog and click Save. CostLens validates the credentials and starts the first sync.

Broader scope

To cover many subscriptions at once, assign the role at a management group scope instead of a single subscription: --scope "/providers/Microsoft.Management/managementGroups/<MG_ID>". Enter the management group ID in the connect dialog and the generated script updates automatically.

Recommendations & Advisor

Azure recommendations come from two places, both read-only:

  • Azure Advisor cost recommendations (right-sizing, shutdown, reservations) — the authoritative source, surfaced by the Azure Advisor (Cost) check.
  • CostLens resource checks over the Azure Resource Manager + Monitor APIs — idle VMs, unattached disks, orphaned snapshots, idle public IPs and load balancers.

Reading Advisor, resource metadata, and Monitor metrics uses the Reader and Cost Management Reader roles. If you assigned only Cost Management Reader above, also add Reader at the same scope so the resource checks can enumerate resources:

bash
az role assignment create --assignee "$APP_ID" \
  --role "Reader" --scope "/subscriptions/$SUBSCRIPTION_ID"

Kubernetes (AKS) cost & optimization

The Cost Management Reader + Reader roles above already give CostLens what it needs for AKS. Reader covers Azure Monitor metric reads and VM Scale Set enumeration, so no separate Monitoring Reader role is required.

Node-pool optimization — no cluster change needed

CostLens follows each AKS node pool to its backing VM Scale Set (in the MC_… node resource group) and reads its CPU from Azure Monitor. Idle / right-sizing / Spot node-pool recommendations appear on the Recommendations page automatically. See Kubernetes Optimization.

Per-cluster node cost — automatic

AKS node compute lives in the cluster's node resource group (MC_<resource-group>_<cluster>_<region>). CostLens attributes that resource group's spend to the cluster using the Cost Management Reader role — nothing to enable.

Per-namespace & per-workload cost — enable the AKS cost analysis add-on

On each cluster, enable the AKS cost analysis add-on (Azure Portal → cluster → Cost analysis, or the aks-preview CLI). Azure Cost Management then allocates the cluster's spend by Kubernetes namespace and controller, which appears in the Kubernetes panel on the Billing page within ~24 hours. See Kubernetes Costs.

No agent, no cluster access

CostLens reads AKS cost and utilisation entirely from Cost Management, Azure Resource Graph, and Azure Monitor — there is nothing to install in the cluster and no Kubernetes API access is required.

Applying fixes (optional)

Scanning is fully read-only. Applying a fix (deallocating an idle VM, deleting an unattached disk/snapshot, releasing a public IP, removing an idle load balancer) requires write access. Grant a Contributor role — or a custom role limited to the specific write actions — at the scope you want CostLens to remediate. Without a write role, recommendations are shown but the Apply Fix button stays disabled. See Auto-Fix for the approval workflow.

Enabling automatic Auto-Fix (least privilege)

Automatic Auto-Fix (hands-off apply) on Azure covers exactly one reversible action today — stopping an idle VM (deallocate). To enable it with least privilege, grant only VM power control via a custom role rather than broad Contributor:

bash
az role definition create --role-definition '{
  "Name": "CostLens Auto-Fix (VM power)",
  "Description": "Least-privilege VM start/deallocate for CostLens Auto-Fix",
  "Actions": [
    "Microsoft.Compute/virtualMachines/read",
    "Microsoft.Compute/virtualMachines/start/action",
    "Microsoft.Compute/virtualMachines/deallocate/action"
  ],
  "AssignableScopes": ["/subscriptions/<SUBSCRIPTION_ID>"]
}'
az role assignment create --assignee "<CLIENT_ID>" \
  --role "CostLens Auto-Fix (VM power)" --scope "/subscriptions/<SUBSCRIPTION_ID>"
Destructive fixes (delete disk/snapshot, release IP, remove load balancer) are never auto-applied on any cloud — they always require manual approval with typed confirmation. Auto-applied idle-VM stops are reversible (start the VM again) and are watched after apply, with a 24-hour manual rollback window.

First sync phases

PhaseWhat happens
Fetching billing dataPulls monthly + daily cost (normalised to USD via the CostUSD metric) from the Cost Management Query API
Running optimisation checksIngests Azure Advisor + runs the CostLens resource checks
Generating AI explanationsAevi writes plain-English explanations and savings estimates

Common errors and fixes

ErrorFix
AUTH_FAILEDThe client secret is wrong or expired. Re-run az ad app credential reset and update the secret via Edit Credentials.
INSUFFICIENT_PERMISSIONSThe service principal is missing a role. Confirm Cost Management Reader (and Reader for resource checks) is assigned at the correct scope.
EXPORT_NOT_CONFIGUREDCost Management data isn't available yet for a new subscription — allow up to 24–48 hours after first usage.
No recommendations appearAzure Advisor needs a few days of usage to generate cost recommendations; resource checks require the Reader role.
No per-namespace AKS costEnable the AKS cost analysis add-on on the cluster; allow ~24h for allocated data to appear.
CostLens
Previous
AWS Accounts
CostLens
Next
GCP Accounts