DEV Community

Cover image for AWS IAM Mistakes That Can Destroy Your Infrastructure
Prashik besekar
Prashik besekar

Posted on

AWS IAM Mistakes That Can Destroy Your Infrastructure

I almost made mistake #3. It would have exposed my entire AWS account to the internet.


The Day I Realized IAM Was Serious

When I first started learning AWS I thought IAM was boring.

EC2 was exciting. S3 was cool. Lambda felt like magic.

But IAM? Just users and permissions. Snooze. 😓

Then one day while reviewing my AWS account I found something terrifying — my root account had been used to create access keys. Those keys were sitting in my code. My code was on GitHub.

Public GitHub.

My entire AWS infrastructure was one Google search away from being destroyed.

That day I stopped treating IAM as boring. IAM is the lock on your front door. Get it wrong and everything else doesn't matter.

Here are the 7 biggest IAM mistakes I've seen — and how to fix every single one. šŸ”


Mistake 1 — Using the Root Account for Everything

This is the most common mistake beginners make.

When you create an AWS account you get a root user. This root user has unlimited access to everything in your account — billing, services, settings, everything.

Many beginners use this root account for daily work. Creating EC2 instances, uploading to S3, everything.

Why this is dangerous:
If someone gets your root credentials — they own your entire AWS account. They can delete everything. Run up a $10,000 bill. Lock you out permanently.

The fix:

1. Log into AWS Console with root account
2. Go to IAM → Users → Create User
3. Give it AdministratorAccess policy
4. Log out of root account
5. Log in with new IAM user for ALL daily work
6. Lock away your root credentials — only use for billing
Enter fullscreen mode Exit fullscreen mode

Enable MFA on your root account immediately. Go to IAM → Security recommendations → Enable MFA. This adds a second layer of protection even if password is stolen.


Mistake 2 — Giving Everyone AdministratorAccess

I see this all the time.

Developer needs access to S3 — give them AdministratorAccess. Developer needs to read from RDS — give them AdministratorAccess. It's easier than figuring out exact permissions right?

Wrong. Very wrong.

Why this is dangerous:
If that developer's credentials are compromised — the attacker now has full admin access to your entire infrastructure. They can create new users, delete databases, access all S3 buckets, run expensive EC2 instances.

The fix — Principle of Least Privilege:
Give users ONLY the permissions they absolutely need and nothing more.

Developer needs S3 read access only?

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::your-specific-bucket",
                "arn:aws:s3:::your-specific-bucket/*"
            ]
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Only S3 read. Nothing else. This is how real companies manage IAM. āœ…


Mistake 3 — Hardcoding AWS Credentials in Code

This one destroys people.

It's so tempting when you're learning:

# Please NEVER do this āŒ
import boto3

s3 = boto3.client(
    's3',
    aws_access_key_id='AKIAIOSFODNN7EXAMPLE',
    aws_secret_access_key='wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
)
Enter fullscreen mode Exit fullscreen mode

You write this locally. It works. You push to GitHub.

Now your credentials are public. On the internet. Forever.

GitHub has bots that scan every public repository for AWS credentials within SECONDS of a commit. Within minutes your account can be compromised, crypto miners deployed on EC2, and you're looking at a bill for thousands of dollars.

AWS will email you. But the damage is already done.

The fix — Use Environment Variables:

# Always do this āœ…
import boto3
import os

s3 = boto3.client(
    's3',
    aws_access_key_id=os.environ.get('AWS_ACCESS_KEY_ID'),
    aws_secret_access_key=os.environ.get('AWS_SECRET_ACCESS_KEY'),
    region_name=os.environ.get('AWS_DEFAULT_REGION')
)
Enter fullscreen mode Exit fullscreen mode

Set environment variables on your machine:

export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
export AWS_DEFAULT_REGION=ap-south-1
Enter fullscreen mode Exit fullscreen mode

Or even better — use AWS IAM Roles for EC2 instances. Zero credentials needed in code at all.

Add .env to your .gitignore ALWAYS:

# .gitignore
.env
*.pem
credentials
Enter fullscreen mode Exit fullscreen mode

Mistake 4 — Never Rotating Access Keys

Access keys are like passwords. They should be changed regularly.

Many developers create one access key and use it for years. If that key was ever exposed — even briefly — an attacker could have been using it silently for months.

The fix:
Rotate access keys every 90 days minimum.

1. Go to IAM → Users → your user → Security credentials
2. Create new access key
3. Update your applications with new key
4. Test everything works
5. Delete the old key
Enter fullscreen mode Exit fullscreen mode

Also — regularly audit your access keys:

IAM → Users → Security credentials → 
Check "Last used" column
Enter fullscreen mode Exit fullscreen mode

If a key hasn't been used in 90 days — delete it. Unused keys are unnecessary risk.


