Networking, Identity & Private Connectivity

The Dual-ARN Requirement When Using Inference Profiles in IAM

The most common access-denied surprise with cross-region Claude on Bedrock isn't a missing action — it's a policy that names the inference profile but forgets the foundation model behind it.

Claude 3P 101 · Updated July 2026 · Unofficial guide

On Amazon Bedrock's legacy inference surface, you often don't invoke a model directly — you invoke an inference profile. An inference profile is a Bedrock resource that defines a model plus the AWS regions requests can route to. There are two kinds: system-defined cross-region profiles (which spread traffic across a geography or globally) and user-created application inference profiles (mainly for cost and usage tracking via tags). Either way, the profile is what your code names, and the foundation model is what actually runs.

That two-layer structure is exactly what trips up IAM policies.

Why scoping to the profile ARN alone fails

A security-minded engineer writes a least-privilege policy: allow bedrock:InvokeModel, and set Resource to the inference-profile ARN only. It looks tight. It also doesn't work: AWS documents that when you scope Resource to an inference profile, you must also grant the foundation-model ARN in every region the profile can route to.

Conceptually, the request touches two resources. The caller invokes the profile, and Bedrock then invokes the underlying foundation model in whichever destination region it selects. IAM evaluates access against both, so a policy that authorizes only the first hop is denied at the second. The failure is "silent" in the sense that nothing about the error tells you the fix is a second ARN — you just see an access-denied on an action you clearly allowed.

Two ARN formats are involved, and they differ in an important way:

The working policy shape

AWS's own minimal invoke example grants InvokeModel and InvokeModelWithResponseStream on both resource types:

{
  "Effect": "Allow",
  "Action": [
    "bedrock:InvokeModel",
    "bedrock:InvokeModelWithResponseStream"
  ],
  "Resource": [
    "arn:aws:bedrock:*::foundation-model/*",
    "arn:aws:bedrock:us-east-1:111122223333:inference-profile/*"
  ]
}

To tighten it, replace the wildcards: name the specific model ID in the foundation-model ARN, and list the destination regions the profile routes to instead of * in the region segment. The rule of thumb: every region the profile can route to needs a matching foundation-model grant. If you use a geographic US profile, that means the US destination regions; a global profile widens it further. (Provisioned models are a third, separate resource type — arn:aws:bedrock:{region}:{account}:provisioned-model/{name} — if you use provisioned throughput.)

Locking callers to the profile with a condition key

The dual grant raises a fair objection: "if I must allow the foundation-model ARN broadly, what stops someone from bypassing my profile and invoking the model directly — skipping my cost-tracking tags?" AWS provides the bedrock:InferenceProfileArn condition key for exactly this. Attach it to the foundation-model statement so the model grant is only usable when the request came through the approved profile:

"Condition": {
  "ArnEquals": {
    "bedrock:InferenceProfileArn":
      "arn:aws:bedrock:us-east-1:111122223333:inference-profile/my-profile"
  }
}

With this in place, a direct InvokeModel against the bare model ARN fails (no profile in the request context, so the condition doesn't match), while invocations routed through your named profile succeed. That preserves whatever governance the profile carries — tagging, cost attribution, region scoping.

Rule of thumb: profile-based invocation always needs two grants — profile ARN plus foundation-model ARN for every destination region — and the bedrock:InferenceProfileArn condition key is how you keep the second grant from becoming a bypass.

Where this fits in the bigger picture

This is an identity-policy concern, but the same routing model has an organization-policy twin: service control policies must allow every destination region too, or requests fail at a different layer. That trap — including the special aws:RequestedRegion = "unspecified" value used by global profiles — is covered in the SCP and cross-region inference article. And to verify where routed requests actually ran, see auditing cross-region inference in CloudTrail.

Note that all of this applies to the legacy bedrock-runtime surface and its bedrock:* action namespace. The newer Messages-API surface uses a different action (bedrock-mantle:CreateInference) and selects global versus regional routing differently — see the bedrock-mantle article for that surface.

Where to go next

Start from Bedrock IAM setup if you're building policies from scratch, and the least-privilege guide for cross-platform principles.

Sources