TL;DR: Attach an IAM policy allowing the Cost Explorer read actions, then flip the account-level switch that lets IAM identities access billing at all: in the Billing console, under IAM user and role access to billing information, activate it as the root user. The policy alone is not enough, and this second step is the one most troubleshooting guides miss. Re-run the call and expect cost data back.

The exact error:

```text
AccessDeniedException: User: [FINOPS-READER-USER-ARN] is not authorized to perform: ce:GetCostAndUsage on resource: *
```

1. Confirm who is calling: `aws sts get-caller-identity`
   Expected: the ARN matches the user or role in the error, so you are fixing the right identity.
2. Check whether this is a member account in an Organization: only the payer account holds the consolidated billing data, so member-account callers need the payer's data shared or must call from the payer.
   Expected: you know whether the data even exists in this account.
3. Attach a policy granting the Cost Explorer read actions to the identity:
   ```json
   {
     "Version": "2012-10-17",
     "Statement": [
       {
         "Effect": "Allow",
         "Action": [
           "ce:GetCostAndUsage",
           "ce:GetCostForecast",
           "ce:GetDimensionValues",
           "ce:GetTags"
         ],
         "Resource": "*"
       }
     ]
   }
   ```
   Expected: the policy attaches with no syntax errors.
4. As the root user, open the Billing console, find the setting for IAM user and role access to billing information, and activate it. This is account-level and defaults to off.
   Expected: the console confirms IAM access to billing is activated.
5. Re-run the failing call: `aws ce get-cost-and-usage --time-period Start=2026-09-01,End=2026-10-01 --granularity MONTHLY --metrics BlendedCost`
   Expected: a JSON cost-and-usage response instead of AccessDeniedException.

## Use this when
- The error names ce:GetCostAndUsage, ce:GetCostForecast, or other ce: read actions
- An IAM user or assumed role gets AccessDeniedException on Cost Explorer APIs
- The policy looks correct but the denial persists, which points at the account-level switch
- A FinOps tool or agent fails its first billing API call in a new account

## Not for this skill when
- The error is about the CUR S3 bucket or a KMS key, which are storage and encryption permissions, not Cost Explorer API permissions
- You are in a member account expecting payer-level consolidated data without cross-account setup
- The call throttles with Rate exceeded instead of denying, which is a backoff problem

## Variant phrasings
- user is not authorized to perform ce:GetCostAndUsage
- cost explorer access denied IAM role
- enable IAM access to billing information
- ce:GetCostAndUsage forbidden

## Why it happens
AWS locks billing data behind two gates. The IAM policy is the identity gate, and the account setting is the account gate: even a perfect policy fails while the account still reserves billing for the root user. New accounts and Organization member accounts hit this constantly because the setting is buried in the Billing console and defaults to off.

## Edge cases
- Only the root user can flip the account-level switch, so an admin without root credentials has to escalate
- In Organizations, the payer account sees everything while member accounts see only their own usage unless consolidated data sharing is configured
- The setting can take a few minutes to propagate; a retry loop that gives up after one attempt will report a false failure
- Service control policies on the OU can deny ce: actions above the identity policy, so check effective permissions if both gates look open

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_TZwcqaToeouR2VFrYIfvkQ
