Trust

What the IAM role actually does

Last updated October 13, 2026

Overview

The "Connect AWS" flow deploys a CloudFormation stack in your AWS account. CostPulse never touches your credentials. The stack creates one read-only IAM role and, unless you point it at an export you already have, the Cost & Usage Report export that role reads. Every permission the role holds is listed below, statement by statement, and CostPulse calls every one of them. Nothing is granted just in case.

This page is a summary. The template is the source of truth: read the raw YAML, the same file the "Launch CloudFormation stack" button deploys. If this page and the YAML ever disagree, the YAML is what runs in your account.

This page describes template version 2. Your stack's TemplateVersion output shows which version you deployed. A stack with no such output is version 1, which also granted read-only actions CostPulse never called: seven more Cost Explorer actions, the account alias and account name, AWS Organizations account listing, and report and export definitions. To drop them, update the stack with the current template. Nothing stops working if you don't.

What the stack creates

With the default CurSetupMode = CreateNew, the stack creates these resources in your account, in us-east-1:

  • An S3 bucket, costpulse-cur-<your account ID>. It is encrypted (SSE-S3), blocks all public access, and expires objects after 120 days. It has DeletionPolicy: Retain, so deleting the stack keeps the bucket and its data. It is yours.
  • A bucket policy that lets only the AWS Data Exports and billing report services, acting for your own account, write into that bucket.
  • A CUR 2.0 data export that writes hourly cost and usage data to that bucket as Parquet.
  • The IAM role costpulse-readonly-<your account ID>.

With CurSetupMode = UseExisting, the stack creates only the IAM role and points it at the bucket and prefix you name.

The export the stack creates selects these CUR 2.0 columns: billing period start, payer account ID, line item ID, time interval, line item description, line item type, operation, product code, resource ID, unblended cost, usage account ID, usage amount, usage start and end dates, usage type, pricing unit, product family, region code, service code, and resource tags.

Who can assume the role

The role's trust policy names one principal, CostPulse's AWS account (arn:aws:iam::922981237283:root by default), and allows the assume only when the request presents the External ID CostPulse generated for your account. That condition prevents a "confused deputy" attack, where a different AWS customer could otherwise trick CostPulse into reading your account instead of theirs.

What's granted, and why

The role has one inline policy, CostPulseBillingReadOnly, with these statements:

Sid: ListCURBucket · Resource: the CUR bucket (limited to your prefix if you set one)
s3:ListBucket · s3:GetBucketLocation

Lets CostPulse find new report files and build an S3 client for the bucket's region. No other bucket in your account.

Sid: ReadCURObjects · Resource: objects under the CUR prefix only
s3:GetObject

Reads the report files themselves. This is the only object data the role can read.

Sid: CostExplorerRead · Resource: *
ce:GetCostAndUsage

When you connect, CostPulse calls ce:GetCostAndUsage to backfill about 90 days of daily spend, so detection works before the first CUR file arrives. Read-only.

Sid: BedrockMetricsRead · Resource: * (every CloudWatch metric in the account)
cloudwatch:GetMetricData · cloudwatch:ListMetrics

CostPulse queries only the AWS/Bedrock namespace, for per-model invocation and token counts, so it can attribute Bedrock spend to individual models. The grant itself is not limited to that namespace: these two read actions cannot be scoped by namespace in IAM, so the role could read any CloudWatch metric in the account. Metrics only: no access to CloudWatch Logs or prompt content.

What's not granted

No write, delete, or configuration-change permission anywhere in your account. No access to S3 objects outside the CUR bucket and prefix, RDS or DynamoDB data, CloudWatch Logs, secrets, or parameters. No AWS credentials of yours ever reach CostPulse's servers, only the ARN of the role you provision and the External ID it was created with.

Revoking access

Delete the CloudFormation stack (or just the IAM role, if you created it another way) at any time. Deleting the role ends CostPulse's access; CostPulse has no other path into your environment. Deleting the stack also removes the data export and the bucket policy. The CUR bucket and the files already in it are kept, because they are yours. Delete the bucket yourself if you no longer want them.

More detail

For encryption, infrastructure, subprocessors, and how to report a security issue, see the full Security page.