Fatskills
Practice. Master. Repeat.
Study Guide: TECH **AWS IAM Users, Groups, Roles & Policies: Zero-Fluff, Hands-On Study Guide**
Source: https://www.fatskills.com/aws-certified-solutions-architect-associate/chapter/tech-aws-iam-users-groups-roles-policies-zero-fluff-hands-on-study-guide

TECH **AWS IAM Users, Groups, Roles & Policies: Zero-Fluff, Hands-On Study Guide**

By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.

⏱️ ~9 min read

AWS IAM Users, Groups, Roles & Policies: Zero-Fluff, Hands-On Study Guide

(For AWS Solutions Architect – Associate & Real-World Production)


1. What This Is & Why It Matters

You’re a cloud engineer at a fintech startup. Your team just migrated a monolithic app to AWS, and now every developer, CI/CD pipeline, and Lambda function needs access to AWS services—but no one should have more permissions than absolutely necessary. If you get IAM wrong: - Security breach: A junior dev accidentally deletes a production DynamoDB table because their IAM user had dynamodb:* permissions.
- Downtime: Your CI/CD pipeline fails because the IAM role attached to the EC2 runner lacks s3:GetObject for deployment artifacts.
- Cost explosion: A misconfigured IAM policy grants ec2:RunInstances to a test account, and someone spins up 100 p3.8xlarge instances overnight.

IAM is the gatekeeper of AWS. It controls who (users, services) can do what (actions) on which resources. Mastering IAM means: ✅ Least privilege: No "god mode" permissions—only what’s needed.
Scalability: Manage 100+ users without manually attaching policies to each.
Auditability: Track who did what (CloudTrail) and rotate credentials automatically.
Automation: Grant temporary access to services (e.g., Lambda, EC2) without hardcoding keys.

Real-world scenario: You inherit a legacy AWS account where: - The root user is used for daily tasks.
- Developers share a single IAM user with admin permissions.
- EC2 instances have hardcoded AWS keys in their ~/.aws/credentials file.
Your mission: Refactor IAM to be secure, scalable, and auditable—without breaking production.


2. Core Concepts & Components


? IAM User

  • Definition: A person or application with long-term AWS credentials (access key + secret key).
  • Production insight: ⚠️ Never use the root user for daily tasks. Create IAM users for humans and services. Rotate access keys every 90 days.

? IAM Group

  • Definition: A collection of IAM users. Policies attached to a group apply to all its members.
  • Production insight: Use groups to manage permissions at scale (e.g., Developers, Admins, ReadOnly). Avoid attaching policies directly to users.

? IAM Role

  • Definition: A temporary identity for AWS services (EC2, Lambda, ECS) or federated users (SAML, OIDC). No long-term credentials.
  • Production insight: Always use roles for AWS services (e.g., EC2, Lambda). Hardcoding keys in code is a security anti-pattern.

? IAM Policy

  • Definition: A JSON document defining permissions (e.g., "Allow s3:GetObject on arn:aws:s3:::my-bucket/*").
  • Production insight: Least privilege > convenience. Start with Deny by default, then explicitly Allow what’s needed.

? Managed Policy

  • Definition: AWS-predefined policies (e.g., AmazonS3ReadOnlyAccess). Can’t be modified.
  • Production insight: Use managed policies for common use cases (e.g., AWSLambdaBasicExecutionRole). Avoid reinventing the wheel.

? Inline Policy

  • Definition: A policy embedded directly into a user, group, or role. Not reusable.
  • Production insight: Use inline policies for one-off exceptions (e.g., a single user needs extra permissions). Prefer managed policies for consistency.

? Trust Policy

  • Definition: Defines who can assume a role (e.g., "Allow EC2 instances in account 123456789012 to assume this role").
  • Production insight: Critical for cross-account access (e.g., a dev account assuming a role in prod). Always restrict the Principal to specific accounts/ARNs.

? Permission Boundary

  • Definition: A cap on the maximum permissions a user/role can have, even if their policies allow more.
  • Production insight: Use permission boundaries to delegate IAM administration safely (e.g., let a team manage their own users but limit them to s3:* only).

? Identity Provider (IdP)

  • Definition: External identity source (e.g., Active Directory, Google Workspace) that federates into AWS via SAML/OIDC.
  • Production insight: Avoid creating IAM users for employees. Use SSO (e.g., AWS SSO, Okta) for centralized access.


3. Step-by-Step Hands-On: Secure IAM for a Production App


Prerequisites

  • AWS account with admin IAM permissions (not root!).
  • AWS CLI installed (aws --version).
  • A test app (e.g., a Lambda function + S3 bucket).

Goal

Refactor IAM for a serverless app (API Gateway + Lambda + DynamoDB) to follow least privilege. Current state: - Lambda uses a hardcoded access key in its environment variables.
- Developers share an IAM user with AdministratorAccess.
- No groups or roles exist.

