Onboarding: AWS¶
This guide wires your AWS environment into Venturi. It assumes one AWS account and one customer-side workload identity (GitHub Actions OIDC, EKS IRSA, or similar) that will assume the role.
Time required
~15 minutes of click-and-paste, plus a single terraform apply.
What this grants Venturi¶
A cross-account IAM role that Venturi assumes from its own production account, restricted to read-only APIs:
- Cost & billing — Cost Explorer (
ce:Get*), Cost & Usage Report S3 bucket (s3:GetObject/s3:ListBucketon the CUR bucket only), pricing catalog (pricing:*). - Bedrock (optional, default on) — foundation/custom model metadata, invocation-logging configuration, inference profiles, provisioned-throughput inventory.
- CloudWatch & CloudTrail — metrics, log events, and Bedrock API call history for the period under analysis.
- Identity inventory — IAM roles/users listing (no policy mutation) and Organizations hierarchy read.
It does not grant write access to any AWS API. check_permissions.py in the
platform repo enforces this at gate time; the role's policy is verifiable in
infra/aws/onboarding/main.tf.
Step 1 — Get the values Venturi will provide¶
Email [email protected] and ask for:
venturi_account_id— the AWS account ID Venturi assumes from.external_id— a per-customer string for thests:ExternalIdcondition. Treat as moderately sensitive (a confused-deputy mitigation, not a full secret).
You will provide back to Venturi:
- The
role_arnoutput fromterraform apply. - The S3 bucket where your Cost & Usage Reports are delivered (
cur_bucket_name). - (Optional) the
cur_report_prefix, if your CUR uses a non-default prefix.
Step 2 — Configure your terraform.tfvars¶
Create terraform.tfvars in infra/aws/onboarding/ (or wherever you've vendored
the module):
aws_region = "us-east-1" # the region your CUR bucket lives in
venturi_account_id = "<from Venturi>"
external_id = "<from Venturi>"
cur_bucket_name = "my-org-cur-bucket"
cur_report_prefix = "cur/" # optional, default depends on your CUR config
enable_bedrock_access = true # default true; flip to false if not using Bedrock
A complete terraform.tfvars.example ships in the module directory.
Step 3 — Apply¶
cd infra/aws/onboarding
terraform init
terraform plan # confirm the role + policies that will be created
terraform apply
terraform apply prints two outputs:
role_arn— paste this into your reply to Venturi.granted_permissions— a human-readable summary of what was granted; keep for audit.
Step 4 — Verify¶
You don't have to take Venturi's word that access is read-only. From inside your AWS account:
The script assumes the role under the same trust policy Venturi uses, then
exercises one Get/List call per granted service. Pass = each call returns
success or a 4xx that's clearly an access-scoped not-found (not 403). Any 403
means a permission gap; any 200 on a write API is a security finding and the
script exits non-zero.
Step 5 — Hand the role ARN to Venturi¶
Reply to your onboarding email with:
role_arn: <terraform output>
cur_bucket: <bucket name>
cur_prefix: <prefix> (if non-default)
region(s): us-east-1, ... (any region where you want Bedrock or CW Logs inventoried)
notes: <anything Venturi should know about your account layout>
Venturi responds within 1 business day confirming the role is reachable and that ingestion has started.
Rotating the external_id¶
Recommended every 12 months:
- Ask Venturi for a new
external_id. - Update
terraform.tfvarsandterraform apply. - Confirm Venturi can still assume the new role before destroying the old trust.
Removing access¶
This deletes the IAM role and its policies; Venturi loses visibility within ~5 minutes. Notify Venturi first so attribution ingestion can pause cleanly.
Troubleshooting¶
| Symptom | Most likely cause |
|---|---|
| Venturi reports "AccessDenied" assuming the role | external_id mismatch — confirm with your onboarding contact. |
| Venturi reports CUR data is missing | CUR bucket name or prefix doesn't match terraform.tfvars. |
| Venturi reports Bedrock data is missing | enable_bedrock_access = false, or Bedrock invocation logging isn't enabled. See AWS docs. |
terraform apply fails on iam:CreateRole |
The caller lacks IAM admin. Run as a user with IAMFullAccess or equivalent. |
Reference¶
- Module source:
infra/aws/onboarding/ - Verify script:
infra/aws/onboarding/scripts/verify.sh - Trust & security model
- Security policy: https://github.com/argmin-com/.github/blob/main/SECURITY.md