IAM Basics for SDK Auth Best Practices
A working checklist of IAM habits that keep AWS SDK authentication secure without slowing you down.
Search across all documentation pages
A working checklist of IAM habits that keep AWS SDK authentication secure without slowing you down.
Each rule is stated positively, with a one-line reason and how to enforce it.
sts:AssumeRole gives scoped, expiring credentials instead of shared static keys.# --- Python (boto3) ---
# Good: no keys in code, SDK resolves the attached role.
import boto3
s3 = boto3.client("s3")// --- TypeScript (AWS SDK v3) ---
// Good: empty config triggers the default credential provider chain.
import { S3Client } from "@aws-sdk/client-s3";
const s3 = new S3Client({});service:Operation actions instead of s3:* or Action: "*".Resource: "*" with the exact bucket, prefix, table, or queue where possible.aws:SourceIp, resource tags, or required encryption to constrain permitted actions further.{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ScopedReadWrite",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::acme-uploads/tenant-*/*"
}
]
}Status="Inactive" gives a safe rollback window before permanent removal.list_access_keys metadata and flag any key older than your rotation policy.# --- Python (boto3) ---
import boto3
iam = boto3.client("iam")
for k in iam.list_access_keys(UserName="ci-deployer")["AccessKeyMetadata"]:
print(k["AccessKeyId"], k["Status"], k["CreateDate"])// --- TypeScript (AWS SDK v3) ---
import { IAMClient, ListAccessKeysCommand } from "@aws-sdk/client-iam";
const iam = new IAMClient({});
const { AccessKeyMetadata } = await iam.send(
new ListAccessKeysCommand({ UserName: "ci-deployer" }));
AccessKeyMetadata?.forEach((k) => console.log(k.AccessKeyId, k.Status, k.CreateDate));SimulatePrincipalPolicy to confirm each intended action is allowed and each forbidden one is denied.Resource: "*", note why so reviewers do not mistake it for laziness.Because it has the highest leverage. A role delivers temporary, auto-rotating credentials with no stored secret, which removes an entire class of leak-and-linger risk before you even think about policy scope.
Only when nothing can assume a role - typically a system outside AWS or legacy tooling during migration. Even then, scope the permissions tightly and rotate on a schedule.
Nothing. IAM evaluates policies on every request regardless of breadth, so a narrow policy is exactly as fast as a broad one while being far safer.
To contain damage. If one workload is compromised, a dedicated least-privilege role limits the attacker to that workload's permissions instead of everything the shared role could do.
Create the new key, deploy and verify it, deactivate the old key, then delete it. Deleting first would break the running credential and cause an outage.
Deactivation is reversible and deletion is not. Setting the key to Inactive first gives you a rollback window to confirm nothing depended on it.
Do not put them in code at all - use roles and the default provider chain. As a backstop, run a secret scanner in CI and store any unavoidable secret in a secrets manager.
Look up the CloudTrail event to see the exact action and resource, then simulate that same action against the principal. That tells you precisely which permission to add - retrying does nothing.
For account-wide actions with no specific resource, such as s3:ListAllMyBuckets. Document these so a reviewer knows the wildcard is required rather than careless.
It caps the maximum permissions a role can have, which is valuable when you let another team or automation create roles. The boundary limits what those delegated roles can ever grant.
Use managed policies for permissions shared across many principals, and inline policies to keep a single role's unique, one-off permissions local and easy to reason about.
On a recurring cadence, not once. Re-run Access Analyzer, review CloudTrail, prune unused actions, and confirm key ages against your rotation policy regularly.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Reviewed by Chris St. John·Last updated Jul 23, 2026