# AWS IAM policies for the Bedrock embedding benchmark Two policies, deliberately separate, because they have different lifetimes. | File | Purpose | Lifetime | |---|---|---| | `bedrock-embedding-invoke.json` | List, describe and invoke **only** `amazon.titan-embed-text-v2:0` and `cohere.embed-v4:0` in `us-east-1` | Attached for as long as the benchmark and the embedding job need to run | | `bedrock-model-access-bootstrap.json` | Turn on model access, including the AWS Marketplace subscription a third-party model needs before its first call | One-time. Attach, enable access, **detach** | Splitting them matters: `aws-marketplace:Subscribe` is the right to commit the account to a paid offer. That is not a permission an embedding batch job should carry around after the one moment it was needed. ## Measured starting state (2026-08-03) ``` aws sts get-caller-identity -> arn:aws:iam:::user/ai-lab-user aws iam list-attached-user-policies -> [] aws iam list-user-policies -> [] aws iam list-groups-for-user -> AI-Lab-Group aws iam list-attached-group-policies -> AmazonEC2FullAccess, IAMFullAccess, ElasticLoadBalancingFullAccess, AmazonVPCFullAccess aws iam list-group-policies -> [] ``` `ai-lab-user` holds no `bedrock:*` permission from any source, which is the whole of the failure. Both of these were observed, not inferred: ``` aws bedrock list-foundation-models --region us-east-1 AccessDeniedException ... not authorized to perform: bedrock:ListFoundationModels aws bedrock-runtime invoke-model --model-id amazon.titan-embed-text-v2:0 ... AccessDeniedException ... not authorized to perform: bedrock:InvokeModel ``` ## Applying them ```bash aws iam create-policy \ --policy-name BedrockEmbeddingInvoke \ --policy-document file://infra/aws/iam/bedrock-embedding-invoke.json aws iam attach-group-policy \ --group-name AI-Lab-Group \ --policy-arn arn:aws:iam:::policy/BedrockEmbeddingInvoke ``` Same two commands for the bootstrap policy, then `aws iam detach-group-policy` once model access shows as granted. ## What is documented vs. what is confirmed Confirmed by running the commands above: the current permission state, and that both `ListFoundationModels` and `InvokeModel` are denied. Taken from AWS documentation and **not yet confirmed against this account**: - that the action list in each policy is sufficient — no live call has succeeded yet, so "sufficient" is unproven either way; - that `cohere.embed-v4:0` needs a Marketplace subscription in this account. It is a third-party model, so the bootstrap policy provides for it; - the foundation-model ARN form `arn:aws:bedrock:us-east-1::foundation-model/` (no account number) — this is the form AWS's own denial message returned, so it is corroborated; - whether the account has an SCP or permissions boundary that would still deny Bedrock after these policies are attached. Nothing here can rule that out from inside the account. Region is pinned to `us-east-1` to match the configured region. Widening to `arn:aws:bedrock:*::foundation-model/...` is a one-line change if the benchmark moves region, but it should be a deliberate one.