Part of my AWS learning journey — transitioning from Systems Engineer to Cloud/DevOps. This session goes deep into IAM — the access control system that governs who can do what across every AWS service.
📋 Topics Covered
| # | Topic | Type |
|---|---|---|
| 1 | Why IAM — The AAA Framework | Concept + Interview |
| 2 | Root User vs IAM User | Concept + Interview |
| 3 | Multi-Factor Authentication Setup | Concept + Lab |
| 4 | IAM Users | Concept + Lab |
| 5 | IAM Groups | Concept + Lab |
| 6 | IAM Roles & Service Principals | Concept + Lab + Interview |
| 7 | Trust Policy & Role Switching | Concept + Interview |
| 8 | IAM Permissions — Syntax & Policies | Concept + Cert |
| 9 | Policy Types — Identity-Based & Resource-Based | Concept + Cert |
| 10 | SCP — The Ceiling Above IAM | Concept + Interview |
| 11 | ARN — Amazon Resource Name | Concept + Lab |
| 12 | IAM Instance Profile | Concept + Lab + Interview |
| 13 | IAM Identity Centre | Concept + DevOps |
| 14 | EC2 Basics — Brief Introduction | Concept + Lab |
| 15 | Lab 1 — Service Principal Creation, Access Between Services | Lab |
| 16 | Lab 2 — Create User, Roles, Groups | Lab |
| 17 | Lab 3 — IAM Instance Profile → EC2 Access S3 | Lab |
Why IAM Exists — The AAA Framework
When you first create an AWS account, you get a Root user — zero restrictions, can delete everything, rack up unlimited bills. Real teams have multiple people: developers, DevOps engineers, auditors, managers. You don't want everyone using the same all-powerful Root account. You need controlled, tracked, individual access. That's what IAM solves.
IAM answers one fundamental question: Who can do what, on which AWS resource — and is it being recorded?
That question maps to a universal security framework called AAA:
| Pillar | Question It Answers | How AWS Implements It |
|---|---|---|
| Authentication | Who are you? | Username + Password + MFA |
| Authorization | What can you do? | IAM Policies and Roles |
| Accounting | What did you do? | AWS CloudTrail (full audit logs) |
When you log into AWS and try to start an EC2 instance — AWS verifies your identity, checks if you're allowed to start EC2, and logs that you did it. Every single time, all three happen.
Root User vs IAM User
| Root User | IAM User | |
|---|---|---|
| Created | When you open AWS account | By Root or an admin |
| Access | Unrestricted — everything | Only what policies allow |
| Can be restricted? | ❌ No | ✅ Yes |
| Use for | Initial setup only, billing emergencies | All daily tasks |
| MFA | Enable immediately | Strongly recommended |
The rule is simple:
Root = lock it away with MFA, use only for account-level emergencies.
IAM User = what you actually log in with every day.
Multi-Factor Authentication (MFA)
A password alone isn't enough. If someone gets your password, they're in. MFA adds a second factor — a time-based OTP from your phone — so even a stolen password is useless without the physical device.
| Type | How It Works | When to Use |
|---|---|---|
| Virtual MFA | Google Authenticator / Authy app — TOTP on your phone | ✅ Default choice for learning |
| Hardware MFA | Physical YubiKey device | ✅✅ Best for Root account |
| SMS/Voice | OTP via text message | ⚠️ Weakest — avoid if possible |
Steps to enable MFA:
IAM Console → Security Credentials → Assign MFA Device → choose Authenticator app → scan QR code with Google Authenticator / Authy → enter two consecutive 6-digit codes → Add MFA ✅
Always enable MFA on Root first — then on your IAM user as well.
IAM Users
An IAM User is an identity for a specific person or application. Unlike Root, it starts with zero permissions — it can log in but cannot access any service until policies are attached.
Creating an IAM User:
IAM Console → Users → Create User → set username → enable Console access + set password → (Optional) add tags → attach policy directly or add to a group → Done ✅
One important note: an IAM user with permission to create users can create more IAM users. Permissions propagate — be deliberate about what you give.
IAM Groups — Managing at Scale
Imagine you have 10 developers. Attaching policies to each one individually is painful and error-prone. Groups solve this.
A Group is a collection of IAM users. Attach a policy to the group once — every user in it inherits those permissions automatically.
Group: DevOpsTeam → Policy: PowerUserAccess
User: tejas → gets PowerUserAccess ✅
User: ravi → gets PowerUserAccess ✅
User: priya → gets PowerUserAccess ✅Add a new team member → add to group → done.
Remove someone → remove from group → done.
Key rules:
- One user can belong to multiple groups
- Groups cannot contain other groups (no nesting)
- Default quota: 300 groups per account
Creating via Group — the cleaner approach:
Create IAM Group → Attach policy to group → Create IAM User → Add user to group → User inherits group's permissions automatically ✅
IAM Roles & Service Principals
An IAM Role is a temporary identity with permissions — no username, no password. It's meant to be assumed — picked up temporarily by a user or an AWS service, used, and then dropped.
Analogy: A Role is like a visitor badge at an office. A visitor picks up the badge at reception (assumes the role), gets access to specific floors (permissions), and returns the badge when done (session ends). No permanent access. No long-term credentials.
IAM User vs IAM Role
| IAM User | IAM Role | |
|---|---|---|
| Has password? | ✅ Yes | ❌ No |
| Permanent? | ✅ Yes | ❌ Temporary (assumed) |
| For? | Human beings | Services or temporary access |
| Credentials | Long-term | Short-term, auto-rotated |
Service Principal
A Service Principal is the identity of an AWS service — used in Trust Policies to allow services like EC2 or Lambda to assume a role.
Common service principals:
-
ec2.amazonaws.com— EC2 can assume this role -
lambda.amazonaws.com— Lambda can assume this role -
s3.amazonaws.com— S3 can assume this role
When you want EC2 to access S3 automatically (without hardcoding credentials), you create a role with ec2.amazonaws.com as the trusted service principal and attach S3 permissions to it. Then attach that role to EC2 — EC2 can now talk to S3 with zero credentials in your code.
Trust Policy & Role Switching
Every IAM Role has two parts:
- Permission Policy — what the role is allowed to do
- Trust Policy — who is allowed to assume this role
Trust Policy example — allowing a specific IAM user to assume a role:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/tejas"
},
"Action": "sts:AssumeRole"
}]
}
Role switching — what actually happens:
Step 1: Create a Role with AmazonS3FullAccess permission
Step 2: By default, nobody can assume it — IAM user tries to switch → fails ❌
Step 3: Edit the Trust Policy → add your IAM user's ARN as a trusted principal
Step 4: Switch Role from Console top-right → enter Account ID + Role name → now operating AS the role
Step 5: You can now access S3 ✅ — but your original EC2 permissions are SUSPENDED for this session
Step 6: Switch back → back to your original IAM user permissions → S3 access gone
That EC2 access disappearing when you switched to the S3 role wasn't a bug — it's exactly how role switching works. The role's permissions replace your current ones for the duration of the session.
IAM Permissions — Syntax & Policies
A Policy is a JSON document that defines exactly what is allowed or denied. Every AWS request is checked against applicable policies to decide: allow or deny?
Basic policy structure:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::my-bucket/*"
}]
}
| Field | What It Means |
|---|---|
Effect |
Allow or Deny
|
Action |
Which API operation (e.g. s3:GetObject, ec2:*) |
Resource |
Which specific resource (by ARN) |
Condition |
Optional — e.g. "only if MFA is active" |
The evaluation rule that matters most:
Explicit Deny → always wins, overrides everything
No Policy → denied by default (implicit deny)
Explicit Allow → access granted, unless a Deny exists somewhere
Combined permissions — how AWS evaluates multiple sources:
User has AmazonEC2FullAccess (direct policy) + Group has ReadOnlyAccess
Result: EC2 Full Access + ReadOnly on everything else (more permissive wins — unless there's an explicit Deny)
Policy Types — Identity-Based & Resource-Based
Identity-Based Policy
- Attached to: IAM user, group, or role
- Says: "This identity can perform these actions"
- No
Principalfield — the identity it's attached to is the principal - Example: AmazonEC2FullAccess attached to an IAM user
Resource-Based Policy
- Attached to: a resource (S3 bucket, SQS queue, etc.)
- Says: "These identities are allowed to access me"
- Has a
Principalfield — explicitly names who can access - Example: S3 bucket policy allowing a specific IAM user to read objects
{
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789:user/tejas"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}]
}
SCP — The Ceiling Above IAM
SCP = Service Control Policy — part of AWS Organizations, used when managing multiple AWS accounts together.
| IAM Policy | SCP | |
|---|---|---|
| Attached to | Users, Groups, Roles | AWS Accounts / Organizational Units |
| Does it grant permissions? | ✅ Yes | ❌ No — only limits |
| Can it restrict Root? | ❌ No | ✅ Yes |
| Who uses it? | Everyone | Enterprises with multiple accounts |
SCP defines the maximum permissions possible in an account. IAM policies still need to grant actual access — but they can never exceed what SCP allows.
Example: SCP says "no S3 access in this account." Even if an IAM policy gives a user S3FullAccess, they still can't access S3. SCP wins.
💡 SCP is enterprise-scale. Keep it in mind — it comes up in architecture interviews and the SAA-C03 exam.
ARN — Amazon Resource Name
ARN = Amazon Resource Name. Every single resource in AWS has a globally unique ARN.
Format:
arn:aws:SERVICE:REGION:ACCOUNT-ID:RESOURCE
Examples:
arn:aws:iam::123456789012:user/tejas → IAM User
arn:aws:iam::123456789012:role/S3AccessRole → IAM Role
arn:aws:s3:::my-bucket → S3 Bucket
arn:aws:ec2:ap-south-1:123456789:instance/i-abc → EC2 Instance
ARNs appear in trust policies, resource-based policies, CloudTrail logs, and anywhere a specific resource needs to be uniquely referenced.
IAM Instance Profile
An Instance Profile is a container that wraps an IAM Role and delivers it to an EC2 instance — giving EC2 automatic, temporary, rotating credentials through the AWS Metadata Service.
Why this matters — the right vs wrong approach:
Wrong approach ❌ — hardcoded keys in code:
aws_access_key_id = 'AKIAIOSFODNN7EXAMPLE' aws_secret_access_key = 'wJalrXUt...'If this code goes to GitHub, your keys are exposed immediately. Bots scan GitHub 24/7.
Right approach ✅ — IAM Instance Profile:
IAM Role → Instance Profile → EC2 Instance → AWS Metadata Service (169.254.169.254) → Temporary credentials (auto-rotated every hour) → Access S3 ✅ — zero hardcoded keys, zero manual rotation
The Instance Profile is created automatically when you attach a role to EC2 via the Console — you don't create it separately. One profile holds exactly one role.
IAM Identity Centre
IAM Identity Centre (formerly AWS SSO — Single Sign-On) is AWS's centralized identity management service for organizations with multiple AWS accounts.
The problem it solves:
Without IAM Identity Centre: each developer needs a separate IAM user in every AWS account they work with — dev account, staging account, prod account. Managing credentials across 10+ accounts becomes a nightmare.
With IAM Identity Centre: one login, one set of credentials → access to multiple AWS accounts and applications based on assigned permission sets. Log in once via the Identity Centre portal, click the account you need, you're in.
Key concepts:
| Concept | What It Is |
|---|---|
| Permission Set | A collection of policies defining access level (like an IAM role, but managed centrally) |
| Identity Source | Where users come from — can be AWS's own directory, Active Directory, or an external IdP (Okta, Azure AD) |
| Assignment | Linking a user/group to a specific AWS account with a specific Permission Set |
| SSO Portal URL | The login page your organization's employees use to access all accounts |
Who uses it: Any organization with multiple AWS accounts — and that's most serious organizations. A company might have separate accounts for dev, staging, prod, security, and logging. IAM Identity Centre manages access across all of them from one place.
🎯 DevOps relevance: In production environments, you'll rarely create individual IAM users anymore. Identity Centre + corporate directory (Active Directory/Okta) is the standard. Users log in with their company credentials and get federated access to AWS accounts — no AWS-specific passwords to manage.
EC2 Basics — Brief Introduction
This session introduced EC2 as part of the IAM Instance Profile lab. Full EC2 coverage is in Session 4 — here's what you need for the labs:
AMI (Amazon Machine Image) — the OS template used to launch EC2. Amazon Linux 2, Ubuntu 22.04, Windows Server are all AMIs. Region-specific — must copy to use in another Region.
Instance Type — CPU and RAM configuration. t2.micro = 1 vCPU, 1 GB RAM — Free Tier eligible.
Key Pair — used to SSH into EC2 without a password. AWS keeps the public key on EC2. You download the private .pem file. Download once — if lost, SSH access is gone permanently.
Security Group — virtual firewall. Port 22 for SSH, Port 80 for HTTP.
User Data — a script that runs once automatically on first boot:
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hello from EC2!</h1>" > /var/www/html/index.html
EC2 Launch Flow (used in labs):
EC2 Console → Launch Instance → Name → AMI (Amazon Linux 2) → Instance Type (t2.micro) → Key Pair (create + download .pem) → Security Group (SSH 22 + HTTP 80) → Storage (8 GB default) → User Data (optional script) → Launch → wait 2 min → Running ✅
🧪 Lab 1 — Service Principal Creation & Access Between Services
Objective: Create an IAM Role using a Service Principal so EC2 can access S3 without hardcoded credentials.
Step 1: IAM Console → Roles → Create Role
Trusted entity type: AWS Service → EC2
(This setsec2.amazonaws.comas the Service Principal in the Trust Policy)Step 2: Attach permission policy → AmazonS3FullAccess
Step 3: Name the role:
EC2-S3-FullAccess-Role→ Create RoleStep 4: Launch an EC2 instance → Advanced Details → IAM Instance Profile → select
EC2-S3-FullAccess-Role
(Or on an existing instance: Actions → Security → Modify IAM Role → select the role → Update)Step 5: SSH into the EC2 instance
Step 6: Run
aws s3 ls
Expected output: list of your S3 buckets ✅ — zero credentials configured on the instance
What just happened: EC2 called the Metadata Service at 169.254.169.254, received temporary credentials from the Instance Profile, used them to authenticate with S3. All automatic. All secure.
🧪 Lab 2 — Create User, Roles, Groups
Objective: Create the full IAM structure — group with policy, user in group, role with trust policy, role switching.
Part A — Group + User:
IAM Console → User Groups → Create group
Name:DevOpsTeam
Attach policy:PowerUserAccess
Create group ✅IAM Console → Users → Create user
Username:dev-user-1
Enable console access → set password
Add user to group:DevOpsTeam
Create user ✅ → download credentials CSVLog in as
dev-user-1via IAM sign-in URL → verify PowerUserAccess is active
Part B — Role + Trust Policy + Switching:
IAM Console → Roles → Create role
Trusted entity type: AWS Account → This account
Attach policy:AmazonS3FullAccess
Name:S3AccessRole→ Create role ✅Open
S3AccessRole→ Trust relationships → Edit trust policy
Add your IAM user's ARN as a Principal:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::YOUR_ACCOUNT_ID:user/dev-user-1"
},
"Action": "sts:AssumeRole"
}]
}
Log in as
dev-user-1→ top-right → Switch Role → enter Account ID +S3AccessRole
Verify: S3 access works ✅
Verify: EC2 access is suspended (role replaced your permissions) ✅
Switch back → original PowerUserAccess restored ✅
🧪 Lab 3 — IAM Instance Profile → EC2 Access S3
Objective: Create an EC2 instance with an Instance Profile that gives it read access to S3, then verify from inside the instance.
Step 1: Create S3 bucket with a test file
S3 Console → Create bucket → name:iam-lab-test-bucket-2026→ uploadtest.txtStep 2: Create IAM Role for EC2
IAM → Roles → Create Role → AWS Service → EC2
Policy:AmazonS3ReadOnlyAccess
Name:EC2-S3-ReadOnly-RoleStep 3: Launch EC2 with Instance Profile
EC2 → Launch Instance → Amazon Linux 2 → t2.micro → Key Pair
Advanced Details → IAM instance profile →EC2-S3-ReadOnly-Role
Security Group: SSH (22) from My IP → LaunchStep 4: SSH into EC2 and verify S3 access
ssh -i your-key.pem ec2-user@<public-ip>
# List S3 buckets — should work with no credentials configured
aws s3 ls
# Download the test file
aws s3 cp s3://iam-lab-test-bucket-2026/test.txt .
cat test.txt
# Try to write — should fail (ReadOnly policy)
aws s3 cp test.txt s3://iam-lab-test-bucket-2026/write-test.txt
# Expected: AccessDenied ✅ (ReadOnly policy working correctly)
⚡ Quick Revision
AAA Framework
- Authentication → Who are you? (credentials + MFA)
- Authorization → What can you do? (IAM Policies)
- Accounting → What did you do? (CloudTrail)
Permission Hierarchy
- SCP (Organizations) → ceiling, limits max permissions, can restrict Root
- IAM Policies → actual grants within that ceiling
- Explicit Deny → always wins over everything
IAM Building Blocks
- User → permanent identity, has password, for humans
- Group → collection of users, attach policy once, inherited by all members
- Role → temporary identity, no password, assumed by users or services
- Policy → JSON document defining Allow/Deny on specific resources
- ARN → unique ID for every AWS resource
Role Switching
- Add user ARN to role's Trust Policy → user can now switch
- Switching: role permissions replace your current permissions for that session
- Switch back → original permissions restored
Instance Profile (EC2 → S3)
- Create Role with Service Principal
ec2.amazonaws.com+ S3 policy - Attach to EC2 via Instance Profile
- EC2 gets auto-rotating temp credentials from Metadata Service
- Zero hardcoded credentials in code or on disk
SCP vs IAM
- IAM: grants permissions within an account
- SCP: limits maximum permissions across accounts, overrides everything including Root
IAM Identity Centre
- One login → multiple AWS accounts
- Uses Permission Sets (managed role bundles) assigned per account per user/group
- Integrates with corporate directories (Active Directory, Okta, Azure AD)
- Standard for multi-account enterprise environments
💼 Interview Questions
Q1: What is the difference between an IAM User and an IAM Role?
An IAM User has permanent credentials (username + password) for a human being. An IAM Role has no password — it provides temporary credentials assumed by users or AWS services. Roles are the correct approach for service-to-service communication.
Q2: What is a Trust Policy and why is it needed?
A Trust Policy is a JSON document on an IAM Role that defines who is allowed to assume it. Without a Trust Policy, nobody can use the role — not even admins. You explicitly add trusted principals (IAM user ARNs or service principals like ec2.amazonaws.com).
Q3: What happens when you switch roles in AWS Console?
Your current IAM user permissions are temporarily suspended and fully replaced by the role's permissions for that session. When you switch back, your original permissions are restored. This is why EC2 access disappears when you switch to an S3-only role.
Q4: What is an IAM Instance Profile and why use it instead of access keys?
An Instance Profile is a container that delivers an IAM Role to an EC2 instance. EC2 automatically receives temporary, rotating credentials from the AWS Metadata Service — no hardcoded keys anywhere. This is far safer than embedding access keys in code, which can be accidentally exposed via Git repositories.
Q5: What is the difference between SCP and IAM policies?
IAM policies grant permissions to users, groups, or roles within an account. SCPs (Service Control Policies) sit above IAM at the Organizations level and define the maximum permissions allowed in an account — they restrict, not grant. Even the Root user is subject to SCPs.
Q6: An IAM user has EC2FullAccess directly and ReadOnlyAccess via their group. What's their effective permission?
They get EC2 Full Access combined with ReadOnly on everything else. AWS combines all Allow permissions from all sources. However, if an Explicit Deny exists anywhere — in any policy, including an SCP — it overrides all Allows.
Q7: What is IAM Identity Centre and when would an organization use it?
IAM Identity Centre is AWS's centralized identity management service. It lets users log in once with one set of credentials (optionally from a corporate directory like Active Directory or Okta) and access multiple AWS accounts via assigned Permission Sets — without separate IAM users per account. Organizations use it whenever they have more than one AWS account and want centralized, governed access management.
Q8: Your EC2 instance returns AccessDenied when calling DynamoDB. What do you check first?
Check the IAM Role attached to the EC2 instance via its Instance Profile. Verify the role has the required DynamoDB permissions (dynamodb:GetItem, dynamodb:PutItem, etc.) on the correct table ARN. Missing or incorrect permissions on the Execution Role is the most common cause of AccessDenied errors from EC2 or Lambda calling other AWS services.
🔬 Practice Tasks
Create an IAM Group called
DevOpsTeam, attachPowerUserAccess, create a user and add them to the group. Log in as that user and verify you can access EC2 but not billing (billing is Root-only by default).Create an IAM Role with
AmazonS3ReadOnlyAccess. Edit its Trust Policy to add your IAM user's ARN. Switch to that role from the Console. Verify S3 access works — verify EC2 access is suspended while the role is active. Switch back and confirm EC2 access returns.Explore the
AmazonEC2FullAccesspolicy JSON in IAM Console. Find whatec2:*means. Identify 3 specific actions it covers (e.g.,ec2:StartInstances,ec2:DescribeInstances,ec2:TerminateInstances).Complete Lab 3 above — EC2 Instance Profile with S3 ReadOnly access. Verify you can list and download from S3, then try to upload and confirm you receive AccessDenied. This proves the Least Privilege principle is working.
Create an IAM Role for EC2 with only
AmazonS3FullAccess. Try to runaws ec2 describe-instancesfrom inside the EC2 instance — confirm it returns AccessDenied. This demonstrates that the Instance Profile only gives what the role allows — nothing more.
AWS Session 3 — IAM Essentials | Cloud + DevOps learning journey — Systems Engineer → Cloud/DevOps Engineer
Top comments (0)