Step 1: Create IAM Groups for Team Roles

# Create groups for developers, admins, and read-only users
aws iam create-group --group-name Developers
aws iam create-group --group-name Admins
aws iam create-group --group-name ReadOnly

# Attach managed policies to groups
aws iam attach-group-policy --group-name Developers --policy-arn arn:aws:iam::aws:policy/PowerUserAccess
aws iam attach-group-policy --group-name Admins --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
aws iam attach-group-policy --group-name ReadOnly --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess

Verify:


aws iam list-attached-group-policies --group-name Developers

Expected output:


{
  "AttachedPolicies": [
{
"PolicyName": "PowerUserAccess",
"PolicyArn": "arn:aws:iam::aws:policy/PowerUserAccess"
} ] }


Step 2: Create IAM Users and Add to Groups

# Create a developer user (no console access)
aws iam create-user --user-name alice-dev
aws iam add-user-to-group --user-name alice-dev --group-name Developers

# Create an admin user (with console access)
aws iam create-user --user-name bob-admin
aws iam create-login-profile --user-name bob-admin --password TempPass123! --password-reset-required
aws iam add-user-to-group --user-name bob-admin --group-name Admins

# Generate access keys for alice-dev (for CLI/SDK)
aws iam create-access-key --user-name alice-dev > alice-dev-keys.json

⚠️ Security note: Never commit alice-dev-keys.json to Git. Use AWS Secrets Manager or ~/.aws/credentials instead.


Step 3: Replace Hardcoded Keys with an IAM Role for Lambda

  1. Create a role for Lambda:
    bash
    aws iam create-role --role-name LambdaDynamoDBRole --assume-role-policy-document file://trust-policy.json

    trust-policy.json:
    json
    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Effect": "Allow",
    "Principal": {
    "Service": "lambda.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
    }
    ]
    }

  2. Attach a policy to the role:
    bash
    aws iam attach-role-policy --role-name LambdaDynamoDBRole --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
    aws iam put-role-policy --role-name LambdaDynamoDBRole --policy-name DynamoDBAccess --policy-document file://dynamodb-policy.json

    dynamodb-policy.json (least privilege):
    json
    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Effect": "Allow",
    "Action": [
    "dynamodb:GetItem",
    "dynamodb:PutItem",
    "dynamodb:UpdateItem"
    ],
    "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/MyAppTable"
    }
    ]
    }

  3. Update Lambda to use the role:

  4. In the AWS Console, go to Lambda > Your Function > Configuration > Permissions.
  5. Under Execution role, select LambdaDynamoDBRole.
  6. Delete the hardcoded access key from environment variables.

Verify:


aws lambda get-function --function-name MyLambdaFunction | jq '.Configuration.Role'

Expected output:


"arn:aws:iam::123456789012:role/LambdaDynamoDBRole"


Step 4: Enable MFA for Admin Users

# Enable MFA for bob-admin
aws iam enable-mfa-device --user-name bob-admin --serial-number arn:aws:iam::123456789012:mfa/bob-admin --authentication-code1 123456 --authentication-code2 789012

⚠️ Note: Replace 123456 and 789012 with codes from your MFA device (e.g., Google Authenticator).

Verify:


aws iam list-mfa-devices --user-name bob-admin


Step 5: Set a Permission Boundary for Developers

# Create a permission boundary policy
aws iam create-policy --policy-name DeveloperBoundary --policy-document file://boundary-policy.json

boundary-policy.json:


{
  "Version": "2012-10-17",
  "Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*",
"dynamodb:*",
"lambda:*"
],
"Resource": "*"
} ] } # Attach the boundary to the Developers group aws iam put-group-policy --group-name Developers --policy-name DeveloperBoundary --policy-document file://boundary-policy.json

Why this matters: Even if a developer attaches AdministratorAccess to their user, the boundary caps their permissions to s3:*, dynamodb:*, and lambda:*.


4. ? Production-Ready Best Practices


Security

  • Least privilege: Start with Deny in policies, then explicitly Allow what’s needed.
  • MFA everywhere: Enforce MFA for all human users (especially admins).
  • No hardcoded keys: Use IAM roles for AWS services (EC2, Lambda, ECS).
  • Rotate credentials: Set a 90-day rotation policy for access keys.
  • Audit trails: Enable AWS CloudTrail to log all IAM actions.

Cost Optimization

  • Avoid over-provisioning: Don’t grant * permissions when s3:GetObject suffices.
  • Use managed policies: They’re free and maintained by AWS.

Reliability & Maintainability

  • Naming conventions: Prefix roles with their service (e.g., LambdaDynamoDBRole, EC2S3ReadRole).
  • Tagging: Tag IAM resources (e.g., Environment=Prod, Team=Backend).
  • Idempotency: Use Terraform/CloudFormation to manage IAM (avoid manual changes).

