AWS IAM

AWS Identity and Access Management (IAM) is the service that controls who can do what in an AWS account. Every API call to every AWS service — launching an EC2 instance, reading an S3 bucket, invoking a Lambda function — is authorized by IAM first. It's the foundation the entire account's security rests on, and the single most important AWS service to understand, because nearly every AWS security incident traces back to an IAM misconfiguration.

IAM's model is deny-by-default: nothing is allowed until a policy explicitly grants it. Get IAM right — least privilege, roles instead of long-lived keys, no wildcard admin everywhere — and most of AWS security follows. Get it wrong and a single leaked credential or over-permissive policy exposes everything.

TL;DR

Core Concepts

Users, Roles, and Groups

The most important distinction: roles have no permanent credentials. When an EC2 instance, Lambda function, or federated user assumes a role, AWS issues short-lived credentials (via STS) that expire automatically. This is why roles are strongly preferred — there's no static key sitting in a config file to leak. An instance profile attaches a role to EC2; the service uses it transparently.

Policies

Permissions are JSON policy documents. The anatomy:

Policy types you'll meet: managed policies (reusable, AWS- or customer-managed), inline policies (embedded in one identity), resource-based policies (attached to the resource itself, like an S3 bucket policy — these enable cross-account access), and SCPs (Service Control Policies, org-wide guardrails that cap what accounts can do).

How Access Is Decided

When a request is made, IAM evaluates all applicable policies with a specific precedence:

The rules that trip people up: an explicit Deny overrides any Allow (useful for guardrails), and everything is denied unless something explicitly allows it. Permission boundaries and SCPs add ceilings — even an Allow doesn't work if a boundary/SCP forbids it. When "I have Allow but it's still denied," suspect an SCP, boundary, or resource-policy blocking it.

Roles in Practice: Assuming and Federation

Roles are assumed via STS (sts:AssumeRole), which returns temporary credentials. This powers:

Best Practices

Least Privilege

Grant only the permissions actually needed, scoped to specific resources. Start restrictive and add as required — the opposite of the tempting "Action": "*", "Resource": "*" that turns every credential into account-admin. Use IAM Access Analyzer to find unused permissions and generate least-privilege policies from actual usage.

Kill Long-Lived Access Keys

Static IAM user access keys are the #1 AWS credential-leak vector (committed to git, embedded in code, left in CI). Replace them:

If a workload has no access key to leak, that entire attack class disappears — this is the highest-leverage IAM improvement most accounts can make.

Enforce MFA and Guardrails

Require MFA for humans (especially privileged actions), use SCPs in AWS Organizations to set account-wide guardrails (block regions, prevent disabling logging, deny root usage), and set permission boundaries to cap what roles others create can grant. Lock down the root account entirely — MFA on it, no access keys, use only for the rare tasks that require it.

Audit Everything

Enable CloudTrail so every IAM action is logged, review with Access Analyzer, and rotate any remaining credentials. IAM without an audit trail is security theater — you can't detect misuse you don't log.

Common Mistakes

Wildcard Admin Everywhere

Attaching AdministratorAccess (or "*":"*" policies) to users, roles, and services "to make it work" means every credential is a master key. A leaked key or compromised service then owns the account. Scope permissions to what's needed — the extra effort is the entire point of IAM.

Long-Lived Access Keys in Code/CI

Access keys in source, config files, or CI variables get leaked constantly (public repos, logs, breaches). Use roles and OIDC federation so there are no static keys. If you find AKIA... in a codebase, that's an incident.

Confusing Identity-Based and Resource-Based Policies

Cross-account and service-to-service access often needs both an identity policy (the caller may act) and a resource policy (the resource permits the caller). "I granted the role S3 access but it's denied" is frequently a missing bucket policy — or vice versa.

Ignoring Explicit Deny and SCP Interactions

An Allow that "doesn't work" is usually blocked by an explicit Deny, an SCP guardrail, or a permission boundary higher up. Understand the evaluation order before debugging — the problem is often a ceiling you forgot about.

Neglecting the Root Account

The root user can do anything, including bypass some controls. Leaving it without MFA, with active access keys, or using it routinely is a critical risk. Secure it, remove its keys, and use IAM/Identity Center for daily work.

FAQ

What's the difference between an IAM user and a role?

A user is a persistent identity with long-lived credentials (password/access keys). A role is an assumable identity that grants temporary, auto-expiring credentials when assumed. Roles are preferred for nearly everything — services, cross-account access, and federated humans — because there's no permanent secret to leak. Modern AWS best practice minimizes users almost to zero.

How do I let an EC2 instance or Lambda access other AWS services?

Attach an IAM role (instance profile for EC2, execution role for Lambda). The workload automatically receives temporary credentials scoped to that role — no access keys to store or rotate. This is the correct, secure pattern; embedding access keys in the instance/function is the mistake to avoid.

Why is my request denied even though I have an Allow policy?

Check for: an explicit Deny somewhere (it overrides Allow), a Service Control Policy capping the account, a permission boundary on the role, or (for cross-account/resource access) a missing resource-based policy. IAM is deny-by-default with ceilings, so an Allow is necessary but not always sufficient.

What's the best way for my team to access AWS?

IAM Identity Center (formerly AWS SSO) or federation with your identity provider — humans log in through SSO and assume roles for temporary credentials, with MFA enforced. Avoid creating IAM users with personal access keys for people; it's harder to manage and far easier to leak.

How does IAM relate to zero trust?

IAM is AWS's implementation of zero-trust principles for cloud access: identity-based authorization on every request, least privilege, temporary credentials, and full auditing. Roles + short-lived credentials + tight policies are exactly the "never trust, always verify, grant the minimum" model applied to AWS.

Related Topics

References