Skip to main content

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.

note

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.

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.

note

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:

note

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:

FieldExample
AWS S3 bucket ARNarn: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:

FieldExample
Infracost Organization ID00000000-0000-0000-0000-000000000000
AWS management account ID111111111111
AWS management account regionus-east-1
AWS management account cross-account-link role ARNarn:aws:iam::111111111111:role/infracost-readonly
AWS member account cross-account-link role ARNsarn: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.

tip

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:PutReportDefinition and bcm-data-exports:CreateExport