Observability

  • Monitor unused credentials: Use IAM Access Analyzer to find unused roles/users.
  • Set CloudWatch alarms: Alert on CreateAccessKey, DeleteUser, or AttachUserPolicy events.


5. ⚠️ Common Mistakes & Traps

Mistake Symptom Fix/Prevention
Using root user for daily tasks CloudTrail logs show root making changes. Security audit fails. Create IAM users for all humans. Enable MFA on root.
Hardcoding access keys in code GitHub repo leaks keys. Lambda fails with InvalidClientTokenId. Use IAM roles for AWS services. Store keys in Secrets Manager.
Granting * permissions A dev accidentally deletes a production S3 bucket. Start with Deny in policies. Use AWS Policy Generator for least privilege.
Not using groups 100+ users with manually attached policies. Hard to audit. Create groups (e.g., Developers, Admins) and attach policies to groups.
Ignoring permission boundaries A dev escalates privileges by attaching AdministratorAccess to their user. Set permission boundaries for groups/users.
Not rotating access keys A leaked key from 2020 is still active. Set a 90-day rotation policy. Use aws iam list-access-keys to audit.


6. ? Exam/Certification Focus


Typical Question Patterns

  1. Least privilege:
  2. "A Lambda function needs to read from an S3 bucket. Which policy should you attach?"


    • AmazonS3ReadOnlyAccess (managed policy).
    • AdministratorAccess (overkill).
  3. IAM roles vs. users:

  4. "An EC2 instance needs to write to DynamoDB. Should you use an IAM user or role?"


    • Role (temporary credentials, no keys to manage).
    • ❌ User (requires hardcoded keys).
  5. Cross-account access:

  6. "Account A needs to assume a role in Account B. What must you configure?"


    • Trust policy in Account B’s role allowing Account A as Principal.
    • IAM policy in Account A allowing sts:AssumeRole.
  7. MFA enforcement:

  8. "How do you enforce MFA for all IAM users?"
    • IAM policy with aws:MultiFactorAuthPresent: true condition.
    • ❌ "Just tell users to enable MFA" (not enforceable).

⚠️ Trap Distinctions

Concept Key Difference
IAM User vs. Role Users = long-term credentials (humans/apps). Roles = temporary (AWS services).
Managed vs. Inline Policy Managed = reusable (AWS or custom). Inline = embedded in user/group/role.
Trust Policy vs. Permission Policy Trust = who can assume the role. Permission = what the role can do.
Permission Boundary Caps maximum permissions (even if policies allow more).

Scenario-Based Question

"You need to grant a third-party vendor read-only access to an S3 bucket for 24 hours. What’s the most secure way?" - ✅ Create an IAM role with a trust policy allowing the vendor’s AWS account to assume it, and attach a policy granting s3:GetObject. Set a 24-hour session duration.
- ❌ "Create an IAM user and share the access key" (long-term credentials, hard to revoke).
- ❌ "Grant s3:* to the vendor’s account" (over-permissive).


7. ? Hands-On Challenge

Challenge: A developer (alice-dev) needs to deploy a Lambda function but gets AccessDenied when trying to create a CloudWatch Logs group. Fix the IAM permissions without granting AdministratorAccess.

Solution: 1. Attach the managed policy AWSLambdaBasicExecutionRole to alice-dev:
bash
aws iam attach-user-policy --user-name alice-dev --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
2. Why it works: This policy grants logs:CreateLogGroup, logs:CreateLogStream, and logs:PutLogEvents—exactly what Lambda needs for logging.


8. ? Rapid-Reference Crib Sheet

Command/Concept Example/Notes
Create IAM user aws iam create-user --user-name alice
Create IAM group aws iam create-group --group-name Developers
Attach policy to group aws iam attach-group-policy --group-name Developers --policy-arn arn:aws:iam::aws:policy/PowerUserAccess
Create IAM role aws iam create-role --role-name LambdaRole --assume-role-policy-document file://trust-policy.json
Assume role (CLI) aws sts assume-role --role-arn arn:aws:iam::123456789012:role/LambdaRole --role-session-name TestSession
List attached policies aws iam list-attached-user-policies --user-name alice
Enable MFA aws iam enable-mfa-device --user-name alice --serial-number arn:aws:iam::123456789012:mfa/alice --authentication-code1 123456 --authentication-code2 789012
Permission boundary aws iam put-user-policy --user-name alice --policy-name Boundary --policy-document file://boundary-policy.json
⚠️ Default IAM policy No permissions by default (explicit Deny).
⚠️ Root user Full access. Never use for daily tasks.
⚠️ IAM policy evaluation Explicit Deny > Explicit Allow > Default Deny.


9. ? Where to Go Next

  1. AWS IAM Best Practices – Official guide.
  2. AWS Policy Generator – Build least-privilege policies.
  3. IAM Access Analyzer – Find unused permissions.
  4. AWS Well-Architected Framework – Security Pillar – IAM in the context of broader security.


ADVERTISEMENT