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

# Terraform Setup for the Forecasting Role

> For customers who manage all AWS infrastructure via Terraform: create the Cloud Capital Forecasting role without using the CloudFormation template.

Cloud Capital normally provisions the [Forecasting role](/get-started/aws-data-integration) using a CloudFormation template deployed into your AWS management or payer account. If your organization requires that **all** infrastructure changes go through Terraform, you can create the equivalent IAM role directly — the role's trust policy, permissions, and function are identical to the CloudFormation version.

> [!NOTE]
>
> This page only covers the **Forecasting role** (cost, billing, and usage data access). If you haven't already reviewed how the AWS data integration works, start with [Integrate AWS Data](/get-started/aws-data-integration) first.

***

## What this role does

The Forecasting role is assumed by Cloud Capital's AWS account to read your Cost and Usage Report (CUR), AWS pricing data, and billing/organization metadata, and to check its own permissions. It cannot purchase commitments and cannot create, modify, or delete your AWS infrastructure. Its only non-read actions are two Cost Explorer jobs — a cost allocation tag backfill and a Savings Plans Purchase Analyzer analysis — neither of which makes a purchase. See [What Cloud Capital accesses](/get-started/aws-data-integration#what-cloud-capital-accesses) and [Security and access summary](/get-started/aws-data-integration#security-and-access-summary) for the full breakdown.

***

## Required parameters

Your Terraform configuration needs the following four values:

| Parameter | Value |
| - | - |
| `param_CrossAccountRoleName` | A role name of your choosing, e.g. `CloudCapitalForecastingRole` |
| `param_CloudCapitalAccountRole` | `708317008333` |
| `param_CloudCapitalExternalId` | Your Cloud Capital Integration ID — see below |
| `param_CostAndUsageBucketName` | The S3 bucket name holding your Cost and Usage Report export |

