DEV Community

Cover image for Pixel & Spoon Hands-On: Writing and Attaching IAM Policies πŸ“œ

Pixel & Spoon Hands-On: Writing and Attaching IAM Policies πŸ“œ

Chapter 4.3 β€” Hands-on companion to Chapter 4: IAM: The Gatekeeper of AWS. Aarav has EC2 access β€” but do we really know what that means? Today we open the policy, read what's inside, and write a tighter one.


The Policy We've Been Ignoring

In Chapter 4.1, we attached AmazonEC2FullAccess to Aarav.

In Chapter 4.2, we moved that to the Developers group.

But here's something we haven't done yet β€” actually looked at what AmazonEC2FullAccess allows.

Spoiler: it's a lot.

AmazonEC2FullAccess lets Aarav start instances, stop instances, terminate instances, create snapshots, modify security groups, allocate elastic IPs β€” essentially everything you can do with EC2.

Right now, Pixel & Spoon is a small startup. Aarav is trustworthy. It's fine.

But what happens when the team grows? What if you hire a junior developer who should only be able to view servers, not terminate them? Or a contractor who needs to start and stop instances, but never delete anything permanently?

AWS-managed policies like AmazonEC2FullAccess are broad by design β€” they cover everything in a service. Custom policies let you grant exactly what someone needs, nothing more.

That's what this chapter is about.


πŸ“œ What's Actually Inside a Policy?

Before we write one, let's read one.

In the AWS Console, search for IAM β†’ click Policies in the left sidebar β†’ search for AmazonEC2FullAccess β†’ click on it β†’ click the JSON tab.

alt text
You'll see something like this (simplified):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ec2:*",
      "Resource": "*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Let's read this in plain English:

"Version"    β†’  The policy language version. Always "2012-10-17". Don't change this.

"Statement"  β†’  A list of permission rules. One policy can have many statements.

"Effect"     β†’  "Allow" or "Deny". This one allows.

"Action"     β†’  What is being allowed. "ec2:*" means every EC2 action β€” all of them.

"Resource"   β†’  Which specific resources. "*" means all resources, no restrictions.
Enter fullscreen mode Exit fullscreen mode

So AmazonEC2FullAccess in plain English says:

"Allow everything EC2 can do, on every resource, with no conditions."

That's powerful. Too powerful for a junior developer.


πŸ› οΈ Step-by-Step: Creating a Custom Policy

Let's create a policy called PixelSpoon-Developer-EC2 that gives Aarav only what he actually needs day-to-day:

  • View all instances βœ…
  • Start and stop instances βœ…
  • Connect to instances βœ…
  • Terminate instances ❌ (too destructive β€” requires deliberate action)
  • Modify security groups ❌ (that's Rohit's job)

Step 1 β€” Open IAM β†’ Policies

Search IAM in the console β†’ left sidebar β†’ Policies β†’ orange Create policy button.

alt text

Step 2 β€” Switch to the JSON Editor

At the top of the policy editor, click the JSON tab.

Clear what's there and paste in this custom policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:Describe*",
        "ec2:StartInstances",
        "ec2:StopInstances",
        "ec2:GetConsoleOutput",
        "ec2-instance-connect:SendSSHPublicKey"
      ],
      "Resource": "*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

What each action does:

ec2:Describe*                        β†’  View/list any EC2 resource (instances, AMIs, etc.)
ec2:StartInstances                   β†’  Power on a stopped instance
ec2:StopInstances                    β†’  Power off a running instance
ec2:GetConsoleOutput                 β†’  Read the instance's console log for debugging
ec2-instance-connect:SendSSHPublicKey β†’  Connect via browser-based EC2 Instance Connect
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ Notice ec2-instance-connect is a separate service prefix from ec2 β€” it's easy to assume it lives under ec2: but AWS treats Instance Connect as its own service in IAM. This is a common mistake that causes "access denied" errors even when EC2 permissions look correct.