Mistake 5 — Not Using IAM Roles for EC2

This is a big one that even intermediate developers get wrong.

When your EC2 instance needs to access S3 or other AWS services — beginners put access keys directly on the server:

# On EC2 server - WRONG āŒ
aws configure
# Then type access key and secret key
Enter fullscreen mode Exit fullscreen mode

This means credentials are sitting on your server. If the server is compromised — those credentials are gone.

The fix — IAM Roles:

IAM Roles give your EC2 instance temporary credentials automatically. No keys stored anywhere.

1. Go to IAM → Roles → Create Role
2. Select "AWS Service" → EC2
3. Attach the permissions your EC2 needs (e.g. AmazonS3ReadOnlyAccess)
4. Name the role (e.g. "ec2-s3-read-role")
5. Go to EC2 → your instance → Actions → Security → Modify IAM Role
6. Attach your new role
Enter fullscreen mode Exit fullscreen mode

Now your EC2 can access S3 without any credentials stored anywhere. This is production-grade security. āœ…


Mistake 6 — Ignoring IAM Policy Conditions

Most people write IAM policies like this:

{
    "Effect": "Allow",
    "Action": "s3:*",
    "Resource": "*"
}
Enter fullscreen mode Exit fullscreen mode

This allows S3 access from ANYWHERE — any IP, any time, any condition.

The fix — Add Conditions:

Restrict access to specific IP addresses:

{
    "Effect": "Allow",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::my-bucket/*",
    "Condition": {
        "IpAddress": {
            "aws:SourceIp": "203.0.113.0/24"
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Require MFA for sensitive operations:

{
    "Effect": "Deny",
    "Action": ["s3:DeleteObject", "s3:DeleteBucket"],
    "Resource": "*",
    "Condition": {
        "BoolIfExists": {
            "aws:MultiFactorAuthPresent": "false"
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Conditions add a powerful extra layer of security that most beginners completely ignore.


Mistake 7 — Not Monitoring IAM Activity

Many people set up IAM and forget about it.

They never check who is accessing what. They never look at failed login attempts. They never review which permissions are actually being used.

This means if something goes wrong — you find out too late.

The fix — Enable CloudTrail:

1. Go to AWS CloudTrail → Create Trail
2. Enable for all regions
3. Store logs in S3 bucket
4. Enable CloudWatch integration for alerts
Enter fullscreen mode Exit fullscreen mode

CloudTrail records every API call made in your account — who did what, when, from where. If someone accesses your account — you'll know.

Also use IAM Access Analyzer:

IAM → Access Analyzer → Create Analyzer
Enter fullscreen mode Exit fullscreen mode

This automatically finds resources in your account that are shared with external entities. It will show you things you didn't even know were public.


Quick Security Checklist

Go through this right now for your AWS account:

☐ Root account MFA enabled
☐ Root account access keys deleted
☐ IAM users created for daily work
☐ Least privilege applied to all users
☐ No credentials hardcoded in code
☐ .env files in .gitignore
☐ Access keys rotated in last 90 days
☐ IAM Roles used for EC2 instances
☐ CloudTrail enabled
☐ IAM Access Analyzer enabled
Enter fullscreen mode Exit fullscreen mode

If you can check all 10 — your AWS account is more secure than 90% of beginners out there. āœ…


Real Cost of Getting IAM Wrong

This is not theoretical. Real people lose real money.

A developer pushes AWS credentials to GitHub → bots find it in seconds → spin up 100 GPU instances for crypto mining → $50,000 bill in 24 hours.

This happens every single week to developers around the world.

AWS has a process to appeal these bills — but it's stressful, not guaranteed, and completely avoidable.

Take IAM seriously from day one. It takes 30 minutes to set up properly. It can save you thousands of rupees and weeks of stress.


Summary

Mistake Fix
Using root account Create IAM user for daily work
AdministratorAccess everywhere Principle of least privilege
Hardcoded credentials Environment variables + IAM Roles
Never rotating keys Rotate every 90 days
Keys on EC2 Use IAM Roles instead
No conditions on policies Add IP and MFA conditions
Not monitoring Enable CloudTrail + Access Analyzer

Final Thoughts

IAM is not the exciting part of AWS. But it's the most important part.

Every other AWS service you build — EC2, S3, Lambda, RDS — is only as secure as your IAM setup.

Get IAM right and your infrastructure is protected. Get it wrong and everything else doesn't matter.

Take 30 minutes today and go through that security checklist. Your future self will thank you. šŸ’Ŗ


Follow LearnWithPrashik for more practical AWS security and backend development content.

I write the honest, practical guides I wish existed when I started.

Connect with me:
LinkedIn: linkedin.com/in/prashik-besekar
GitHub: github.com/prashikBesekar

Top comments (1)

Collapse
 
ptak_dev profile image
Patrick T

Good breakdown.