AWS IAM Explained: Users, Groups, Roles, and Policies
The single most common way people burn through their AWS free tier — or worse, rack up a real bill — isn't a bad architecture decision. It's signing in as the root user for everyday work, or attaching a policy so broad it doesn't matter what actually goes wrong. IAM (Identity and Access Management) is the AWS service that fixes both problems, and it's foundational enough that every DMI assignment from Week 6 (AWS Cloud) onward assumes you understand it. This post covers the four IAM building blocks — users, groups, roles, policies — and then walks through creating your first IAM user the way AWS actually recommends.
Root user vs. IAM user
When you create an AWS account, you get exactly one root user — the email and password you signed up with. Root has unrestricted access to everything in the account, including billing, and it cannot be limited by a policy. That's precisely why you shouldn't use it day to day: if root credentials leak, there's no permission boundary standing between an attacker and your entire account.
An IAM user is a separate identity you create inside the account — for yourself, a teammate, or an application — that starts with zero permissions until you explicitly grant some. AWS's own IAM security best practices are direct about this: lock away root credentials, enable MFA on root, and do essentially everything else through IAM identities with least-privilege permissions instead.
IAM groups — attach policies once, not per person
A group is just a named collection of users. You attach a policy to the group, and every current and future member inherits it. The alternative — attaching the same policy to five individual users — means five places to update when permissions change, and five chances to miss one. If you're onboarding a new developer, adding them to the "Developers" group is one action instead of re-deriving what permissions they need from scratch.
IAM policies — the actual rules
A policy is a JSON document that defines what's allowed: which actions, on which resources, under which conditions. AWS ships managed policies for common cases (like AmazonS3ReadOnlyAccess), which are a reasonable starting point — but the best-practice direction is to move toward narrower, customer-managed policies scoped to exactly what a task needs, once you know what that is. A minimal example, granting read-only access to one specific S3 bucket rather than every bucket in the account:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::my-portfolio-site",
"arn:aws:s3:::my-portfolio-site/*"
]
}
]
}
That's least privilege in practice: not "can this user do their job," but "can this user do their job and nothing else." See policies and permissions in IAM for the full policy language.
IAM roles — identity without a password
A role has no password and no permanent access keys. Instead, it's assumed — by a person, an application, or an AWS service — and grants temporary credentials that expire. The classic example: an EC2 instance that needs to read from S3 gets an IAM role attached to it, and AWS delivers short-lived credentials directly to the instance. No access key sitting in a config file for someone to leak.
This matters beyond EC2. AWS's current guidance is that workloads should use roles for temporary credentials, not IAM users with long-term access keys, wherever the workload can support it — and for human users at organization scale, AWS recommends IAM Identity Center (federated, temporary access) over creating individual IAM users at all. If you continue into DMI's Kubernetes weeks, you'll see this exact pattern again — a pod on an EKS node assuming a role instead of holding static credentials — covered in more depth in IAM for EKS: Cluster Role, Node Role, Pod Identity, and Cluster Access.
Why a personal learning account still starts with an IAM user
IAM Identity Center is the right answer once there's an organization with multiple AWS accounts to federate into. For a single free-tier account — which is what DMI's Week 6, Assignment 1 has you set up — there's no organization to federate into yet. The practical, AWS-documented starting point is: create one IAM user for yourself, require MFA on it, and stop signing in as root once it exists. That's what the walkthrough below does.
Hands-on: create your first IAM user with least-privilege access
- Sign in as root, once. You need root only for this first step — creating the IAM entities that replace it for everyday use.
- Open the IAM console and create a group — e.g.
Developers. - Attach a policy to the group, not to any individual user. Start with an AWS managed policy scoped to what you're actually doing (for a static-site assignment, that might be S3 access; for a compute assignment, EC2). Prefer a narrow customer-managed policy like the JSON example above once you know exactly what's needed.
- Create the IAM user — your name, not a shared "admin" account — and add it to the group. Skip generating access keys unless you specifically need programmatic (CLI/SDK) access; console-only users don't need them.
- Enable MFA on the new user. AWS's current guidance recommends phishing-resistant MFA (a passkey or security key) where you can use one — see MFA in IAM.
- Sign out of root and back in as your IAM user. From here, root is only for the handful of actions that genuinely require it (like closing the account) — everything else happens as the IAM user.
The mistake this avoids isn't hypothetical: it's how people accidentally leave the AWS free tier without noticing, because a broad policy or a leaked root credential let something run up charges no budget alert caught in time. Least privilege is the actual guardrail — the budget alert from Assignment 1 is the backstop, not the first line of defense.
The four pieces, together
- Users — an identity for a person or application, zero permissions by default.
- Groups — attach a policy once, every member inherits it.
- Policies — the actual JSON rules; managed policies to start, customer-managed for least privilege.
- Roles — temporary, assumed credentials for services and (at scale) for humans via IAM Identity Center — no long-lived secret sitting around to leak.
Getting this right early matters more than it looks like it should — every AWS assignment in DMI's graded weekly loop, and every production system you touch afterward, inherits whatever permission model you set up first.
Want to practice this on real, graded assignments? Start with DMI Self-Paced →