> [!NOTE]
>
> Find your `CloudCapitalExternalId` in the Cloud Capital application at [app.cloudcapital.co/integrations](https://app.cloudcapital.co/integrations) — it's labeled **Integration ID** there. It's a UUID, e.g. `a1b2c3d4-e5f6-7890-abcd-ef1234567890`.

> [!NOTE]
>
> `CostAndUsageBucketName` is the S3 bucket you configured when creating your cost data export — see [Create a cost data export in AWS](/get-started/aws-data-integration#setup) if you haven't set this up yet.

***

## IAM policy JSON

The two policy documents below are extracted directly from Cloud Capital's Forecasting CloudFormation template. Import or reference them as-is in your Terraform configuration — do not modify the actions, effects, or condition keys.

### Trust policy (assume role policy)

This policy allows only Cloud Capital's AWS account to assume the role, and only when the correct External ID is presented.

```json trust-policy.json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "708317008333"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "<param_CloudCapitalExternalId>"
        }
      }
    }
  ]
}
```

Replace `<param_CloudCapitalExternalId>` with your Cloud Capital Integration ID from [app.cloudcapital.co/integrations](https://app.cloudcapital.co/integrations).

### Permissions policy

This policy scopes the role to read-only access over cost, billing, pricing, and organization metadata; your specific CUR bucket; two narrowly-scoped Cost Explorer jobs; currently-unused optimization-recommendation reads; and a self-permission check.

```json permissions-policy.json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CostAndBillingRead",
      "Effect": "Allow",
      "Action": [
        "budgets:Describe*",
        "budgets:View*",
        "ce:Get*",
        "ce:Describe*",
        "ce:List*",
        "ce:StartCostAllocationTagBackfill",
        "cur:Describe*",
        "cur:Get*",
        "cur:Validate*",
        "pricing:DescribeServices",
        "pricing:GetAttributeValues",
        "pricing:GetProducts",
        "organizations:Describe*",
        "organizations:List*",
        "savingsplans:Describe*",
        "billing:Get*",
        "payments:List*",
        "payments:Get*",
        "tax:List*",
        "tax:Get*",
        "consolidatedbilling:Get*",
        "consolidatedbilling:List*",
        "account:GetContactInformation",
        "invoicing:List*",
        "invoicing:Get*",
        "freetier:Get*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "PurchaseAnalyzer",
      "Effect": "Allow",
      "Action": [
        "ce:StartCommitmentPurchaseAnalysis"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AccessCURBucket",
      "Effect": "Allow",
      "Action": [
        "s3:Get*",
        "s3:List*",
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::<param_CostAndUsageBucketName>",
        "arn:aws:s3:::<param_CostAndUsageBucketName>/*"
      ]
    },
    {
      "Sid": "WorkloadOptimizationRecommendations",
      "Effect": "Allow",
      "Action": [
        "compute-optimizer:Get*",
        "compute-optimizer:Describe*",
        "cost-optimization-hub:ListRecommendations",
        "cost-optimization-hub:ListRecommendationSummaries",
        "cost-optimization-hub:GetRecommendation",
        "cost-optimization-hub:GetPreferences",
        "cost-optimization-hub:ListEnrollmentStatuses",
        "trustedadvisor:Describe*",
        "trustedadvisor:List*",
        "trustedadvisor:Get*",
        "support:DescribeTrustedAdvisorChecks",
        "support:DescribeTrustedAdvisorCheckResult",
        "support:DescribeTrustedAdvisorCheckSummaries",
        "support:DescribeTrustedAdvisorCheckRefreshStatuses"
      ],
      "Resource": "*"
    },
    {
      "Sid": "SelfPermissionSimulation",
      "Effect": "Allow",
      "Action": [
        "iam:SimulatePrincipalPolicy"
      ],
      "Resource": "arn:aws:iam::<payer-account-id>:role/<param_CrossAccountRoleName>"
    }
  ]
}
```

Replace both `<param_CostAndUsageBucketName>` placeholders with the S3 bucket name from your cost data export, and `<payer-account-id>` with the ID of the AWS account where you deploy this role. The last statement lets the role check its own permissions and nothing else: Cloud Capital uses it to warn you when a permission is missing, before an action fails.

***

## Example Terraform configuration

The following wires the policy documents above together with the required parameters using standard `aws_iam_role` and `aws_iam_role_policy` resources.

```hcl main.tf theme={null}
variable "cross_account_role_name" {
  description = "The name of the cross account role that Cloud Capital will assume"
  type        = string
  default     = "CloudCapitalForecastingRole"
}

variable "cloud_capital_account_id" {
  description = "The Cloud Capital AWS account that will assume the role"
  type        = string
  default     = "708317008333"
}

variable "cloud_capital_external_id" {
  description = "The Integration ID from app.cloudcapital.co/integrations"
  type        = string
}

variable "cost_and_usage_bucket_name" {
  description = "The S3 bucket name holding your Cost and Usage Report export"
  type        = string
}

resource "aws_iam_role" "cloud_capital_forecasting" {
  name = var.cross_account_role_name

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = ""
        Effect = "Allow"
        Principal = {
          AWS = var.cloud_capital_account_id
        }
        Action = "sts:AssumeRole"
        Condition = {
          StringEquals = {
            "sts:ExternalId" = var.cloud_capital_external_id
          }
        }
      }
    ]
  })
}

resource "aws_iam_role_policy" "cloud_capital_forecasting_policy" {
  name = "CloudCapitalImportPolicy"
  role = aws_iam_role.cloud_capital_forecasting.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "CostAndBillingRead"
        Effect = "Allow"
        Action = [
          "budgets:Describe*",
          "budgets:View*",
          "ce:Get*",
          "ce:Describe*",
          "ce:List*",
          "ce:StartCostAllocationTagBackfill",
          "cur:Describe*",
          "cur:Get*",
          "cur:Validate*",
          "pricing:DescribeServices",
          "pricing:GetAttributeValues",
          "pricing:GetProducts",
          "organizations:Describe*",
          "organizations:List*",
          "savingsplans:Describe*",
          "billing:Get*",
          "payments:List*",
          "payments:Get*",
          "tax:List*",
          "tax:Get*",
          "consolidatedbilling:Get*",
          "consolidatedbilling:List*",
          "account:GetContactInformation",
          "invoicing:List*",
          "invoicing:Get*",
          "freetier:Get*"
        ]
        Resource = "*"
      },
      {
        Sid      = "PurchaseAnalyzer"
        Effect   = "Allow"
        Action   = ["ce:StartCommitmentPurchaseAnalysis"]
        Resource = "*"
      },
      {
        Sid    = "AccessCURBucket"
        Effect = "Allow"
        Action = [
          "s3:Get*",
          "s3:List*",
          "s3:GetBucketLocation"
        ]
        Resource = [
          "arn:aws:s3:::${var.cost_and_usage_bucket_name}",
          "arn:aws:s3:::${var.cost_and_usage_bucket_name}/*"
        ]
      },
      {
        Sid    = "WorkloadOptimizationRecommendations"
        Effect = "Allow"
        Action = [
          "compute-optimizer:Get*",
          "compute-optimizer:Describe*",
          "cost-optimization-hub:ListRecommendations",
          "cost-optimization-hub:ListRecommendationSummaries",
          "cost-optimization-hub:GetRecommendation",
          "cost-optimization-hub:GetPreferences",
          "cost-optimization-hub:ListEnrollmentStatuses",
          "trustedadvisor:Describe*",
          "trustedadvisor:List*",
          "trustedadvisor:Get*",
          "support:DescribeTrustedAdvisorChecks",
          "support:DescribeTrustedAdvisorCheckResult",
          "support:DescribeTrustedAdvisorCheckSummaries",
          "support:DescribeTrustedAdvisorCheckRefreshStatuses"
        ]
        Resource = "*"
      },
      {
        Sid      = "SelfPermissionSimulation"
        Effect   = "Allow"
        Action   = ["iam:SimulatePrincipalPolicy"]
        Resource = aws_iam_role.cloud_capital_forecasting.arn
      }
    ]
  })
}

output "cloud_capital_forecasting_role_arn" {
  description = "Role ARN for Cloud Capital"
  value       = aws_iam_role.cloud_capital_forecasting.arn
}
```

> [!WARNING]
>
> Deploy this into your AWS **management or payer account** — the same account where your Cost and Usage Report export lives. This is a different account from the dedicated commitment account used by the [Optimization role](/optimization/cloud-provider-account-terraform).

***

## Setup

**1. Create your cost data export in AWS**

If you haven't already, follow [Create a cost data export in AWS](/get-started/aws-data-integration#setup) to set up a CUR 2.0 export and note the resulting S3 bucket name.

**2. Get your Cloud Capital External ID**

Sign in to the Cloud Capital application and copy the **Integration ID** from [app.cloudcapital.co/integrations](https://app.cloudcapital.co/integrations). It's a UUID, e.g. `a1b2c3d4-e5f6-7890-abcd-ef1234567890`.

**3. Apply the Terraform configuration**

Add the configuration above to your Terraform codebase, set `cloud_capital_external_id` and `cost_and_usage_bucket_name` to the values from the previous steps, and apply it in your management or payer account.

**4. Share the Role ARN with Cloud Capital**

After apply completes, copy the `cloud_capital_forecasting_role_arn` output and enter it in the Cloud Capital application where prompted for the Forecasting role ARN, then click **Test Role** to verify the connection.

> [!NOTE]
>
> If Cloud Capital will also be managing AWS Savings Plans and Reserved Instances on your behalf, a second, separate role is required. See [Terraform Setup for the Optimization Role](/optimization/cloud-provider-account-terraform).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.