AWS Identity and Access Management (IAM) decides who can call which AWS API on which resource. Every request to AWS, from the console, the CLI or an SDK, passes through it. A mistake here is how most cloud breaches start: a leaked access key, an over-broad role, or a shared root password. This note covers the identities, and the next two notes cover the policies that give them permissions.
For the general ideas of authentication (who are you?) and authorization (what may you do?), see API security considerations. IAM is AWS's implementation of both.
The pieces at a glance#
IAM has a few building blocks. Each one answers a different question.
| Identity | What it is | Credentials |
|---|---|---|
| Root user | The identity that created the account | Email and password, optional access keys |
| IAM user | A long-lived identity for one person or app | Password and/or access keys |
| IAM group | A collection of users that share policies | None. A group can't sign in |
| IAM role | A set of permissions that someone assumes | Temporary, from AWS STS |
Two more terms come up everywhere in IAM, so it helps to pin them down now. A principal is any identity that makes a request: a user, a role session, an AWS service, or a federated user. A policy is a JSON document attached to a principal or resource that allows or denies actions.
One rule applies to all of these: IAM is secure by default. A new user or role has no permissions. Every request is denied until a policy allows it.
The root user#
The root user has full, unrestricted access to everything in the account, including billing and closing the account. Policies inside the account can't limit it.
Because nothing inside the account can limit it, treat the root user as a break-glass identity, one you lock away for emergencies:
- Turn on MFA for it on day one.
- Delete its access keys, or never create them.
- Don't use it for daily work. Create other identities for that.
- Use it only for the few tasks that require it, such as changing account-level settings.
Root can still be limited from outside the account. In an AWS Organization, the management account can restrict member accounts' root users with service control policies. See IAM policy types.
IAM users#
Since root is off-limits for daily work, you need other identities. The first option is an IAM user, a named identity with long-term credentials:
- A password to sign in to the AWS Management Console.
- Access keys (an access key ID plus a secret access key) for the CLI, SDKs and API.
- A few older services also accept X.509 signing certificates.
Each user's actions appear under their own name in AWS CloudTrail. That gives you accountability that a shared login can't.
Long-term credentials are also the weak point. Access keys don't expire. They leak through Git commits, laptop backups and CI logs. AWS now recommends that people sign in through federation (see below) and that you keep IAM users for the rare cases that need them.
IAM groups#
Once you have more than a few users, attaching policies to each one gets hard to track. A group lets you manage permissions for many users at once. You attach policies to the group, and every member inherits them.
- A user can belong to several groups. Their permissions are the combination of all of them.
- When someone changes team, move them between groups instead of editing policies.
- A group is not a principal. It can't sign in, and you can't name it in a resource policy.
- Groups can't contain other groups. There is no nesting, so a deep org chart becomes many flat groups.
A typical setup has groups such as Admins, Developers and ReadOnly, each with its own policies.
IAM roles and temporary credentials#
Roles fix the weak point of users: credentials that never expire. A role is an identity with permissions but no long-term credentials. Instead of signing in as a role, a trusted principal assumes it. AWS Security Token Service (STS) then returns temporary credentials: an access key ID, a secret key and a session token that expire after a set time.
Assuming a role raises two questions: who may do it, and what they get. Each role has a policy for each:
- A trust policy says who may assume the role.
- A permissions policy says what the role may do once assumed.
Where roles are used#
Roles cover most access that isn't a person at a keyboard.
| Who assumes it | Example |
|---|---|
| An AWS service | An EC2 instance profile lets an app on the instance read from S3. A Lambda execution role lets a function write to DynamoDB |
| A user in another account | A partner account's role reads one shared bucket |
| A federated user | A developer signs in through the company identity provider and gets a role |
| A CI/CD pipeline | A GitHub Actions job exchanges an OIDC token for a deploy role |
For the EC2 case, the app never stores a key. The SDK fetches temporary credentials from the instance metadata service, and AWS rotates them before they expire.
Users vs roles#
With both identities covered, the table sums up when each one fits.
| IAM user | IAM role | |
|---|---|---|
| Lifetime | Long-term | Per session |
| Credentials | Persistent password or keys | Temporary, issued by STS |
| Tied to | One person or app | Whoever the trust policy allows |
| Permissions from | Own policies plus group policies | Permissions policies (the trust policy only says who may assume it) |
Switching roles#
When you assume a role, you swap permissions instead of adding them together.
Say an app runs as role A, which can list an S3 bucket. It assumes role B, which can read and write a DynamoDB table. While it uses role B's credentials, it can use DynamoDB but can't list the bucket. To list the bucket again, it must go back to role A's credentials.
Assuming one role from another is role chaining. AWS caps a chained session at one hour, and long chains make CloudTrail harder to follow. Keep chains short.
Multi-factor authentication (MFA)#
Roles cover workloads, but people still sign in with passwords, and passwords leak too. MFA asks for a second factor in addition to a password. IAM supports passkeys and security keys (FIDO), virtual authenticator apps, and hardware TOTP tokens.
- Require MFA for the root user and every human with console access.
- You can also require MFA for sensitive API calls. A policy condition on
aws:MultiFactorAuthPresentdenies the call unless the session used MFA.
Federation#
Federation is the sign-in method AWS recommends for people, as mentioned under IAM users. It lets people use an identity they already have instead of a separate IAM user. The external identity provider (IdP) authenticates the person. AWS trusts the IdP and hands out temporary role credentials.
- SAML 2.0 connects corporate directories such as Microsoft Entra ID (formerly Azure AD), Okta or Active Directory.
- OIDC connects web identity providers and CI systems.
- AWS IAM Identity Center is the managed option for a workforce across many accounts. It gives single sign-on (SSO) and maps directory groups to permission sets in each account.
With federation, leavers lose AWS access when their directory account is disabled. Nobody has to hunt for stray IAM users.
Least privilege#
Least privilege means each identity gets only the permissions its task needs, and nothing else. It limits the blast radius when a credential leaks or code has a bug. Here's a practical way to get there:
- Start with a narrow policy, or an AWS managed policy for a first draft.
- Watch what the identity uses. IAM Access Analyzer can generate a policy from CloudTrail activity.
- Replace broad actions such as
s3:*with the specific actions used. - Review "last accessed" data and remove permissions that nobody uses.
AWS managed policies are a quick start, but many grant more than one team needs. Move to your own customer managed policies as usage becomes clear.
Best practices#
These habits cover most of what goes wrong with IAM.
Identities#
- Lock away the root user: MFA on, no access keys.
- Have people sign in through federation or IAM Identity Center with temporary credentials.
- Give each person or workload its own identity. Never share credentials.
- Use roles for workloads on EC2, Lambda, containers and CI. Don't put access keys in code or config.
Permissions#
- Grant least privilege, and review it regularly with access levels and last-accessed data.
- Attach policies to groups or roles, not to individual users.
- Use roles to delegate access across accounts instead of sharing keys.
Credentials#
- Enforce a strong password policy for any remaining IAM users.
- Require MFA for privileged users.
- Rotate the access keys that must exist, and remove unused credentials.
Limitations to know#
IAM has some sharp edges. Most have a standard workaround.
| Limitation | Effect | Common workaround |
|---|---|---|
| No nested groups | Users join many flat groups by hand | Map IdP groups to roles or permission sets |
| Some actions lack resource-level control | You must use "Resource": "*" for them |
Check the service authorization reference; narrow with conditions |
| No built-in just-in-time access | Temporary elevation needs a custom flow | Short role sessions plus an approval workflow |
| Roles and policies never expire | Forgotten access stays live | Review last-accessed data; automate cleanup |
| No record of who created a resource | Ownership tracking is manual | Enforce tags with policies; read CloudTrail |
| One account is a weak tenant boundary | Isolating tenants in one account is hard | Use separate accounts in AWS Organizations |
| Large policies are hard to reason about | Unexpected allows or denies | Validate with IAM Access Analyzer; keep policies small |
One more gap doesn't fit the table. Policies can react to some context, such as source IP, time of day or MFA, through condition keys. They don't react to behavior, such as a sudden spike in API calls. For that, add detection with services such as Amazon GuardDuty and AWS Config.
Key takeaways#
- IAM is secure by default: nothing is allowed until a policy allows it.
- Lock away the root user with MFA and no access keys.
- Users have long-term credentials; roles hand out temporary STS credentials. Prefer roles.
- Groups bundle policies for users, can't sign in, and can't be nested.
- Assuming a role swaps your permissions for the role's permissions.
- Federate people through an IdP or IAM Identity Center, and grant least privilege.