Safeguard
Cloud Security

AWS IAM Security Best Practices: A 2026 Field Guide

IAM is where most AWS breaches actually happen. This field guide covers least privilege, role assumption, permission boundaries, and the policy patterns that keep blast radius small.

Marcus Chen
Cloud Security Engineer
5 min read

Ask an incident responder where AWS breaches actually happen and the answer is rarely "a vulnerability." It's identity: a leaked access key, an over-permissioned role, a trust policy that let the wrong account assume it. IAM is simultaneously the most powerful and the most misunderstood service in AWS, because its failure mode is silent — an over-broad policy works perfectly right up until it's the thing that turns one compromised function into an account takeover. This field guide is a set of patterns, not principles, so each item is something you can check or change today.

The Mental Model: Every Permission Is Blast Radius

Before the patterns, internalize one idea. Every permission you grant is a measure of what an attacker gets if that identity is compromised. A role with s3:GetObject on one bucket has a blast radius of one bucket. A role with s3:* on * has a blast radius of your entire data estate. IAM security is the discipline of keeping blast radius small, and every practice below is a way of doing that.

Pattern 1: Kill Long-Lived Access Keys

Long-lived access keys are the credential most likely to end up in a repo, a laptop backup, or a scraper's database. Replace them with temporary credentials from role assumption wherever possible. Humans should authenticate through AWS IAM Identity Center; workloads should use IAM roles for service accounts (IRSA on EKS), instance profiles, or task roles. If a long-lived key genuinely can't be avoided, rotate it on a schedule and scope it to the absolute minimum.

Audit for old keys directly:

aws iam list-users --query 'Users[].UserName' --output text | \
  tr '\t' '\n' | while read u; do
    aws iam list-access-keys --user-name "$u" \
      --query 'AccessKeyMetadata[?Status==`Active`].[UserName,CreateDate]' \
      --output text
  done

Any key older than your rotation window is a finding.

Pattern 2: Write Policies With Explicit Actions and Resources

The most common IAM mistake is the wildcard. Deny yourself the habit of "Action": "*" and "Resource": "*" outside of break-glass admin roles. Scope to what the workload does:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "ReadReportsOnly",
    "Effect": "Allow",
    "Action": ["s3:GetObject", "s3:ListBucket"],
    "Resource": [
      "arn:aws:s3:::acme-reports",
      "arn:aws:s3:::acme-reports/*"
    ]
  }]
}

Add Condition blocks to tighten further — restrict by source VPC, by tag, or by aws:PrincipalOrgID so a policy can't be assumed from outside your organization.

Pattern 3: Right-Size With Access Analyzer

You don't have to guess what a role needs. IAM Access Analyzer generates policies from CloudTrail history and flags unused access. Run its unused-access findings regularly and strip permissions a role hasn't touched in 90 days. This is the fastest way to shrink an existing account's blast radius without breaking anything, because you're removing access that demonstrably isn't used. Our writeup on least-privilege IaC patterns shows how to bake the results back into version-controlled policy.

Pattern 4: Use Permission Boundaries for Delegated Admin

When you let teams create their own roles (which you should, to avoid a central bottleneck), a permission boundary caps what those roles can ever grant. It's a ceiling: a developer can create roles freely, but no role they create can exceed the boundary. This lets you delegate IAM safely — the team moves fast, and the boundary guarantees they can't escalate beyond your intent.

Pattern 5: Guardrails With Service Control Policies

SCPs sit above IAM at the AWS Organizations level and no IAM policy can override them. Use them for organization-wide invariants: deny disabling CloudTrail, deny removing S3 public-access blocks, deny actions in regions you don't operate in, and require IMDSv2. Even a fully compromised account with admin IAM can't violate an SCP.

Pattern 6: Lock Down Trust Policies

A role is only as safe as who can assume it. Review every role's trust policy for overly broad principals — "Principal": {"AWS": "*"} with a weak condition is an open door. For cross-account roles, require an ExternalId and pin the source account. For OIDC federation (GitHub Actions, for example), pin the sub claim to the specific repo and branch so an unrelated workflow can't assume the role.

IAM Security Checklist

PracticeCheckPriority
Long-lived keysNone active beyond rotation windowCritical
Root accountMFA on, no access keysCritical
PoliciesNo */* outside break-glassCritical
Access AnalyzerUnused access reviewed monthlyHigh
Permission boundariesApplied to delegated role creationHigh
SCPsDeny disabling logging / public-access blocksHigh
Trust policiesNo broad principals, ExternalId on cross-accountHigh

How Safeguard Helps

IAM policies live in your Terraform and CloudFormation long before they live in AWS, which is exactly where Safeguard catches the dangerous ones. It scans your infrastructure-as-code for wildcard actions, over-broad trust policies, missing conditions, and public-access risks in the pull request that introduces them — so an over-permissioned role is flagged against the specific line of HCL before it ever reaches your account. Griffin, Safeguard's AI triage engine, then ranks those identity findings by real blast radius, surfacing the role that grants s3:* on a production bucket ahead of a harmless read-only policy. If you're comparing this build-time model to a cloud posture platform that evaluates IAM after deployment, the Safeguard vs Prisma Cloud comparison lays out the difference in timing and cost of remediation.

IAM security isn't about a single setting — it's the sum of many small decisions to keep blast radius small. Kill long-lived keys, scope every policy, review unused access, and enforce guardrails that no IAM policy can override.

Want to catch over-permissioned IAM roles before they deploy? Start free with Safeguard or read the documentation to scan your first IaC repository.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.