FinOpsAI reads a FOCUS 1.2 Data Export from an S3 bucket in your account through an IAM role you create and control. No access keys are created, exchanged or stored. This page is written for the administrator of your AWS management (payer) account — it can be forwarded as-is.
AWS Data Exports writes a FOCUS 1.2 file set to an S3 bucket in your account every day. FinOpsAI's ingestion identity — a Google Cloud service account — presents a Google-signed token to AWS STS and assumes an IAM role in your account (AssumeRoleWithWebIdentity). The role's trust policy accepts only that one identity, and its permission policy allows only reading the export bucket plus five read-only commitment-inventory calls. You can revoke everything by deleting the role.
| FinOpsAI identity to trust | Your workspace's own Google service account, identified by its numeric unique ID (pinned as both accounts.google.com:sub and :aud). The wizard shows it and writes it into the CloudFormation template it generates — one identity per FinOpsAI workspace, so no other workspace can ever assume your role. |
|---|---|
| Federated principal | accounts.google.com — AWS's built-in Google provider. Do not create an IAM OIDC identity provider for accounts.google.com; doing so shadows the built-in handling and breaks token validation. |
| Permissions | s3:GetObject, s3:ListBucket, s3:GetBucketLocation on the export bucket; savingsplans:DescribeSavingsPlans, ec2:DescribeReservedInstances, ce:GetSavingsPlansUtilization, ce:GetSavingsPlansUtilizationDetails, ce:GetReservationUtilization |
| What FinOpsAI never asks for | IAM users, access keys, secret keys, AdministratorAccess or any write permission |
| Data residency | Create the bucket in ap-south-1 (Mumbai) if billing data must stay in India. FinOpsAI reports the bucket region and flags buckets outside India. |
Billing exports can only be created in the management (payer) account. If your organisation uses AWS Organizations, a Data Export created there covers every member account. If you are not the management-account administrator, forward this page to whoever is.
bcm-data-exports:*, cur:*), S3 bucket creation, and IAM role creation in the management account.acme-focus-billing-export.Fast path (one stack). On step 2 the wizard's default is One stack does it all: enter the 12-digit management account ID, click Create stack in AWS, tick the IAM acknowledgement, click Create stack. One CloudFormation stack (FinOpsAI-Connect, in us-east-1 — the only region where AWS offers the Data Exports resource) creates a private bucket finopsai-focus-<account id>, the FOCUS 1.2 export into it (Parquet, daily, overwrite) and the read-only role FinOpsAIReader whose trust policy names your workspace identity. The template is one published file, identical for every customer; your workspace identity travels as a stack parameter. Steps 1, 2 and 5 below are what the stack does for you. The bucket is in us-east-1, where AWS keeps your bill; if your policy needs the export source in India, use the manual steps with a bucket in ap-south-1.
Asia Pacific (Mumbai) ap-south-1. Name e.g. acme-focus-billing-export. Keep Block all public access on. Default encryption (SSE-S3) is fine. Create.focus. Data table FOCUS 1.2 with AWS columns. Compression/format Parquet. File versioning Overwrite existing data export file. Under Data export storage settings choose the bucket from Step 1 and S3 path prefix focus. Create.
The console offers to apply the bucket policy that lets the export service (bcm-data-exports.amazonaws.com and billingreports.amazonaws.com) write to the bucket — accept it. Without that policy the export is created but never delivers. The first file set arrives within 24 hours and is refreshed up to three times a day thereafter; earlier months are not back-filled.
focus. The wizard derives the role ARN from the account ID and the default role name FinOpsAIReader.FinOpsAIReader with a trust policy pinned to your workspace identity and a read-only policy limited to your bucket (plus the optional commitments describe/get calls). Click the CloudFormation link → Create stack → Upload a template file → the file you downloaded → Next → stack name finopsai-reader → Next → tick I acknowledge that AWS CloudFormation might create IAM resources with custom names → Submit. About a minute. The wizard watches and turns green when the role can be assumed.
Prefer to create the role by hand? The same step shows the trust policy and the permission policy to paste (IAM → Roles → Create role → Custom trust policy); the values are identical to what the template creates.
For review by your security team. The CloudFormation template from Step 5 creates exactly these two documents; if you create the role by hand, paste them from the wizard, which fills in your workspace identity.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Federated": "accounts.google.com" },
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"accounts.google.com:sub": "<your workspace identity's unique ID — shown in the wizard>",
"accounts.google.com:aud": "<the same value>"
}
}
}]
}
Both conditions pin the same value — the numeric unique ID of your workspace's FinOpsAI service account. No other Google identity, and no other FinOpsAI workspace, can assume the role.
YOUR-BUCKET-NAME is your bucket from Step 1{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "FinOpsAIReadFocusExport",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket", "s3:GetBucketLocation"],
"Resource": [
"arn:aws:s3:::YOUR-BUCKET-NAME",
"arn:aws:s3:::YOUR-BUCKET-NAME/*"
]
},
{
"Sid": "FinOpsAICommitmentInventoryReadOnly",
"Effect": "Allow",
"Action": [
"savingsplans:DescribeSavingsPlans",
"ec2:DescribeReservedInstances",
"ce:GetSavingsPlansUtilization",
"ce:GetSavingsPlansUtilizationDetails",
"ce:GetReservationUtilization"
],
"Resource": "*"
}
]
}
The second statement is optional. It lets FinOpsAI list your Savings Plans and Reserved Instances and read their utilisation for the Commitments view; these are account-wide describe/get calls that do not support resource-level ARNs, hence "Resource": "*". Omit it and billing analysis still works — the Commitments inventory shows "access not granted".
| Field | Where to find it | Example |
|---|---|---|
| Export bucket | S3 → bucket name (no s3://, no path) | acme-focus-billing-export |
| Prefix | Data Exports → your export → S3 path prefix | focus |
| Payer account ID | Account menu → Account → Account ID | 123456789012 |
| Role name (optional) | Only if you renamed the role in the template or by hand | FinOpsAIReader |
| Check | Pass | Fail — likely cause and fix |
|---|---|---|
| Assume the FinOpsAI role | STS accepted the Google token and issued role credentials. | Trust policy does not match: sub and aud must both equal your workspace identity's unique ID as shown in the wizard (redeploying the template fixes it); the principal must be accounts.google.com; no custom OIDC provider for Google may exist. Also check the Role ARN is typed exactly. |
| Bucket region | Region read via GetBucketLocation; shown with a residency flag. | Permission policy lacks s3:GetBucketLocation, or the bucket name is wrong. "Outside India" is a warning, not a failure. |
| Export bucket listed | ListObjects under the prefix succeeded. | Missing s3:ListBucket on the bucket ARN (the one without /*), or the prefix differs from the export's S3 path prefix. |
| Find the FOCUS export | An export folder was found under the prefix. | The export was created with a different prefix or into a different bucket; compare with Data Exports → export details. |
| Verify the FOCUS manifest | A FOCUS 1.2 manifest was read for the latest billing period. | "No export delivered yet — expected within 24h" is normal right after creation and does not block Finish. If it persists past 24 h, the export bucket policy was not applied (Step 2 note) — open the export in Data Exports and check its status. |
Delete the finopsai-reader CloudFormation stack, or the FinOpsAIReader role if you created it by hand. Access stops at the next token exchange — within the hour. The export and bucket are yours; disable the export in Data Exports if you no longer need it. Use Disconnect in FinOpsAI to remove the ingested rows and the connection record from FinOpsAI's side.
FinOpsAI reads the FOCUS 1.2 table only. Create a FOCUS export alongside your existing CUR; both can deliver to the same bucket under different prefixes.
"Resource": "*"Omit the second statement. Everything derived from billing works; only the live Savings Plan / RI inventory is unavailable.
The role must be in the account that owns the export bucket — normally the management account, because only it can create the export. If the bucket lives in a member account (cross-account delivery), create the role there and enter that account's role ARN; the payer account ID stays the management account's.
Check the S3 path: Data Exports writes to <prefix>/<export-name>/…. The prefix you enter in FinOpsAI is the S3 path prefix, not the export name.
finops@samsofttechnologies.com — include the check that failed and its detail text.