AL.
🇪🇸 ES
Back to blog
AWS · 11 min read

AWS IAM Explained: Users, Groups, Policies, MFA, and Best Practices

Learn AWS IAM basics: users, groups, JSON policies, MFA setup, root account security, and the least privilege principle.

AWS IAM — Part 1 of 2


When you first start with AWS, you use your root account for everything. You create EC2 instances, S3 buckets, and Lambda functions all with root credentials. Then someone tells you this is a security nightmare, and you should be using IAM.

But what exactly is IAM? How do users, groups, and policies work? And why is everyone so paranoid about the root account?

In this article, we’ll cover AWS Identity and Access Management (IAM) fundamentals: what it is, why it matters, how to create users and groups, how policies work, and security best practices including MFA and the principle of least privilege.

This is Part 1 of our AWS IAM series. In Part 2, we’ll dive deep into IAM Roles.

What Is IAM and Why It Matters

AWS IAM (Identity and Access Management) is the service that controls who can access what in your AWS account.

Think of it like building security:

  • Root account: Master key that opens everything (dangerous to share)
  • IAM users: Individual key cards for specific people
  • IAM groups: Departments with shared permissions
  • IAM policies: Rules about which doors each key card can open

Without IAM:

  • Everyone uses root credentials (security disaster)
  • No audit trail of who did what
  • Can’t grant limited permissions
  • Can’t enforce MFA
  • Compliance requirements are impossible to meet

With IAM:

  • Each person/service has their own credentials
  • Fine-grained permission control
  • Audit trail of all actions (CloudTrail)
  • MFA enforcement
  • Temporary credentials for services (roles)

Root Account vs IAM Users

The Root Account

When you create an AWS account, you start with a root user. This user:

  • Has complete, unrestricted access to everything
  • Can’t be restricted by policies
  • Can close the account
  • Can change billing information
  • Is identified by your email address

You should almost never use the root account.

IAM Users

IAM users are identities you create within your AWS account:

  • Each user has their own credentials
  • Permissions are controlled by policies
  • Can be audited individually
  • Can be deleted without affecting the account
  • Identified by username

Best practice: Create an IAM user for yourself with admin permissions, then lock away the root account.

Creating Your First IAM User

Via AWS Console

  1. Sign in as root (this time only!)
  2. Go to IAM console
  3. Click “Users” → “Add users”
  4. Enter username (e.g., “john.doe”)
  5. Select AWS access type:
    • AWS Management Console access: For humans (creates password)
    • Programmatic access: For CLI/SDK (creates access key)
  6. Set permissions (we’ll cover this next)
  7. Review and create

Via AWS CLI

First, install and configure the AWS CLI:

aws configure
# Enter your root access key (last time using root!)
# AWS Access Key ID: YOUR_ROOT_ACCESS_KEY
# AWS Secret Access Key: YOUR_ROOT_SECRET_KEY
# Default region: us-east-1
# Default output format: json

Create IAM user:

# Create user
aws iam create-user --user-name john.doe

# Create login profile (console password)
aws iam create-login-profile \
  --user-name john.doe \
  --password 'TempPassword123!' \
  --password-reset-required

# Create access key (programmatic access)
aws iam create-access-key --user-name john.doe

Output:

{
    "AccessKey": {
        "UserName": "john.doe",
        "AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
        "Status": "Active",
        "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        "CreateDate": "2025-09-01T12:00:00Z"
    }
}

Save the SecretAccessKey immediately—you can’t retrieve it later.

IAM Groups

Groups are collections of users with the same permissions. Instead of attaching policies to each user individually, you attach them to the group.

Why Use Groups?

Without groups:

  • Add “S3 read” policy to alice
  • Add “S3 read” policy to bob
  • Add “S3 read” policy to charlie
  • (Repeat for 50 developers… nightmare when you need to update permissions)

With groups:

  • Create “Developers” group with “S3 read” policy
  • Add alice, bob, charlie to group
  • (Update one group to update everyone)

Creating Groups

Via console:

  1. IAM → Groups → Create New Group
  2. Name: “Developers”
  3. Attach policies (we’ll cover next)
  4. Add users to group

Via CLI:

# Create group
aws iam create-group --group-name Developers

# Add user to group
aws iam add-user-to-group --user-name john.doe --group-name Developers