Notice what's not in the list β€” ec2:TerminateInstances, ec2:AuthorizeSecurityGroupIngress, ec2:DeleteSnapshot. Aarav simply can't do those things, even accidentally.

AWS IAM create policy JSON editor console screenshot

Click Next.


Step 3 β€” Name and Describe the Policy

Policy name:   PixelSpoon-Developer-EC2
Description:   EC2 access for Pixel and Spoon developers. View, start, stop, and connect only. No termination or security group modifications.
Enter fullscreen mode Exit fullscreen mode

A good description matters β€” six months from now, you or someone else will look at this policy and need to understand what it does without decoding the JSON.

Click Create policy.

AWS IAM policy review create name screenshot


πŸ” Attach the New Policy to the Developers Group

Now let's swap out AmazonEC2FullAccess from the Developers group and replace it with our tighter custom policy.

Step 1 β€” Go to IAM β†’ User groups β†’ click Developers.

Step 2 β€” Click the Permissions tab β†’ click on the check box next to AmazonEC2FullAccess and click Remove to remove it.

alt text

Step 3 β€” Click Add permissions β†’ Attach policies β†’ search for PixelSpoon-Developer-EC2 β†’ tick it β†’ click Attach policies.

Or you can filter by type Customer managed policies to find it faster.

alt text

Done. Aarav now has exactly what he needs β€” and nothing that could cause an incident at 2am.


🧠 AWS Managed vs Customer Managed β€” When to Use Which

Now that you've written one custom policy, here's a simple rule of thumb:

AWS Managed Policies
     βœ… Great for getting started quickly
     βœ… Maintained and updated by AWS
     ❌ Often broader than you actually need
     Use for: prototypes, personal learning, non-critical access

Customer Managed Policies
     βœ… Exactly the permissions you define
     βœ… Reusable across users, groups, and roles
     βœ… Auditable β€” you know exactly what's allowed
     ❌ Takes more time to write and maintain
     Use for: real teams, production environments, sensitive roles
Enter fullscreen mode Exit fullscreen mode

At Pixel & Spoon, we'll keep AdministratorAccess on Rohit's Admins group for now β€” he's the only one in it and he genuinely needs broad access. But as the company grows, even that will get tightened.


πŸ› οΈ Try It Yourself

πŸ› οΈ Task: Write a read-only policy for Divya

Pixel & Spoon just brought on Divya as a data analytics intern.
She needs to VIEW EC2 instances and S3 buckets β€” but touch nothing.

Goal: Create a custom policy called PixelSpoon-Intern-ReadOnly
that allows only Describe/List/Get actions on EC2 and S3.

Hints:
- ec2:Describe* covers all EC2 viewing actions
- s3:GetObject, s3:ListBucket cover S3 read access
- Effect should be "Allow" on both
- Resource: "*" is fine for now

Then create an IAM user "divya-intern" and attach this policy directly
- remember to ad MFA
(she's temporary, so no group needed).
This is where IAM Role would be better, but we'll cover that in the next chapter.
Enter fullscreen mode Exit fullscreen mode

Click to reveal the answer
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "ec2:Describe*",
                "s3:ListBucket"
            ],
            "Resource": "*"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

New IAM User list should look like this


πŸ—ΊοΈ Continue the Hands-On Series

Ch 4.1 β€” βœ… Creating IAM Users

Ch 4.2 β€” βœ… Creating and Managing IAM Groups

Ch 4.3 β€” βœ… Writing and Attaching IAM Policies (you are here)

Ch 4.4 β€” Creating IAM Roles: Human & Service

Next up β€” Karthik the auditor needs temporary access to Pixel & Spoon's AWS account. And the CI/CD bot needs to deploy code automatically without a human logging in. Both of these need Roles β€” not users, not groups.

πŸ‘‰ Chapter 4.4: Creating IAM Roles β†’ (Read it here)


Resources I'm learning from:


Top comments (0)