Least-Privilege IAM for Bedrock
Identity Boundaries First
Use dedicated IAM roles for Bedrock callers and grant only the actions and model resources required. A leaked credential with bedrock:* on * can silently run up enormous token bills or exfiltrate data through model calls - least privilege is your first cost control and your first security control.
A Production-Shaped Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InvokeApprovedModelsOnly",
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": [
"arn:aws:bedrock:us-east-1::foundation-model/amazon.nova-lite-v1:0",
"arn:aws:bedrock:us-east-1::foundation-model/amazon.nova-pro-v1:0"
]
}
]
}
Note what this policy does not include: no bedrock:CreateGuardrail, no customization jobs, no ListFoundationModels. The application role invokes exactly two pinned models and nothing else. Platform/admin roles get the control-plane actions separately.
Common IAM Mistakes with Bedrock
| Mistake | Risk | Fix |
|---|---|---|
"Resource": "*" on invoke actions | Any newly enabled model becomes instantly callable | Pin foundation-model ARNs per environment |
| One shared role for app + admin | App compromise grants policy/config mutation | Separate runtime and management roles |
| Long-lived access keys in code | Key leakage = unlimited token spend | Use role assumption (IRSA, instance profiles, Lambda execution roles) |
| No CloudTrail review for bedrock events | Silent misuse goes unnoticed | Alert on anomalous InvokeModel volume and denied calls |
Defense in Depth
Combine IAM with application-side allowlists so business logic cannot invoke unapproved models even if policy broadens later. IAM answers "what is this principal allowed to call?"; your config answers "what has this product approved?". Both should agree, and either alone should be enough to block a mistake.
bedrock:InvokeModel on any model ARN outside your approved catalogue. Individual account admins then cannot accidentally widen access.