One of Bedrock's biggest operational advantages over a standalone AI vendor is that authentication disappears into AWS's existing machinery. A Lambda function, an ECS task, or an EC2 instance each carries an IAM role, and the Anthropic SDK resolves credentials through the standard AWS chain — constructor arguments, then environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_REGION), then the config file and credential providers including SSO, assumed roles, the ECS task role, and the EC2 instance metadata service. In practice: attach a role to the compute, write no credential code at all.
The role per compute type
The pattern is the same everywhere; only the attachment point differs. For Lambda, add Bedrock permissions to the function's execution role. For ECS/Fargate, put them on the task role (the identity your application code uses) — not the task execution role, which is what the ECS agent uses to pull images and write logs. For EC2, attach an instance profile wrapping the role; the SDK picks it up from instance metadata. In all three cases, this Python runs unchanged:
from anthropic import AnthropicBedrockMantle
# No keys anywhere: credentials come from the attached role.
client = AnthropicBedrockMantle(aws_region="us-east-1")
msg = client.messages.create(
model="anthropic.claude-sonnet-5",
max_tokens=512,
messages=[{"role": "user", "content": "Summarize this ticket..."}],
)
A least-privilege inference policy
Avoid attaching AmazonBedrockFullAccess to production workloads — it exists, alongside AmazonBedrockReadOnly, but grants far more than inference. A workload that only calls Claude needs the invocation actions, scoped to the models it uses:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": [
"arn:aws:bedrock:*::foundation-model/anthropic.claude-sonnet-5",
"arn:aws:bedrock:us-east-1:111122223333:inference-profile/*"
]
}]
}
Three notes on that policy. First, if the workload uses the Converse API on the legacy surface, bedrock:Converse and bedrock:ConverseStream exist as actions too — though AWS documents that Converse is blocked automatically when InvokeModel is denied, allow statements should name what the code actually calls. Second, the inference-profile ARN line matters: invoking through a cross-region inference profile requires permissions on both the foundation-model and inference-profile resources. Third, if the workload uses the newer "Claude in Amazon Bedrock" surface, note that the bedrock-mantle endpoint uses a distinct action namespace — bedrock-mantle:CreateInference — so a policy written only with bedrock:* actions won't cover it. Grant that action on the allowed model ARNs for roles using AnthropicBedrockMantle.
The provisioned service-role pattern
For the current Claude in Amazon Bedrock surface, Anthropic documents a recommended variant for human and CI access: an administrator provisions a Bedrock service role with the inference permissions, and grants developers iam:PassRole on that role rather than direct invocation rights. This centralizes what the role may do while letting many principals use it. Federated alternatives (SAML/OIDC/Identity Center assumed roles, 12-hour maximum session) and short-lived bearer tokens exist for the same surface, with bearer tokens explicitly the least-preferred option — compute workloads should stay on attached roles.
Rotation is another quiet benefit of this pattern. Roles issue temporary credentials that AWS refreshes automatically, so there is no long-lived Claude secret to store, leak, or rotate on a schedule — a meaningful reduction in operational risk compared with API-key-based access to a standalone vendor, and one reason security teams tend to approve Bedrock-based Claude deployments quickly.
Hardening around the role
Two complements finish the design. Network: if the compute runs in a VPC without internet egress, add interface VPC endpoints (com.amazonaws.{region}.bedrock-runtime or com.amazonaws.{region}.bedrock-mantle) so Claude traffic stays on AWS PrivateLink — details in PrivateLink setup. Audit: CloudTrail logs InvokeModel and Converse calls as management events by default, including the calling role's identity, so per-role usage is traceable without extra setup.
Where to go next
Restrict roles further with Bedrock IAM condition keys, or centralize inference across accounts with cross-account role assumption. General principles live in least-privilege IAM for Claude.