# List groups for a user
aws iam list-groups-for-user --user-name john.doe

Typical Group Structure

Admins
├─ Full administrator access
└─ Members: DevOps team leads

Developers
├─ EC2, Lambda, S3 access
├─ No billing/IAM access
└─ Members: Engineering team

ReadOnly
├─ View-only access
└─ Members: Analysts, auditors

Billing
├─ View and manage billing
└─ Members: Finance team

Users can be in multiple groups:

  • john.doe → Developers + Billing
  • jane.smith → Admins

IAM Policies: How Permissions Work

Policies are JSON documents that define permissions. They answer: “Can this identity do this action on this resource?”

Policy Structure

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}

Components:

  • Version: Policy language version (always “2012-10-17”)
  • Statement: Array of permission statements
  • Effect: “Allow” or “Deny”
  • Action: AWS service action(s)
  • Resource: AWS resource(s) the action applies to

Multiple Actions and Resources

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket/*",
        "arn:aws:s3:::another-bucket/*"
      ]
    }
  ]
}

Wildcards

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",  // All S3 actions
      "Resource": "arn:aws:s3:::*"  // All S3 buckets
    }
  ]
}

Deny Overrides Allow

Explicit deny always wins:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "*"
    },
    {
      "Effect": "Deny",
      "Action": "s3:DeleteBucket",
      "Resource": "*"
    }
  ]
}

This allows all S3 actions except DeleteBucket.

Managed Policies vs Inline Policies

AWS Managed Policies

Pre-built policies created and maintained by AWS:

  • AdministratorAccess: Full access to all AWS services
  • PowerUserAccess: Full access except IAM and billing
  • ReadOnlyAccess: Read-only access to all services
  • AmazonS3FullAccess: Full S3 access
  • AmazonEC2ReadOnlyAccess: Read-only EC2 access

Attach via CLI:

aws iam attach-group-policy \
  --group-name Developers \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess

Pros: Easy, maintained by AWS, best practices built-in Cons: Might grant more permissions than needed

Customer Managed Policies

Custom policies you create and manage:

# Create policy from JSON file
aws iam create-policy \
  --policy-name S3BucketSpecificAccess \
  --policy-document file://policy.json

policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::my-specific-bucket/*"
    }
  ]
}

Attach to group:

aws iam attach-group-policy \
  --group-name Developers \
  --policy-arn arn:aws:iam::123456789012:policy/S3BucketSpecificAccess

Pros: Precise control, least privilege Cons: More work to maintain

Inline Policies

Policies embedded directly in a user, group, or role (not recommended):

aws iam put-user-policy \
  --user-name john.doe \
  --policy-name InlineS3Access \
  --policy-document file://policy.json

Cons: Hard to reuse, hard to track, no versioning When to use: One-off exceptions only

Setting Up MFA (Multi-Factor Authentication)

MFA adds a second factor (something you have) to authentication:

  • Password (something you know)
  • MFA device (something you have)

Even if someone steals your password, they can’t sign in without the MFA device.

MFA for Root Account (Critical!)

  1. Sign in as root
  2. Click account name → Security Credentials
  3. Multi-Factor Authentication → Activate MFA
  4. Choose device type:
    • Virtual MFA (app like Google Authenticator, Authy)
    • Hardware MFA (YubiKey, etc.)
  5. Scan QR code with authenticator app
  6. Enter two consecutive MFA codes
  7. Save recovery codes in a safe place

Never skip this step. A compromised root account = complete account takeover.

MFA for IAM Users

Via console:

  1. IAM → Users → [username]
  2. Security credentials tab
  3. Assigned MFA device → Manage
  4. Follow setup wizard

Via CLI:

# Create virtual MFA device
aws iam create-virtual-mfa-device \
  --virtual-mfa-device-name john-mfa \
  --outfile QRCode.png \
  --bootstrap-method QRCodePNG

# Enable MFA device for user
aws iam enable-mfa-device \
  --user-name john.doe \
  --serial-number arn:aws:iam::123456789012:mfa/john-mfa \
  --authentication-code-1 123456 \
  --authentication-code-2 789012

Enforcing MFA with Policies

Require MFA for sensitive actions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ec2:TerminateInstances",
      "Resource": "*",
      "Condition": {
        "BoolIfExists": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

This allows terminating instances only if MFA is used.

Password Policies

Enforce strong passwords organization-wide:

Via console:

  1. IAM → Account settings
  2. Set password policy:
    • Minimum length: 14 characters
    • Require uppercase, lowercase, numbers, symbols
    • Password expiration: 90 days
    • Prevent password reuse
    • Require admin password reset

Via CLI:

aws iam update-account-password-policy \
  --minimum-password-length 14 \
  --require-symbols \
  --require-numbers \
  --require-uppercase-characters \
  --require-lowercase-characters \
  --max-password-age 90 \
  --password-reuse-prevention 5

The Principle of Least Privilege

Grant only the permissions necessary to perform a task—no more.

Bad Example: Too Much Access

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*"
    }
  ]
}

This is administrator access. Fine for admins, terrible for everyone else.

Good Example: Least Privilege

Developer needs to deploy Lambda functions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "lambda:CreateFunction",
        "lambda:UpdateFunctionCode",
        "lambda:UpdateFunctionConfiguration",
        "lambda:GetFunction"
      ],
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-app-*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iam:PassRole"
      ],
      "Resource": "arn:aws:iam::123456789012:role/lambda-execution-role"
    }
  ]
}

This grants:

  • Lambda function management (only for functions starting with “my-app-”)
  • Permission to assign the execution role
  • Nothing else

How to Apply Least Privilege

  1. Start with no permissions
  2. Grant permissions as needed
  3. Use AWS Access Advisor to see unused permissions
  4. Regularly audit and remove unnecessary permissions

IAM Best Practices Checklist

Here’s a quick reference for IAM security:

Root Account Security

  • Enable MFA on root account
  • Create IAM admin user for daily use
  • Delete root access keys (if they exist)
  • Use root account only for tasks that require it
  • Store root credentials securely (password manager)

Users and Groups

  • Create individual IAM users (never share credentials)
  • Use groups to assign permissions
  • Require MFA for privileged users
  • Rotate credentials regularly
  • Deactivate/delete unused users

Permissions

  • Grant least privilege
  • Use AWS managed policies when appropriate
  • Create customer managed policies for specific needs
  • Avoid inline policies
  • Regularly review permissions with Access Advisor

Password and Access Keys

  • Enforce strong password policy
  • Rotate access keys regularly (every 90 days)
  • Never commit access keys to version control
  • Use IAM roles instead of access keys when possible

Monitoring

  • Enable CloudTrail for audit logging
  • Set up alerts for suspicious activity
  • Review IAM credential report monthly
  • Monitor failed authentication attempts

Checking Your Security Posture

AWS provides tools to assess IAM security:

IAM Credential Report

Download a CSV of all users and their credentials status:

aws iam generate-credential-report
aws iam get-credential-report --output text --query 'Content' | base64 --decode > credentials.csv

Shows:

  • Users with password enabled
  • MFA status
  • Access key age
  • Last password change
  • Last used date

Access Advisor

See which permissions users/groups/roles have used:

aws iam generate-service-last-accessed-details \
  --arn arn:aws:iam::123456789012:user/john.doe

Remove permissions that haven’t been used in 90+ days.

Common IAM Mistakes

1. Using Root Account for Daily Tasks

Never do this. Create an admin IAM user instead.

2. Sharing Credentials

Each person should have their own IAM user.

3. Embedding Access Keys in Code

# Bad!
aws_access_key = "AKIAIOSFODNN7EXAMPLE"
aws_secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

Use IAM roles (covered in Part 2) or environment variables.

4. Overly Permissive Policies

Don’t use "Action": "*" unless absolutely necessary.

5. Not Enabling MFA

MFA prevents 99% of account compromises.

Conclusion

IAM is the foundation of AWS security. Without proper IAM configuration, everything else you build is vulnerable.

In this part, we covered:

  • Root account vs IAM users
  • Creating users and groups
  • How IAM policies work (JSON structure)
  • Managed vs inline policies
  • MFA setup and enforcement
  • Password policies
  • The principle of least privilege
  • Security best practices

In Part 2, we’ll dive deep into IAM Roles: how they work, when to use them, and how they enable secure service-to-service communication without credentials.

Stay secure, and remember: when in doubt, grant less permission. You can always add more later.