AWS Integration
The AWS Integration connects your AWS organization to Infracost Cloud, giving Infracost read-only access to your billing data as well as AWS account metadata. This enables visibility into actual cloud costs and usage across your organization alongside your infrastructure-as-code cost estimates.
This integration requires access to your AWS organization's management account. Reach out to support@infracost.io before getting started if you have questions.
Initial Configuration
Prerequisites
- Access to the AWS console on your AWS organization's management account
- Permission to create IAM roles and policies in that account
- Your Infracost External ID — find it in Infracost Cloud under Agents → Integrations → AWS. Used as the external ID for the cross-account role.
Step 1: Deploy Infracost cross-account link
The Infracost AWS Integration uses a Terraform module to provision a read-only IAM role in your accounts. Infracost uses this role to access the data needed to power cost visibility features.
Add the following to your Terraform configuration for your management account:
module "infracost_management_account" {
source = "github.com/infracost/cross-account-link?ref=v0.11.0"
infracost_external_id = "YOUR_EXTERNAL_ID"
is_management_account = true
providers = {
aws = aws.management_account
}
}
Replace YOUR_EXTERNAL_ID with the value from the prerequisites.
Repeat this for each member account in your AWS organization, using is_management_account = false:
module "infracost_member_account_1" {
source = "github.com/infracost/cross-account-link?ref=v0.11.0"
infracost_external_id = "YOUR_EXTERNAL_ID"
is_management_account = false
providers = {
aws = aws.member_account_1
}
}
Include an outputs.tf for each account so you can easily reference the ARNs needed in a later step. Replace MODULE_NAME with the name you used above:
output "account_id" {
description = "The AWS account ID where the module was provisioned."
value = module.MODULE_NAME.account_id
}
output "account_region" {
description = "The AWS region of the account where the module was provisioned."
value = module.MODULE_NAME.account_region
}
output "role_arn" {
description = "The ARN of the Cross-Account Role with IAM read-only permissions. Provide this to Infracost."
value = module.MODULE_NAME.role_arn
}
output "billing_and_cost_management_export_arn" {
description = "The ARN of the BCM Data Exports export. Provide this to Infracost."
value = module.MODULE_NAME.billing_and_cost_management_export_arn
}
output "billing_and_cost_management_bucket_arn" {
description = "The ARN of the S3 bucket used for BCM Data Exports. Provide this to Infracost."
value = module.MODULE_NAME.billing_and_cost_management_bucket_arn
}
output "s3_storage_lens_configuration_arn" {
description = "The ARN of the S3 Storage Lens configuration. Provide this to Infracost."
value = module.MODULE_NAME.s3_storage_lens_configuration_arn
}
output "s3_storage_lens_bucket_arn" {
description = "The ARN of the S3 bucket used for S3 Storage Lens exports. Provide this to Infracost."
value = module.MODULE_NAME.s3_storage_lens_bucket_arn
}
Then run:
terraform init
terraform apply
Once applied, Terraform will output Cross-Account Link role ARNs for each account — you'll need them in Step 3.
When new features are added, this module may need to be updated to include new permissions. Infracost will notify you when an update is required.
Step 2: Enable cost and usage data exports to Infracost
For deeper visibility into actual AWS spend, including individual billing line items and S3 usage metrics — you can configure data exports to S3 buckets that Infracost will ingest.
Enrollment prerequisites
Enable Cost Optimization Hub and Compute Optimizer
The Cost Optimization Hub recommendations export requires your AWS Organization's management account to be opted in to both AWS Compute Optimizer and AWS Cost Optimization Hub, org-wide.
These enrollments are not managed by the Terraform module — they are global, account-level toggles that must be performed manually, one-time, against the management account before applying:
aws compute-optimizer update-enrollment-status \
--status Active \
--include-member-accounts \
--region us-east-1
aws cost-optimization-hub update-enrollment-status \
--status Active \
--include-member-accounts \
--region us-east-1
AWS documents that enrollment can take up to 24 hours to take effect, though it is often faster.
Enable trusted access for S3 Storage Lens
S3 Storage Lens must have trusted access configured for cross-account visibility.
This configuration is not managed by the Terraform module — it is a global, account-level toggle that must be performed manually, one-time, against the management account before applying:
aws organizations enable-aws-service-access --service-principal storage-lens.s3.amazonaws.com
Configuration
module "infracost_management_account" {
source = "github.com/infracost/cross-account-link?ref=v0.11.0"
infracost_external_id = "YOUR_EXTERNAL_ID"
is_management_account = true
enable_data_exports = true # <-- Set this variable to true
providers = {
aws = aws.management_account
}
}
This provisions the configuration and storage for the following exports:
The data exports are read periodically by Infracost, which may incur minor AWS query costs (~$0.0004 per 1,000 S3 requests). S3 storage costs also apply.
After completing the export configuration, AWS can take upwards of 24 hours to populate the buckets with the first data exports.
Optional: Provide custom data exports instead
Use this option if you prefer to manage your own data exports or want to provide additional custom data to Infracost. You can enable Infracost access for specific S3 bucket ARNs. When doing so, please contact support@infracost.io to ensure your use case and configuration are supported.
module "infracost_management_account" {
source = "github.com/infracost/cross-account-link?ref=v0.11.0"
infracost_external_id = "YOUR_EXTERNAL_ID"
is_management_account = true
providers = {
aws = aws.management_account
}
s3_bucket_arns = [
"arn:aws:s3:::my-custom-export" # <-- Add any custom S3 ARNs
]
}
If using this option, please provide the following details to Infracost:
| Field | Example |
|---|---|
| AWS S3 bucket ARN | arn:aws:s3:::my-custom-export |
Data ownership and lifecycle
Your AWS account retains ownership of the data. Infracost is granted solely read-only access to the export buckets.
Each data exports bucket is configured with a 365-day object lifecycle policy. Intelligent tiering is applied to reduce storage costs.
Step 3: Send your details to Infracost
After deploying the module, share the following details with your Infracost product contact or support@infracost.io:
| Field | Example |
|---|---|
| Infracost Organization ID | 00000000-0000-0000-0000-000000000000 |
| AWS management account ID | 111111111111 |
| AWS management account region | us-east-1 |
| AWS management account cross-account-link role ARN | arn:aws:iam::111111111111:role/infracost-readonly |
| AWS member account cross-account-link role ARNs | arn:aws:iam::222222222222:role/infracost-readonly, ... |
The Infracost team will confirm once the integration is active.
Upgrading
As Infracost adds support for additional capabilities there may be a need to upgrade the Terraform module.
Step 1: Update version references
To upgrade, change the version of the module in the ref parameter to the version you'd like to use and make any additional changes needed.
Don't forget to review the release notes for updates and breaking changes.
module "infracost_management_account" {
- source = "github.com/infracost/cross-account-link?ref=v0.9.0"
+ source = "github.com/infracost/cross-account-link?ref=v0.11.0"
+ super_cool_new_feature = true
...
}
Step 2: Download updated module version
Once you've updated the version, rerun terraform init but add the -upgrade flag to force it to check for and download the correct version of the module:
terraform init -upgrade
Step 3: Plan and Apply
Now that you've updated the module version, and made any additional modifications, you can run a plan to verify your work, and apply the changes.
terraform plan
terraform apply
Removing
To remove the Infracost cross-account link components simply run terraform destroy against your project.
Troubleshooting
ValidationException: This account is unable to create an export against this Table
If terraform apply fails with ValidationException: This account is unable to create an export against this Table on the Cost Optimization Hub export, the management account is not yet opted in to Compute Optimizer and Cost Optimization Hub. Run the commands in Enrollment prerequisites above, then re-run terraform apply.
Error: creating AWS BCM Data Exports Export: operation error BCM Data Exports: CreateExport, https response error StatusCode: 400, RequestID: 00000000-0000-0000-0000-000000000000, ValidationException: This account is unable to create an export against this Table.
This error typically happens for one of the following reasons:
- Target is not the management account.
- Make sure you are targetting the management/payer account.
- IAM billing access is not enabled. If this setting is deactivated, IAM users and roles in the account can’t access the Billing and Cost Management console pages, even if they have administrator access or the required IAM policies.
- As the root user, head to the AWS Console and select "Account" from the drop-down in upper-right corner.
- Scroll down to the "IAM user and role access to Billing information" section.
- Select "Edit", and check the box in front of "Activate IAM Access".
- IAM user does not have the correct IAM permissions to create the resources.
- Ensure the user has
cur:PutReportDefinitionandbcm-data-exports:CreateExport
- Ensure the user has