> ## Documentation Index
> Fetch the complete documentation index at: https://docs.costory.io/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS Billing Setup

> Connect AWS CUR 2.0 billing data to Costory via CloudFormation, manual setup, or Terraform.

<Tabs>
  <Tab title="Manual setup">
    Open Costory and go to **Billing > Import new billing datasource > AWS**. The stepper guides you through each field. The steps below explain how to prepare your AWS account.

    You can use CloudFormation or set things up manually. Both paths produce the same result: an S3 bucket with <Tooltip tip="AWS's detailed billing export, the raw data source for AWS cost analysis." cta="See Glossary" href="/docs/glossary#cur">CUR 2.0</Tooltip> data and an IAM role that Costory can assume.

    **Option A: CloudFormation (recommended)**

    1. Open the [CloudFormation template](https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/create/review?templateURL=https://costory-public-templates.s3.us-east-1.amazonaws.com/create_cur2_and_assign_iam_rights_v2.yaml) in **us-east-1**.
    2. Deploy the stack and note the **Bucket Name**, **Role ARN**, and **Prefix** from the stack outputs.

    **Option B: Manual**

    1. Create a CUR 2.0 data export in the AWS Billing console (Parquet format, overwrite enabled). Use hourly granularity if you run EKS or ECS. Enable all checkboxes under Additional Content (Include ID resources, Include Split cost allocation data, etc...).
    2. Create an S3 read-only IAM policy scoped to the export bucket.
    3. Create a web identity IAM role trusted by Costory's GCP service account.

    **Connect in Costory**

    1. Go to **Billing > Import new billing datasource > AWS**.
    2. Enter the **S3 bucket name**, **Role ARN**, and **Prefix**.
    3. If you run EKS or ECS, enable **<Tooltip tip="An AWS feature that breaks down container costs (EKS, ECS) to individual pod labels." cta="See Glossary" href="/docs/glossary#split-cost-allocation">Split cost allocation data</Tooltip>** and activate the relevant cost allocation tags (`aws:eks:*`, `aws:ecs:*`). This gives you pod-level (EKS) and job-level (ECS) cost granularity. See [Kubernetes cost visibility](/use-cases/k8s_waste/visibility) for details.

    <Tip>
      **Cost allocation tags:** Activate as many cost allocation tags as you can in the AWS Billing console. Costory [Dimensions](/features/tagging/dimensions) automatically detect and merge meaningful tags so you can filter by team, environment, project, etc.
    </Tip>

    <Note>
      The first AWS export can take up to **12 hours**. Costory sends you an email when data is received. Backfill covers up to **12 months** via `aws:createdBy` tag backfill. For longer periods, open an AWS Support request.
    </Note>

    <Frame caption="Successful datasource import in Costory.">
      <img src="https://mintcdn.com/costory/szA7rIpq2yYQC3Qx/images/success_import.png?fit=max&auto=format&n=szA7rIpq2yYQC3Qx&q=85&s=30f41a37a9181cbdb07f39b2494c387e" alt="Costory datasource successfully connected" width="1898" height="1041" data-path="images/success_import.png" />
    </Frame>
  </Tab>

  <Tab title="Terraform">
    <Accordion title="Full Terraform configuration">
      ```hcl theme={null}
      terraform {
        required_providers {
          aws = {
            source  = "hashicorp/aws"
            version = ">= 5.0"
          }
          costory = {
            source  = "costory-io/costory"
            version = ">= 0.1.0"
          }
        }
      }
      variable "s3_name" {
        type        = string
        description = "Base name for the CUR bucket."
        default     = "billing-data-exports"
      }

      variable "s3_prefix" {
        type        = string
        description = "The S3 prefix for the CUR exports."
        default     = "costory-cur"
      }

      variable "aws_region" {
        type        = string
        description = "AWS region used by this Terraform stack."
        default     = "us-east-1"
      }

      variable "costory_api_token" {
        type        = string
        description = "Costory API token."
        sensitive   = true
      }

      provider "costory" {
        token = var.costory_api_token
      }

      provider "aws" {
        region = var.aws_region
      }

      data "aws_caller_identity" "current" {}
      data "aws_partition" "current" {}
      data "costory_service_account" "current" {}


      locals {
        account_id = data.aws_caller_identity.current.account_id

        cur_bucket_name = "${var.s3_name}-${local.account_id}"
        cur_export_name = "${var.s3_name}-costory-data-exports"
        # Issue with AWS provider see https://github.com/hashicorp/terraform-provider-aws/issues/43978
        cur_definition_source_arn = "arn:${data.aws_partition.current.partition}:cur:us-east-1:${local.account_id}:definition/*"
        bcm_export_source_arn     = "arn:${data.aws_partition.current.partition}:bcm-data-exports:us-east-1:${local.account_id}:export/*"

        cur_table_configurations = {
          COST_AND_USAGE_REPORT = {
            INCLUDE_RESOURCES                     = "TRUE"
            INCLUDE_SPLIT_COST_ALLOCATION_DATA    = "TRUE"
            TIME_GRANULARITY                      = "HOURLY"
            INCLUDE_MANUAL_DISCOUNT_COMPATIBILITY = "FALSE"
            INCLUDE_CAPACITY_RESERVATION_DATA     = "TRUE"
            BILLING_VIEW_ARN                      = "arn:${data.aws_partition.current.partition}:billing::${data.aws_caller_identity.current.account_id}:billingview/primary"
            INCLUDE_IAM_PRINCIPAL_DATA            = "TRUE"
          }
        }
        // SQL Query to get all columns
        cur_query_statement = <<-EOT
      SELECT bill_bill_type, bill_billing_entity, bill_billing_period_end_date, bill_billing_period_start_date, bill_invoice_id, bill_invoicing_entity, bill_payer_account_id, bill_payer_account_name, capacity_reservation_capacity_reservation_arn, capacity_reservation_capacity_reservation_status, capacity_reservation_capacity_reservation_type, cost_category, discount, discount_bundled_discount, discount_total_discount, identity_line_item_id, identity_time_interval, line_item_availability_zone, line_item_blended_cost, line_item_blended_rate, line_item_currency_code, line_item_iam_principal, line_item_legal_entity, line_item_line_item_description, line_item_line_item_type, line_item_net_unblended_cost, line_item_net_unblended_rate, line_item_normalization_factor, line_item_normalized_usage_amount, line_item_operation, line_item_product_code, line_item_resource_id, line_item_tax_type, line_item_unblended_cost, line_item_unblended_rate, line_item_usage_account_id, line_item_usage_account_name, line_item_usage_amount, line_item_usage_end_date, line_item_usage_start_date, line_item_usage_type, line_item_user_identifier, pricing_currency, pricing_lease_contract_length, pricing_offering_class, pricing_public_on_demand_cost, pricing_public_on_demand_rate, pricing_purchase_option, pricing_rate_code, pricing_rate_id, pricing_term, pricing_unit, product, product_comment, product_fee_code, product_fee_description, product_from_location, product_from_location_type, product_from_region_code, product_instance_family, product_instance_type, product_instancesku, product_location, product_location_type, product_operation, product_pricing_unit, product_product_family, product_region_code, product_servicecode, product_sku, product_to_location, product_to_location_type, product_to_region_code, product_usagetype, reservation_amortized_upfront_cost_for_usage, reservation_amortized_upfront_fee_for_billing_period, reservation_availability_zone, reservation_effective_cost, reservation_end_time, reservation_modification_status, reservation_net_amortized_upfront_cost_for_usage, reservation_net_amortized_upfront_fee_for_billing_period, reservation_net_effective_cost, reservation_net_recurring_fee_for_usage, reservation_net_unused_amortized_upfront_fee_for_billing_period, reservation_net_unused_recurring_fee, reservation_net_upfront_value, reservation_normalized_units_per_reservation, reservation_number_of_reservations, reservation_recurring_fee_for_usage, reservation_reservation_a_r_n, reservation_start_time, reservation_subscription_id, reservation_total_reserved_normalized_units, reservation_total_reserved_units, reservation_units_per_reservation, reservation_unused_amortized_upfront_fee_for_billing_period, reservation_unused_normalized_unit_quantity, reservation_unused_quantity, reservation_unused_recurring_fee, reservation_upfront_value, resource_tags, savings_plan_amortized_upfront_commitment_for_billing_period, savings_plan_end_time, savings_plan_instance_type_family, savings_plan_net_amortized_upfront_commitment_for_billing_period, savings_plan_net_recurring_commitment_for_billing_period, savings_plan_net_savings_plan_effective_cost, savings_plan_offering_type, savings_plan_payment_option, savings_plan_purchase_term, savings_plan_recurring_commitment_for_billing_period, savings_plan_region, savings_plan_savings_plan_a_r_n, savings_plan_savings_plan_effective_cost, savings_plan_savings_plan_rate, savings_plan_start_time, savings_plan_total_commitment_to_date, savings_plan_used_commitment, split_line_item_actual_usage, split_line_item_net_split_cost, split_line_item_net_unused_cost, split_line_item_parent_resource_id, split_line_item_public_on_demand_split_cost, split_line_item_public_on_demand_unused_cost, split_line_item_reserved_usage, split_line_item_split_cost, split_line_item_split_usage, split_line_item_split_usage_ratio, split_line_item_unused_cost, tags FROM COST_AND_USAGE_REPORT
      EOT
      }
      # Creates AWS Billing Data Export:

      resource "aws_s3_bucket" "s3_client_bucket" {
        bucket = local.cur_bucket_name
      }

      resource "aws_s3_bucket_public_access_block" "s3_client_bucket" {
        bucket = aws_s3_bucket.s3_client_bucket.id

        ignore_public_acls      = true
        restrict_public_buckets = true
      }

      data "aws_iam_policy_document" "s3_client_bucket_access_policy" {
        statement {
          effect = "Allow"
          principals {
            type = "Service"
            identifiers = [
              "billingreports.amazonaws.com",
              "bcm-data-exports.amazonaws.com",
            ]
          }
          actions = [
            "s3:PutObject",
            "s3:GetBucketPolicy",
          ]
          resources = [
            aws_s3_bucket.s3_client_bucket.arn,
            "${aws_s3_bucket.s3_client_bucket.arn}/*",
          ]
          condition {
            test     = "StringLike"
            variable = "aws:SourceArn"
            values = [
              local.cur_definition_source_arn,
              local.bcm_export_source_arn,
            ]
          }
          condition {
            test     = "StringLike"
            variable = "aws:SourceAccount"
            values   = [local.account_id]
          }
        }
      }

      resource "aws_s3_bucket_policy" "s3_client_bucket_access_policy" {
        bucket = aws_s3_bucket.s3_client_bucket.id
        policy = data.aws_iam_policy_document.s3_client_bucket_access_policy.json
      }

      resource "aws_bcmdataexports_export" "cur_report_definition" {
        depends_on = [aws_s3_bucket_policy.s3_client_bucket_access_policy]
        export {
          name = local.cur_export_name
          data_query {
            query_statement      = local.cur_query_statement
            table_configurations = local.cur_table_configurations
          }
          destination_configurations {
            s3_destination {
              s3_bucket = aws_s3_bucket.s3_client_bucket.bucket
              s3_region = var.aws_region
              s3_prefix = var.s3_prefix

              s3_output_configurations {
                compression = "PARQUET"
                format      = "PARQUET"
                output_type = "CUSTOM"
                overwrite   = "OVERWRITE_REPORT"
              }
            }
          }
          refresh_cadence {
            frequency = "SYNCHRONOUS"
          }
        }
      }
      # Give Costory permission to read the S3 bucket:

      data "aws_iam_policy_document" "costory_read_s3_policy" {
        statement {
          sid    = "Statement1"
          effect = "Allow"
          actions = [
            "s3:ListBucket",
            "s3:GetObject",
          ]
          resources = [
            aws_s3_bucket.s3_client_bucket.arn,
            "${aws_s3_bucket.s3_client_bucket.arn}/*",
          ]
        }
      }
      resource "aws_iam_policy" "costory_read_s3_policy" {
        name        = "Costory-read-s3-${var.s3_name}"
        description = "Allows Costory to read the CUR S3 bucket."
        policy      = data.aws_iam_policy_document.costory_read_s3_policy.json
      }
      # Costory is hosted on GCP we rely on a federated role on your organization service account to access the AWS billing data export.
      data "aws_iam_policy_document" "costory_federated_role_assume" {
        statement {
          effect = "Allow"
          actions = [
            "sts:AssumeRoleWithWebIdentity",
          ]
          principals {
            type        = "Federated"
            identifiers = ["accounts.google.com"]
          }
          condition {
            test     = "StringEquals"
            variable = "accounts.google.com:sub"
            values   = data.costory_service_account.current.sub_ids
          }
        }
      }
      resource "aws_iam_role" "costory_federated_role" {
        name               = "costory-trust-link-${var.s3_name}"
        assume_role_policy = data.aws_iam_policy_document.costory_federated_role_assume.json
      }
      resource "aws_iam_role_policy_attachment" "costory_read_s3_policy_attachment" {
        role       = aws_iam_role.costory_federated_role.name
        policy_arn = aws_iam_policy.costory_read_s3_policy.arn
      }
      # Create the Costory AWS billing datasource in Costory:
      resource "costory_billing_datasource_aws" "main" {
        name                   = "AWS CUR ${var.s3_name}"
        bucket_name            = aws_s3_bucket.s3_client_bucket.bucket
        role_arn               = aws_iam_role.costory_federated_role.arn
        prefix                 = var.s3_prefix
        eks_split_data_enabled = true
        depends_on             = [aws_bcmdataexports_export.cur_report_definition]
      }
      ```
    </Accordion>
  </Tab>
</Tabs>
