Claude Platform on AWS in Practice

Using EC2 Instance Roles with Claude Platform on AWS

The simplest production credential story on this platform: attach a role to the instance and deploy code with no keys in it at all.

Claude 3P 101 · Updated July 2026 · Unofficial guide

If your application runs on EC2, you never need to put an AWS access key anywhere. Attach an IAM role to the instance (via an instance profile), and AWS's instance metadata service (IMDS) — a local endpoint every EC2 instance can query about itself — serves short-lived credentials for that role to any process on the machine. The AnthropicAWS client reads them through the AWS default credential provider chain, which per Anthropic's docs includes EC2 IMDS as a supported source, and SigV4-signs every Claude request with them.

The payoff is twofold. Zero key management: nothing to generate, store in a secrets manager, inject at deploy time, or scrub from images and logs. Automatic rotation: IMDS-delivered credentials are temporary and refreshed by the platform; the SDK simply keeps reading fresh ones from the chain. There is no rotation runbook because there is nothing to rotate.

The setup, end to end

1. Create the role and scope it. Create an IAM role trusted by the EC2 service and attach a policy scoped to your workspace. The minimal inference policy from the official reference is the right starting point — Allow CreateInference, CountTokens, GetModel, ListModels, and GetWorkspace on arn:aws:aws-external-anthropic:us-west-2:123456789012:workspace/wrkspc_01AbCdEf23GhIj. Ready-made documents are in the policy templates.

2. Attach it to the instance. Associate the role's instance profile with the EC2 instance (at launch or later). Every process on that instance can now obtain the role's credentials — which is exactly why the policy should be narrow.

3. Set the two non-secret config values. The client still needs its required configuration — the AWS region and workspace ID, neither of which is sensitive:

export AWS_REGION='us-west-2'                # your workspace's region
export ANTHROPIC_AWS_WORKSPACE_ID='wrkspc_01AbCdEf23GhIj'

4. Write ordinary code. No credential parameters anywhere:

from anthropic import AnthropicAWS

client = AnthropicAWS()  # role credentials arrive via IMDS
resp = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Draft a status update."}],
)
print(resp.content[0].text)

Because the credentials are temporary, the SDK also sends the x-amz-security-token session-token header automatically — you'll see it if you ever inspect requests, and it's expected.

Pitfalls worth knowing

IMDS is last in the chain. The credential chain checks environment variables, shared credential files, web identity, and container credentials before the instance role. A leftover AWS_ACCESS_KEY_ID exported in a service unit, a stray ~/.aws/credentials from debugging, or credentials baked into an AMI will silently win over the role you attached. If requests are being denied under an identity you don't recognize, audit the higher chain links first — details in the credential chain guide.

Missing region or workspace fails fast. The client raises at construction — before any request — if AWS_REGION (or AWS_DEFAULT_REGION) or ANTHROPIC_AWS_WORKSPACE_ID is unset. Unlike the Bedrock client, there is no us-east-1 fallback. Bake both into the instance's launch configuration or service environment.

A 403 is authorization, not authentication. If the request reaches the server and comes back 403, the role authenticated fine but either the workspace ID is wrong or the role's policy is missing an aws-external-anthropic: action. Check the policy against the actions reference.

Account prerequisite still applies. If every request fails with "Outbound web identity federation is disabled for your account," that's the one-time account setting (aws iam enable-outbound-web-identity-federation), not an instance-role problem. Verify the account's federation state with aws iam get-outbound-web-identity-federation-info.

Auditing works out of the box. Because requests are signed by a named role, your CloudTrail and IAM tooling attribute Claude traffic to that role like any other AWS service call. Note that inference calls are CloudTrail Data events, so enabling (paid) data-event logging is required if you want them in the trail; the x-amzn-requestid on each response ties a specific API response back to its log entry.

Rule of thumb: instance-role credentials are per-instance, not per-process. If multiple applications with different trust levels share one EC2 host, they share one role — consider separate instances, or a container platform where task roles or per-pod IRSA roles give finer-grained identities.

Where to go next

The same zero-key pattern on other compute: ECS and Fargate task roles, IRSA for Kubernetes pods, and Lambda execution roles. For the signing mechanics underneath, see SigV4 under the hood.

Sources