AWS Identity and Access Management (IAM) is the service that decides, for every single action in your AWS account, whether it is allowed. Every API call — launching an instance, reading a file from S3, writing to a database — is authenticated and then checked against IAM policies. Because of this, IAM is the foundation of AWS security: get it right and your account is well-defended; get it wrong and you risk data breaches or runaway resources.
IAM is also one of the most misunderstood AWS services, partly because its flexibility can be intimidating. But the core model is logical and learnable: you have identities, you attach policies to them, and AWS evaluates those policies on every request. Master that mental model and the rest falls into place.
This guide explains IAM in depth: its building blocks, how policy documents are structured, how AWS decides allow vs deny, the central role of IAM roles and temporary credentials, and the best practices — least privilege, MFA, and avoiding the root account — that keep real accounts safe.
What Is IAM?
IAM lets you create identities and grant them precise permissions through policies — JSON documents that list which actions are allowed or denied on which resources. IAM is global (not tied to a Region), free to use, and integrated with every AWS service. Nothing in your account can act without permissions explicitly granted through IAM.
The Building Blocks
- Users — long-lived identities representing a person or an application, with their own credentials (password and/or access keys).
- Groups — collections of users that share permissions (e.g. Developers, Admins). Attach policies to the group and all members inherit them.
- Roles — identities with permissions that are assumed temporarily, with no permanent credentials. Services (EC2, Lambda), users, and other accounts assume roles to get short-lived access.
- Policies — the JSON documents that define permissions, attached to users, groups, or roles.
Anatomy of a Policy Document
An IAM policy is JSON with one or more statements. Each statement has an Effect (Allow or Deny), one or more Actions (the API operations), a Resource (which ARNs it applies to), and optional Conditions (e.g. only from a certain IP or only with MFA).
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadOneBucket",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::my-app-bucket",
"arn:aws:s3:::my-app-bucket/*"
],
"Condition": {
"IpAddress": {"aws:SourceIp": "203.0.113.0/24"}
}
}
]
}
Identity-Based vs Resource-Based Policies
Most policies are identity-based — attached to a user, group, or role. Some services also support resource-based policies attached to the resource itself (an S3 bucket policy, an SQS queue policy, a Lambda permission). Resource-based policies are essential for cross-account access, letting another account act on your resource without you creating users for them.
How AWS Evaluates Permissions
When a request is made, AWS gathers all applicable policies and applies a clear rule: an explicit Deny always wins; otherwise, access is granted only if some policy explicitly Allows it; if nothing allows it, the default is Deny. In short: deny > allow > implicit deny. This is why you can safely grant broad access in one policy and carve out exceptions with an explicit Deny in another.
Roles and Temporary Credentials (STS)
Roles are the modern, preferred way to grant access. Instead of embedding long-lived access keys in an application, you attach a role; behind the scenes the Security Token Service (STS) issues short-lived credentials that rotate automatically. An EC2 instance with an attached role, a Lambda function with an execution role, or a CI pipeline assuming a deployment role all get exactly the permissions they need without any secret ever being stored.
Permission Boundaries and SCPs
For larger organizations, two guardrails matter: a permissions boundary caps the maximum permissions a user or role can have (even if a policy grants more), and Service Control Policies (SCPs) in AWS Organizations set account-wide limits across many accounts. Together they let central teams delegate safely without risking over-permissioning.
Real-World Use Cases
- Granting a Lambda function read access to exactly one S3 bucket — and nothing else.
- Giving a team read-only access to billing or to specific services.
- Letting an EC2 instance call AWS APIs through an instance role instead of stored keys.
- Enabling secure cross-account access with assumable roles.
- Enforcing MFA-only access to sensitive actions via policy conditions.
Creating a User and Attaching a Policy (CLI)
# Create a user
aws iam create-user --user-name app-reader
# Attach an AWS-managed read-only policy
aws iam attach-user-policy \
--user-name app-reader \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
# Create a role an EC2 instance / Lambda can assume (trust policy in a file)
aws iam create-role --role-name app-role \
--assume-role-policy-document file://trust-policy.json
Best Practices
- Least privilege — grant only the permissions actually needed; start narrow and widen as required.
- Use roles, not long-lived keys — especially for EC2, Lambda, containers, and CI/CD.
- Enable MFA on the root account and all privileged users.
- Lock away the root account — never use it for daily work; create individual admin users instead.
- Use IAM Identity Center (SSO) for human access across multiple accounts.
- Review with Access Analyzer — find unused permissions and unintended public/cross-account access.
Common Mistakes to Avoid
- Granting
"Action": "*"/ AdministratorAccess everywhere — far too broad. - Hard-coding access keys in code or Git — use roles and a secrets manager.
- Sharing one IAM user among many people — destroys auditability; give everyone their own identity.
- Skipping MFA on the root user and admins.
- Never rotating credentials — rotate keys, or better, eliminate them with roles.
Frequently Asked Questions
User or role — which should I use? Prefer roles for anything programmatic; use users (ideally via Identity Center) for people.
Is IAM free? Yes — IAM itself has no charge; you pay only for the AWS resources actions touch.
What wins, allow or deny? An explicit Deny always overrides any Allow.
How do apps get credentials safely? Through roles and STS, which issue automatically rotating short-lived credentials.
What is the difference between authentication and authorization in IAM? Authentication verifies who you are (via credentials), while authorization decides what you're allowed to do (via policies). IAM handles both: it first confirms the identity behind a request, then evaluates every applicable policy to allow or deny the specific action.
Can I test a policy before applying it? Yes — use the IAM Policy Simulator to check whether a given policy would allow or deny specific actions, which helps you validate least-privilege changes safely before rollout.
Summary Table
| Element | Role in IAM |
|---|---|
| User | Long-lived identity for a person/app |
| Group | Shared permissions for many users |
| Role | Temporary, assumable permissions |
| Policy | JSON defining allowed/denied actions |
| STS | Issues short-lived credentials |
Cross-Account Access in Practice
A common real-world need is letting one AWS account access resources in another — for example, a central security account auditing many workload accounts, or a CI/CD account deploying into production. IAM handles this elegantly with cross-account roles. In the resource-owning account you create a role whose trust policy names the other account as allowed to assume it, and attach the permissions that role should grant. Users or services in the trusted account then call sts:AssumeRole to receive temporary credentials for that role. No passwords or access keys are shared between accounts, every assumption is logged in CloudTrail, and access can be revoked instantly by editing the trust policy. This pattern is the backbone of secure multi-account AWS organizations and is far safer than creating duplicate users in each account.
Credential Types in AWS
It helps to know the kinds of credentials IAM deals with. Console passwords let people sign in to the web console. Access keys (an access key ID and secret) authenticate programmatic calls from the CLI or SDKs — these are long-lived and the most commonly leaked, so minimize them. Temporary security credentials from STS are short-lived (minutes to hours) and automatically rotated; roles hand these out behind the scenes. The modern guidance is clear: prefer temporary credentials via roles everywhere you can, and treat any long-lived access key as a liability to be eliminated.
Auditing with Access Analyzer and CloudTrail
Granting permissions is only half the job; you also need visibility into how they're used. IAM Access Analyzer continuously checks your policies and flags resources that are shared publicly or across accounts, and can generate least-privilege policies based on your actual access activity. AWS CloudTrail records every API call in your account — who did what, when, and from where — which is essential for security investigations and compliance. Together they let you tighten permissions over time and prove that your controls work.
A Day-One IAM Setup Checklist
- Secure the root user with a strong password and hardware/virtual MFA, then stop using it.
- Create individual admin users (or, better, set up IAM Identity Center for SSO).
- Enforce MFA for all human users and a strong password policy.
- Replace any application access keys with roles.
- Turn on CloudTrail and review Access Analyzer findings regularly.
Reference
This article follows the official AWS documentation. Read the full reference here: AWS IAM documentation.
Conclusion
IAM is where AWS security begins and ends. Model access with users, groups, and (above all) roles; write least-privilege policies; understand that explicit deny always wins; enable MFA; and keep the root account untouched. Lean on roles and STS so secrets never live in your code. Done well, IAM gives you tight, auditable, and flexible control over everything that happens in your cloud.
π¬ Comments (0)
No comments yet. Be the first to share your thoughts!