What's up everyone! π Welcome back to my "AWS VPC to ECS with CloudFormation" series - Day 3 is here!
So in my last blog posts, I got the networking foundation sorted with VPC and subnets. Now I'm diving into something that honestly used to give me nightmares - IAM permissions and security stuff. But you know what? Once I stopped being scared of it and actually understood what's happening, it became way less intimidating!
What I'm Tackling Today
Alright, so before I can actually run any containers, I need these three things set up:
- IAM Roles - Because AWS won't let you do anything without proper permissions (and rightfully so!)
- SSM Parameters - My secret weapon for managing configurations
- ECS Cluster - The actual home where my containers will live
Real talk - I used to just copy IAM policies from Stack Overflow and pray they worked. Bad idea. Trust me, learn from my mistakes! π
Today's Architecture - What We're Building
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Day 3: Security & Orchestration β
β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββ β
β β IAM Roles β β SSM Parameters β β ECS Cluster β β
β β β β β β β β
β β βββββββββββββββ β β βββββββββββββββ β β βββββββββββββββββββββββββββ β β
β β βECS Executionβ β β βImage ARN β β β β Fargate Platform β β β
β β β Role β β β βParameter β β β β β β β
β β βββββββββββββββ β β βββββββββββββββ β β β βββββββββββββββββββββββ β β β
β β β β β β β β Container Tasks β β β β
β β βββββββββββββββ β β βββββββββββββββ β β β β (Future Home) β β β β
β β βECS Task β β β βConfig Valuesβ β β β βββββββββββββββββββββββ β β β
β β β Role β β β β(Future) β β β β β β β
β β βββββββββββββββ β β βββββββββββββββ β β β Auto Scaling Ready β β β
β β β β β β βββββββββββββββββββββββββββ β β
β β βββββββββββββββ β β β β β β
β β βCodeBuild β β β β β β β
β β β Role β β β β β β β
β β βββββββββββββββ β β β β β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββββ β
β β β β β
β βββββββββββββββββββββββββΌββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββΌβββββββββββββββ β
β β Secure Foundation β β
β β Ready for Containers β β
β βββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. IAM Roles - Finally Making Peace with Permissions
Okay, confession time. IAM used to be my biggest AWS fear. All those JSON policies, trust relationships, conditions... I'd just copy-paste stuff and hope it worked. Spoiler alert: it usually didn't, and I'd spend hours debugging "Access Denied" errors.
But here's what changed everything for me - I started thinking of IAM roles like job descriptions. Each role has specific responsibilities, and AWS just wants to make sure the right "employee" is doing the right job.
Here's my complete IAM setup:
AWSTemplateFormatVersion: "2010-09-09"
Description: "Creating IAM Roles for Learning Purpose"
Parameters:
RoleName:
Type: String
Description: Name of IAM Role
Default: "learner-ecs-role"
TaskRoleName:
Type: String
Description: Name of IAM Role
Default: "learner-ecs-task-exc-role"
BuildRoleName:
Type: String
Description: Name of IAM Role
Default: "learner-build-role"
PolicyName:
Type: String
Description: Name of IAM Policy
Default: "learner-ecs-permission-policy"
PolicyName1:
Type: String
Description: Name of IAM Policy
Default: "learner-ecs-policy"
TeamNameValue:
Type: String
Description: TeamName Tag Value
Default: "awslearner"
EnvironmentValue:
Type: String
Description: Environment Tag Value
Default: "dev"
Resources:
# Permissions for ECS to manage your containers
ECSRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Ref RoleName
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Policies:
- PolicyName: !Ref PolicyName
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 'ecs:*'
- 'ec2:Describe*'
- 'elasticloadbalancing:Describe*'
Resource: '*'
Tags:
- Key: Name
Value: !Ref RoleName
- Key: TeamName
Value: !Ref TeamNameValue
- Key: Environment
Value: !Ref EnvironmentValue
# Permissions for containers to start and access logs
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Ref TaskRoleName
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs-tasks.amazonaws.com]
Action: ['sts:AssumeRole']
Condition:
ArnLike:
aws:SourceArn: !Sub arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:*
StringEquals:
aws:SourceAccount: !Ref AWS::AccountId
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Policies:
- PolicyName: !Ref PolicyName1
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 'ecs:*'
Resource: '*'
Tags:
- Key: Name
Value: !Ref TaskRoleName
- Key: TeamName
Value: !Ref TeamNameValue
- Key: Environment
Value: !Ref EnvironmentValue
# Permissions for CodeBuild to build and push images
CodeBuildRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Ref BuildRoleName
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: CodeBuildECRAccess
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- ecr:GetAuthorizationToken
- ecr:BatchCheckLayerAvailability
- ecr:CompleteLayerUpload
- ecr:InitiateLayerUpload
- ecr:PutImage
- ecr:UploadLayerPart
Resource: "*"
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: "*"
- Effect: Allow
Action:
- s3:GetObject
Resource: "arn:aws:s3:::*"
- Effect: Allow
Action:
- codeconnections:*
Resource: "*"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSCodeBuildDeveloperAccess
- arn:aws:iam::aws:policy/AmazonSSMFullAccess
Tags:
- Key: Name
Value: !Ref BuildRoleName
- Key: TeamName
Value: !Ref TeamNameValue
- Key: Environment
Value: !Ref EnvironmentValue
Time to deploy this bad boy:
aws cloudformation deploy \
--template-file infra/roles/iam.yaml \
--stack-name AWSLearner-IAM-Stack \
--capabilities CAPABILITY_NAMED_IAM
Quick heads up: That --capabilities CAPABILITY_NAMED_IAM
flag is super important - CloudFormation needs your explicit permission to mess with IAM stuff. Learned that one the hard way when my first deployment just sat there doing nothing! π€¦ββοΈ
2. SSM Parameters - My New Best Friend
Okay, can we talk about SSM Parameter Store for a sec? This thing has literally changed my life! No more hardcoding database URLs, API keys, or any other config values directly in my templates.
I remember my early days when I'd hardcode everything and then spend hours trying to figure out why my dev environment was hitting production databases. Yeah... not my proudest moments.
Here's my SSM setup:
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Creating SSM Parameters for Learning Purpose'
Parameters:
TeamNameValue:
Type: String
Description: TeamName Tag Value
Default: "awslearner"
EnvironmentValue:
Type: String
Description: Environment Tag Value
Default: "dev"
SSMName:
Type: String
Default: "/learner/imagearn/value"
Resources:
# Placeholder for storing your container image location
ImageSSM:
Type: AWS::SSM::Parameter
Properties:
Name: !Ref SSMName
Type: String
Value: '1'
Description: "Image ARN"
Tags:
Name: !Ref SSMName
TeamName: !Ref TeamNameValue
Environment: !Ref EnvironmentValue
Why SSM Parameters Rock My World
Look, once you start using these, there's no going back:
- No more secrets in code - Everything stays encrypted and secure
- Change stuff without redeploying - Update a parameter, restart your service, boom!
-
Super organized - That hierarchical naming (
/learner/imagearn/value
) keeps everything neat - Plays nice with everything - Other AWS services can grab these values directly
Let's get this deployed:
aws cloudformation deploy \
--template-file infra/ssm/ssm.yaml \
--stack-name AWSLearner-SSM-Stack \
--capabilities CAPABILITY_NAMED_IAM
3. ECS Cluster - The Container Playground
Now we're getting to the fun stuff! The ECS Cluster is basically the stage where all my containers are going to perform their magic. I'm going with Fargate because honestly? I don't want to deal with managing EC2 instances if I can avoid it.
Here's what I'm setting up:
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Creating ECS Cluster for Learning Purpose'
Parameters:
TeamNameValue:
Type: String
Description: TeamName Tag Value
Default: "awslearner"
EnvironmentValue:
Type: String
Description: Environment Tag Value
Default: "dev"
ClusterName:
Type: String
Description: Name of the ECS Cluster
Default: "learner-cluster"
Resources:
# Container hosting platform where your apps will run
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Ref ClusterName
CapacityProviders:
- FARGATE
DefaultCapacityProviderStrategy:
- CapacityProvider: FARGATE
Weight: 1
Tags:
- Key: Name
Value: !Ref ClusterName
- Key: TeamName
Value: !Ref TeamNameValue
- Key: Environment
Value: !Ref EnvironmentValue
Why Fargate is Perfect for This
Let me tell you why I'm obsessed with Fargate:
- Serverless containers - I just tell AWS what I want, and they handle all the infrastructure nonsense
- Scales like crazy - Traffic spike? No problem, Fargate's got my back
- Secure by default - Each task gets its own little isolated bubble
- Pay for what you use - Only charged for the actual compute time
Time to deploy:
aws cloudformation deploy \
--template-file infra/cluster/cluster.yaml \
--stack-name AWSLearner-Cluster-Stack \
--capabilities CAPABILITY_NAMED_IAM
How These Three Play Together
Here's the cool part - these aren't just random components. They work together like a well-oiled machine:
- IAM Roles are like the security guards - they make sure only the right services can access the right resources
- SSM Parameters are the configuration managers - they store all the dynamic stuff our services need
- ECS Cluster is the execution platform - where the actual magic happens
What's Coming Next?
In my next post (Day 4), I'm going to add the final pieces to this puzzle:
- Security Groups - Network-level firewall rules
- Application Load Balancer - Traffic distribution and health checks
We're getting close to actually running some containers! π
My Key Takeaways
- Don't be scared of IAM - Take time to understand it instead of just copying policies
- SSM Parameters are life-changing - Use them for anything that might need to change
- ECS Cluster setup is actually pretty simple - The complexity comes with the services and tasks
When Things Go Wrong (They Will!)
Here's what I've learned from my many failures:
- IAM issues: Check the trust policy - make sure the right service can actually assume the role
- SSM parameter not found: Double-check the parameter name matches exactly what you're referencing
- ECS cluster stuck: Give it a few minutes - these things take time to spin up
That's Day 3 in the books! We now have a solid, secure foundation that's ready for containers. Next time, we'll add the final infrastructure pieces and get ready to deploy our actual application.
How's your AWS journey going? Ever had any epic IAM fails? Share your war stories in the comments! π
Up next: Day 4 - Security Groups & Load Balancer Setup
π» About Me
Hi! I'm Utkarsh, a Cloud Specialist & AWS Community Builder who loves turning complex AWS topics into fun chai-time stories β
Top comments (1)
This hits home. IAM used to feel like black magic until I started treating roles like job descriptions too. And yes to SSM Parameter Store total game changer for keeping configs clean and safe. Loving this series!