Prerequisites
- An Azure subscription where you hold Owner or User Access Administrator, so you can assign roles.
- Permission to create app registrations in Microsoft Entra ID: the Application Developer role, or Users can register applications set to Yes in Entra ID user settings.
- Multi-factor authentication registered on your account. Security defaults block app registration without it.
Limits to know first
- Client secret only. The dialog takes a client secret. It has no field for a certificate or a federated credential.
- One tenant per workspace. You get one Azure connection per workspace, covering every subscription the service principal can read in one tenant. A second tenant, such as a separate dev tenant, needs its own workspace with its own Rules and chats.
- One set of rules. Azure is a single-connection service, so its Environment stays Not set. Approval rules don’t read the environment in any case. To treat Azure writes differently, write a Rule that names this connection.
Setup
- Azure CLI
- Azure portal
1
Select the subscription
2
Create the service principal with Reader
password only once. The secret expires after one year by default. Add --years 2 (or another value) to change that, and set a reminder to rotate it.3
Add cost access
4
Optional: cover more subscriptions
To give the service principal both roles on every subscription you can see, loop over them. This is the recommended way, because you get an explicit list:A management group assignment is the trade-off: it covers new subscriptions automatically, but also ones you may not want CloudThinker to read. Use it only when that’s what you want:
5
Add the connection in CloudThinker
In the sidebar, click More → Workspace settings → Connections, select Microsoft Azure, and click Connect. The dialog has four fields and no Alias or Description, because Azure allows one connection per workspace. Fill them in like this, then click Connect:
Success state: the connection shows Connecting and Verifying, then a Connected status. Discovery now runs once in the background and spends credits. Check the Discovery section on the detail panel before your first prompt. See What happens after you connect.
Microsoft Customer Agreement billing
Only needed for Optimize on Microsoft Customer Agreement subscriptions. Pay-as-you-go subscriptions bought online usually sit on a Microsoft Customer Agreement (MCA). Cost Management rejects subscription-level queries for these withGiven subscription doesn't have valid WebDirect/AIRS offer type, so Optimize reads spend at the billing profile instead.
To check whether you’re on an MCA, run this. An MCA shows MicrosoftCustomerAgreement:
cloudthinker app. Subscription role assignments don’t reach billing scopes. To confirm it worked, open Optimize and check that Azure spend loads.
Connection details
There’s no subscription field. CloudThinker works with every subscription the service principal can read. If it can read more than one, Optimize asks you to Choose an Azure billing scope the first time you open it.
Required permissions
Reader alone returns no cost data. Reader grants
*/read, and a Cost Management query is a POST action that */read doesn’t cover.
Agent capabilities
CloudThinker runs read-only Azure CLI commands without asking. Changes follow the Write access model.Verify the connection
Example prompts
Write access
Allow writes on the connection’s detail panel controls whether agents may change anything in Azure. It’s on by default, but Reader and Cost Management Reader can’t change anything, so Azure refuses every write until you grant more.
To lock writes in CloudThinker as well, open Microsoft Azure in More → Workspace settings → Connections and turn off the Allow writes switch on its detail panel.
Rotate the client secret
Azure is a single-connection service, so it has no pencil icon or Edit Instance dialog while it’s healthy.
Rotating early costs more than replacing an expired secret, but don’t let the secret expire to save that work: an expired secret means an outage until you replace it. Rotate early in a quiet period. Reconnecting starts a new connection:
- Agents, automations, and Optimize can’t use Azure between the disconnect and the reconnect.
- Discovery runs again and spends credits.
- Allow writes goes back to on. Turn it off again if you had it off.
- Check that Rules naming the Azure connection still list it.
az ad sp credential reset --id <appId> --append, or use Microsoft Entra ID → App registrations → your app → Certificates & secrets. Without --append, the reset deletes the existing secrets, which breaks the connection right away.
Troubleshooting
Sign-in blocked by security defaults
Sign-in blocked by security defaults
az login or the portal returns AADSTS530035: Access has been blocked by security defaults. Security defaults require multi-factor authentication before you can register an app. Register a method at aka.ms/mfasetup and sign in again. The --use-device-code and --allow-no-subscriptions flags don’t get around this.Authentication failed
Authentication failed
Cause: a wrong APP_ID, CLIENT_SECRET, or TENANT_ID, an expired secret, or a conditional access policy. The Microsoft Entra error code tells you which:
Fix: if the values are right, confirm no conditional access policy blocks service principal sign-in.
Client secret expired
Client secret expired
Cause: the secret reached its expiry date (one year by default from the CLI).Fix: create a new secret, then click Replace credentials on the Microsoft Azure detail panel and save it. See Rotate the client secret.
Optimize says Azure Cost Management is not readable
Optimize says Azure Cost Management is not readable
Cause: the service principal lacks cost access.Fix: assign Cost Management Reader on the subscription. For a Microsoft Customer Agreement subscription, also assign Billing profile reader on the billing profile. Role assignments take a few minutes to propagate, so retry after that.
Cost Management returns 429
Cost Management returns 429
Cause: Cost Management heavily throttles new subscriptions, so queries answer
429 Too many requests. Nothing is misconfigured.Fix: wait a few minutes and reload Optimize.Resources or a subscription are missing
Resources or a subscription are missing
Cause: the service principal can’t read that subscription.Fix: assign Reader on every subscription you expect to see. The optional loop step in the Azure CLI tab does it in one go. Role assignments can take up to about 10 minutes to apply, so wait before you ask again.
Security
- Least privilege — grant only the permissions the agents need for your use case; start read-only and widen later.
- Read-only by default — use read-only credentials unless you want agents to make changes through this connection.
- Rotate credentials — rotate keys and tokens on your normal schedule; CloudThinker picks up the new value when you update the connection.
- Revoke on offboarding — remove the credential at the provider when you delete a connection or a teammate leaves.
- Expire and rotate secrets: always set an expiration on the client secret and rotate it before it lapses.
- Scope the roles: assign roles on the subscriptions CloudThinker needs. See the trade-off in the cover more subscriptions step.
Related
Optimize quickstart
See Azure spend and your first cost findings.
Connections overview
How connections, testing, and discovery work.