AWS IAM: The Security Feature You Can’t Ignore


Alright, let’s talk about AWS Identity and Access Management (IAM). If you’re working with AWS, you’re stuck dealing with this beast, so you might as well understand it. IAM is the gatekeeper that decides who gets to touch what in your AWS account, and it’s a global service, meaning it doesn’t care where your resources are sitting. Sounds simple, right? Well, buckle up, because it’s a maze of policies, roles, and permissions that’ll make you want to pull your hair out. Here’s the lowdown, straight from my notes, with all the nitty-gritty details you need to survive this mess.
What the Heck is IAM?
IAM is AWS’s way of controlling who can do what in your account. When you first sign up, you get a root account tied to an email and password. Pro tip: don’t touch it. Seriously, lock it away and never use it unless you’re setting up the account or doing one of those rare tasks only the root user can handle. Sharing it is like handing out keys to your house—stupid and dangerous.
You’ve got users (actual people in your org) and groups (collections of users, because managing permissions one by one is a nightmare). Groups are handy, but don’t get cute—they can’t contain other groups, and users don’t have to be in a group, though they can be in multiple. It’s like herding cats, but you’ll thank yourself for organizing them later.
Authentication vs. Authorization: Know the Difference or Get Screwed
Let’s break this down so it’s crystal clear:
Authentication: This is the “who are you?” part. You punch in your email and password (or maybe a token or fingerprint if you’re fancy), and AWS decides if you’re legit. If you screw this up, you’re not getting in. Simple.
Authorization: Once you’re in, this is the “what can you do?” part. Authorization is where IAM flexes its muscles, deciding if you can read, write, delete, or create stuff. It’s the difference between browsing an S3 bucket and accidentally yeeting your entire database.
IAM Policies: The JSON Hellscape
Here’s where things get spicy. Permissions in IAM are defined by policies, which are JSON documents that make you question your life choices. These policies are slapped onto users or groups and spell out what they can or can’t do. The golden rule? Least privilege principle. Don’t give users more access than they need, or you’re begging for a security breach.
A policy looks something like this (brace yourself):
{
"Version": "2012-10-17",
"Id": "some-optional-id",
"Statement": [
{
"Sid": "optional-statement-id",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::123456789012:user/Bob"},
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": {"IpAddress": {"aws:SourceIp": "203.0.113.0/24"}}
}
]
}
Let’s decode this nightmare with my handy acronym: VISE PRINCIPAL ARC.
Version: Always “2012-10-17”. Don’t ask why, just do it.
Id: Optional policy identifier. Skip it if you’re lazy.
Statement: The meat of the policy. Required. Contains:
Sid: Optional statement ID.
Effect: “Allow” or “Deny”. Pick one.
Principal: Who this applies to (user, role, or account).
Action: What they can do (e.g., “s3:GetObject”). You can use “NotAction” to exclude specific actions.
Resource: What they’re messing with (e.g., an S3 bucket). Uses an ARN (Amazon Resource Name).
Condition: Optional rules for when the policy kicks in (e.g., only from a specific IP).
ARNs are the bane of your existence but critical. They look like this: arn:partition:service:region:account-id:resource-id. For example, arn:aws:s3:::my-bucket/* targets all objects in an S3 bucket. You can use wildcards (*) to be lazy, but don’t skip required fields unless it’s a global service like IAM or S3, where region might be blank.
Policy Evaluation: AWS’s Cruel Game of Deny
When someone tries to do something in AWS, IAM plays judge, jury, and executioner. Here’s how it decides:
Default Deny: Everything is denied unless explicitly allowed. No free rides.
Explicit Allow: If a policy says “Allow” for the action and resource, you’re golden—unless…
Explicit Deny: If any policy says “Deny,” you’re screwed. Deny always wins, no matter how many Allows you’ve got.
If a user’s policy says “Allow” but their group’s policy says “Deny,” guess what? They’re denied. This applies across user policies, group policies, and even resource policies. It’s like a veto that ruins your day.
Types of Policies: Because One Flavor Isn’t Enough
Inline Policies: These are glued directly to a user or role. Use them for one-off exceptions, like letting a service do something weird.
Managed Policies: These are standalone and reusable. There are two types:
AWS Managed Policies: Pre-built by AWS, like “AmazonS3ReadOnlyAccess.” Lazy but useful.
Customer Managed Policies: You make these. More work, but tailored to your needs.
Password Policies: Don’t Be That Guy
Want to make your account a hacker’s playground? Use weak passwords. AWS lets you set a password policy to avoid this disaster:
Minimum length (make it long, like 12 characters).
Require uppercase, lowercase, numbers, and special characters.
Let users change their own passwords (because you’re not their babysitter).
Force password changes periodically (90 days is common).
Block password reuse (no “password123” forever).
MFA: Because Passwords Alone Are a Joke
If you’re not using Multi-Factor Authentication (MFA), you’re basically inviting disaster. MFA combines something you know (password) with something you have (a device). AWS supports:
Virtual MFA: Apps like Google Authenticator or Authy on your phone.
U2F Security Key: Like a YubiKey. One key can work for multiple users.
Hardware Key Fob: Gemalto for regular AWS, SurePassID for GovCloud.
Enable MFA for your root account and IAM users. No excuses.
Resource Policies: The Other Side of the Coin
Some resources, like S3 buckets, have their own policies called resource policies. These can reference IAM users or roles via ARNs (sorry, groups don’t get an invite in the principal of policy). They’re handy for fine-grained control, like letting a specific user access a bucket without touching their IAM policy.
IAM Roles: Permit of Special Entry
IAM roles are like temporary VIP passes. They’re not tied to a specific user but can be assumed by AWS services, users, or external identities. Roles come with policies that define what they can do, and they use AWS Security Token Service (STS) to hand out temporary credentials (15 minutes to 36 hours).
Why bother with roles? Because hardcoding access keys in your Lambda function or EC2 instance is a security sin. Instead, let them assume a role. Examples:
Scenario 1: A Lambda function needs to read an S3 bucket. Create a role with S3 permissions, attach it to the Lambda, and it’s good to go.
Scenario 2: Cross-account access. Account A trusts Account B to assume a role, letting B’s users access A’s resources temporarily.
Roles are also clutch for identity federation, where external users (like your company’s Active Directory users) get temporary AWS access without needing IAM accounts. More on that later.
Identity Federation: Letting Outsiders In (Safely)
Got a ton of users outside AWS, like employees using Active Directory or customers logging in via Google? Identity Federation lets them access AWS without creating IAM users. It works by authenticating users externally (via Google, Okta, etc.) and using STS to issue temporary credentials.
SAML 2.0 Federation
SAML 2.0 is the go-to for enterprise setups. It’s an XML-based standard for secure authentication and authorization. Here’s how it works:
User logs into their identity provider (IdP), like Okta or Active Directory.
IdP generates a SAML Assertion (a fancy XML doc with user info and permissions).
The assertion goes to AWS STS via the AssumeRoleWithSAML API.
STS validates it and hands out temporary credentials tied to an IAM role.
User accesses AWS resources (Console, CLI, or API) with those credentials.
This is perfect for large orgs with thousands of users or when you want Single Sign-On (SSO). For example, an employee logs into Okta, gets redirected to the AWS Console, and assumes a role based on their group membership. No IAM user needed.
IAM Identity Center: SSO on Steroids
AWS pushes IAM Identity Center (formerly AWS SSO) for managing SSO across multiple AWS accounts and third-party apps. It’s fully integrated with SAML 2.0 and supports:
Users/Groups: From its own directory, Active Directory, or external IdPs like Okta.
Permission Sets: Predefined IAM policies assigned to users or groups.
Assignments: Link users to specific AWS accounts with specific permissions.
It’s great for multi-account setups, role-based access, and auditing via CloudTrail. If you’re dealing with workplace identities (e.g., employees), use Identity Center. For customer identities (e.g., app users logging in via Google or Facebook), that’s AWS Cognito territory.
IAM Security Tools: Keeping Tabs on Your Mess
AWS gives you tools to avoid screwing yourself:
IAM Credentials Report: Account-level report listing all users and their credential status (e.g., MFA enabled, access key age).
IAM Access Advisor: User-level report showing what services a user accessed and when. Use it to trim bloated permissions.
Policy Evaluation Logic: The Final Boss
When AWS evaluates a request, it follows this brutal logic:
Explicit Deny: Any Deny in any policy (user, group, resource, etc.) kills the request. No mercy.
Service Control Policies (SCPs): If you’re using AWS Organizations, SCPs can deny actions across accounts. If they say no, you’re done.
Resource-Based Policies: If the resource (e.g., S3 bucket) has a policy, it must allow the action, or you’re out.
Permissions Boundaries: If a user or role has a boundary, it must allow the action.
Session Policies: For temporary credentials (e.g., via STS), session policies must allow the action.
Identity-Based Policies: Finally, IAM policies on the user, group, or role are checked. If they allow, you’re in—unless anything above said no.
Best Practices: Don’t Be an Idiot
Lock the root account: Only use it for setup or must-have tasks.
One user per person: No sharing IAM users.
Group up: Assign permissions to groups, not users.
Strong password policy: Enforce complexity and rotation.
MFA everywhere: Root and IAM users. No exceptions.
Use roles: For services, cross-account access, and federation.
Access keys for code: Use them for CLI/SDK, not Console.
Audit regularly: Check Credentials Report and Access Advisor.
Never share credentials: If you do, you deserve the fallout.
Fun Facts to Ruin Your Day
Max 5000 IAM users per account. Got more? Use federation and roles.
Users can be in up to 10 groups. Annoying, right?
Soft limit of 300 groups per account. Beg AWS support to raise it.
Some tasks (e.g., enabling MFA on the root account) require root credentials. Deal with it.
Why You’ll Hate IAM (But Need It Anyway)
IAM is a pain. The JSON policies, the endless ARNs, the deny-always-wins logic—it’s like AWS designed it to make you cry. But without it, your account would be a free-for-all, and you’d be cleaning up a security disaster faster than you can say “S3 bucket exposed.” So, suck it up, learn the ropes, and use IAM to keep your AWS environment locked down. You’ll thank me when you don’t get hacked.
If you can dare, check out other articles in this AWS series: https://learnwithnitesh.hashnode.dev/series/aws
Subscribe to my newsletter
Read articles from Nitesh Chaturvedi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
