AWS CLI
Set up the Infracost AWS integration using the aws CLI directly — for scripting the setup yourself, or for teams that don't want to run Terraform, deploy a CloudFormation stack, or click through the console. Prefer infrastructure as code? See the Terraform guide or CloudFormation guide instead — both are easier to keep up to date and to roll out across many accounts. Prefer clicking through the console instead of the CLI? See the AWS Console guide.
This integration requires access to your AWS organization's management account. Reach out to support@infracost.io before getting started if you have questions.
This guide covers the required cross-account role setup. Two further capabilities are documented on their own pages, since each involves several AWS services:
- Cost and usage data exports — required, for FOCUS billing data, Cost Optimization Hub recommendations, and S3 Storage Lens metrics. You can either follow that guide to create the exports, or bring your own existing exports instead.
- Cost Anomaly Detection — optional, surfaces AWS-detected cost anomalies alongside your cost data.
Prerequisites
- The AWS CLI configured with credentials for your AWS organization's management account, and for every member account you want Infracost to see — for example, as separate named profiles
- Permission to create IAM roles and policies in those accounts
- Your Infracost External ID — in Infracost Cloud, go to Org Settings > General and copy the External ID. It is also shown on the AWS integration page. Used as the external ID for the cross-account role.
- Infracost's AWS account ID:
237144093413(do not change this unless instructed by Infracost)
The commands below omit --profile for brevity — add it (or set AWS_PROFILE) to target a specific account.
Step 1: Create the cross-account role
Repeat this step identically in your management account first, then in each member account you want Infracost to see. Every command is the same for both account types except the read-only policy in step 3.
Not sure which account is your management account? Run aws organizations describe-organization from any member account — it returns the management account's ID in MasterAccountId.
1. Create the role
Save the trust policy to trust-policy.json, substituting your Infracost External ID:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::237144093413:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "YOUR_EXTERNAL_ID"
}
}
}
]
}
Then create the role:
aws iam create-role \
--role-name infracost-readonly \
--assume-role-policy-document file://trust-policy.json \
--no-cli-pager
2. Attach the AWS-managed view-only policy
aws iam attach-role-policy \
--role-name infracost-readonly \
--policy-arn arn:aws:iam::aws:policy/job-function/ViewOnlyAccess \
--no-cli-pager
3. Add the Infracost read-only policy
This is the one command that differs by account type — management accounts get more permissions (billing, cost, and organization data that only the management account can see), while member accounts get a smaller set.
Management account policy (management account only)
Save as readonly-policy.json:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InfracostManagementAccountReadOnly",
"Effect": "Allow",
"Resource": "*",
"Action": [
"acm:ListTagsForCertificate",
"amplify:ListApps",
"amplify:ListTagsForResource",
"apigateway:GET",
"apprunner:ListServices",
"apprunner:ListTagsForResource",
"bcm-data-exports:Get*",
"bcm-data-exports:List*",
"ce:Describe*",
"ce:Get*",
"ce:List*",
"compute-optimizer:Get*",
"cost-optimization-hub:Get*",
"cost-optimization-hub:List*",
"ec2:DescribeClientVpnEndpoints",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeTransitGatewayAttachments",
"ecr:ListTagsForResource",
"globalaccelerator:ListTagsForResource",
"macie2:ListTagsForResource",
"organizations:DescribeOrganization",
"pricing:Describe*",
"pricing:Get*",
"pricing:List*",
"rds:ListTagsForResource",
"s3:GetBucketLocation",
"s3:GetBucketTagging",
"s3:GetStorageLensConfiguration",
"s3:GetStorageLensConfigurationTagging",
"s3:GetStorageLensDashboard",
"s3:ListStorageLensConfigurations",
"savingsplans:ListTagsForResource",
"scheduler:ListTagsForResource",
"tag:GetResources",
"trustedadvisor:Get*",
"trustedadvisor:List*"
]
}
]
}
Member account policy (every other account)
Save as readonly-policy.json:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InfracostMemberAccountReadOnly",
"Effect": "Allow",
"Resource": "*",
"Action": [
"acm:ListTagsForCertificate",
"amplify:ListApps",
"amplify:ListTagsForResource",
"apigateway:GET",
"apprunner:ListServices",
"apprunner:ListTagsForResource",
"ec2:DescribeClientVpnEndpoints",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeTransitGatewayAttachments",
"ecr:ListTagsForResource",
"globalaccelerator:ListTagsForResource",
"macie2:ListTagsForResource",
"rds:ListTagsForResource",
"s3:GetBucketLocation",
"s3:GetBucketTagging",
"savingsplans:ListTagsForResource",
"scheduler:ListTagsForResource",
"tag:GetResources"
]
}
]
}
Then, on every account, attach whichever version of readonly-policy.json you saved above:
aws iam put-role-policy \
--role-name infracost-readonly \
--policy-name infracost-readonly \
--policy-document file://readonly-policy.json \
--no-cli-pager
4. Add the role introspection policy
Infracost uses this second inline policy to check its own permissions, so it can tell you which features are available given the access you've granted, without failing at feature-detection time.
Save as introspection-policy.json, replacing 111111111111 with this account's ID:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InspectRole",
"Effect": "Allow",
"Action": [
"iam:GetRole",
"iam:ListRolePolicies",
"iam:GetRolePolicy",
"iam:ListAttachedRolePolicies",
"iam:SimulatePrincipalPolicy"
],
"Resource": "arn:aws:iam::111111111111:role/infracost-readonly"
},
{
"Sid": "InspectAttachedPolicies",
"Effect": "Allow",
"Action": [
"iam:GetPolicy",
"iam:GetPolicyVersion"
],
"Resource": "*"
}
]
}
aws iam put-role-policy \
--role-name infracost-readonly \
--policy-name infracost-role-introspection \
--policy-document file://introspection-policy.json \
--no-cli-pager
5. Note the role ARN
aws iam get-role --role-name infracost-readonly --query 'Role.Arn' --output text --no-cli-pager
You'll need the management account's ARN (for example, arn:aws:iam::111111111111:role/infracost-readonly) in Step 2 below.
When new features are added, this role's policies may need to be updated to include new permissions. Infracost will notify you when an update is required — see Upgrading below.
Step 2: Add the integration in Infracost Cloud
After creating the role in your management account (and any member accounts), add the integration to Infracost from the dashboard:
- Go to Org Settings > Integrations > Add integrations, then click Add integration for Amazon Web Services.
- Enter an Alias to identify the integration, and the management account's Role ARN you noted in step 5 above (for example,
arn:aws:iam::111111111111:role/infracost-readonly). - Click Test connection to verify Infracost can assume the role.
- Once the test passes, save the integration.
(Optional) Improve console links for SSO users
If your team signs in through IAM Identity Center (AWS SSO), set your access portal URL so console links to resources on findings route through the portal and open in the correct account — without it, the links can fail for federated users who aren't already signed in.
In the dashboard, go to Org Settings > Agent settings and set AWS access portal to your portal URL, for example https://your-subdomain.awsapps.com/start. You can find this by running aws sso-admin list-instances --no-cli-pager, or under IAM Identity Center > Settings > AWS access portal URL in the console. Leave it blank to keep using direct console links.
Next steps
Your cross-account role is set up, but Infracost still needs cost and usage data exports to show FOCUS billing data, Cost Optimization Hub recommendations, and S3 Storage Lens metrics — this is a required step. If you don't already have these exports, follow the Cost and usage data exports guide next.
Optionally, also set up Cost Anomaly Detection so Infracost can surface AWS-detected cost anomalies.
Upgrading
As Infracost adds support for additional capabilities there may be a need to update the role's permissions.
Don't forget to review the terraform-aws-integration release notes — the Terraform module and CloudFormation template are the source of truth for what permissions this role needs, even if you manage the role yourself via the CLI.
When Infracost notifies you of a required update, add the new actions AWS specifies to readonly-policy.json and re-run the put-role-policy command from step 3 above — it overwrites the existing inline policy of the same name.
Removing
Repeat on each account where you created the role:
aws iam delete-role-policy --role-name infracost-readonly --policy-name infracost-readonly --no-cli-pager
aws iam delete-role-policy --role-name infracost-readonly --policy-name infracost-role-introspection --no-cli-pager
aws iam detach-role-policy \
--role-name infracost-readonly \
--policy-arn arn:aws:iam::aws:policy/job-function/ViewOnlyAccess \
--no-cli-pager
aws iam delete-role --role-name infracost-readonly --no-cli-pager
If you added others, such as infracost-kms-decrypt or infracost-s3-access, delete those inline policies first — delete-role fails while any policies are still attached.
Any resources you created for data exports or anomaly detection are not removed automatically — see those pages' own removal notes.
Troubleshooting
Test connection fails with "Access Denied" or "AssumeRole" errors
- Double-check the Infracost External ID in
trust-policy.jsonexactly matches the value Infracost gave you. - Confirm the trust policy's principal is
arn:aws:iam::237144093413:root— a typo here is the most common cause. - Confirm you're providing the role ARN from the management account, not a member account.
Infracost reports missing permissions for a feature you expect to have
Re-check that you attached the correct read-only policy for the account type — the management account policy includes several actions (bcm-data-exports:*, ce:*, compute-optimizer:*, cost-optimization-hub:*, organizations:DescribeOrganization) that the member account policy intentionally omits.