HANDS-ON ASSESSMENT GUIDE

AWS Cloud
Practical Prep

Everything you need for the assessment — dependency chains, exact command sequences, checklists and common traps. Understand the why, not just the clicks.

14Services covered
3Exact scenarios
60+Checklist items
38Common traps
🗺

Master Mental Model

Before touching the console, map the architecture. Ask these six questions for every scenario:

1 — Where?
Region → AZ → VPC → Subnet
2 — Who?
IAM · Roles · Policies
3 — Traffic?
Routes · IGW · NAT · ALB · DNS
4 — Data?
S3 · EBS · EFS · RDS
5 — Scale?
ASG · Multi-AZ · Read Replicas
6 — Verify?
Browser · curl · Logs · Health checks
INTERNET │ Route 53 / DNS │ Load Balancer (ALB) ├──────────┐ EC2 EC2 ← Public Subnet └────┬─────┘ │ RDS ← Private Subnet +──────────────────+ │ S3 │ │ Files / Assets │ +──────────────────+ VPC 10.0.0.0/16 ├── Public Subnets → IGW ├── Private Subnets → NAT → IGW ├── Route Tables ├── Security Groups (resource-level) └── Network ACLs (subnet-level) IAM → permissions | CloudWatch → monitoring | CloudTrail → API audit

Service Quick Reference

EC2Virtual server
S3Object storage
EBSBlock disk for EC2
EFSShared file system
RDSManaged relational DB
VPCPrivate network
IAMIdentity & permissions
ALBHTTP/HTTPS load balancer
ASGEC2 auto scaling
Route 53DNS service
LambdaServerless functions
CloudWatchMonitoring & alarms
CloudTrailAPI audit history
IGW / NATInternet gateways
🔑

IAM — Identity & Access

IAM Entities
  • User — individual identity
  • Group — collection of users
  • Role — assumable identity (temp creds)
  • Policy — permission document
Policy Elements
  • Effect — Allow / Deny
  • Action — what operation?
  • Resource — on what ARN?
  • Condition — under what condition?
  • Principal — who?
Least Privilege: Give only what is required. Never use AdministratorAccess just because it is convenient.

Verify EC2 Role

bash
aws sts get-caller-identity
Do not put long-lived access keys in application code when an IAM Role can be attached to the EC2 instance instead.
🌐

VPC Networking

📐 CIDR Layout
VPC: 10.0.0.0/16 ├── Public-A 10.0.1.0/24 ├── Public-B 10.0.2.0/24 ├── Private-A 10.0.11.0/24 └── Private-B 10.0.12.0/24

Subnet CIDR must fit inside the VPC CIDR.

Traffic Paths

Public Subnet
EC2 / Resource
↓
Internet Gateway
↓
Internet
Route Table: 0.0.0.0/0 → IGW
Private Subnet (outbound)
Private Resource
↓
NAT Gateway
↓
Internet Gateway
↓
Internet
Key trap: Public subnet ≠ automatically public EC2. The instance also needs a public IP, SG open to port 80, and the route table must point to IGW.

Route Table Rules

Public Route Table
DestinationTarget
10.0.0.0/16local
0.0.0.0/0igw-xxxx
Private Route Table
DestinationTarget
10.0.0.0/16local

⚠ No IGW route here!

Security Group vs NACL

FeatureSecurity GroupNetwork ACL
Level Resource / Instance Subnet
State Stateful Stateless
Rules Allow only Allow + Deny
Return traffic Automatically tracked Must explicitly allow

Layered Security Architecture

Internet
→
ALB-SG
→
EC2-SG
port 80 from ALB-SG
→
RDS-SG
3306 from EC2-SG
Prefer security-group-to-security-group rules between tiers. Never expose database ports to 0.0.0.0/0.

Secure VPC Build Order

1 Create VPC (CIDR 10.0.0.0/16)
2 Create Private Subnet (10.0.1.0/24)
3 Create Public Subnet (10.0.2.0/24)
4 Create private-rt + public-rt
5 Associate private-rt → private subnet
6 Associate public-rt → public subnet
7 Create Internet Gateway
8 Attach IGW to VPC
9 Add 0.0.0.0/0 → IGW to public-rt
✗ Do NOT add IGW route to private-rt
🖥

EC2 — Virtual Servers

Launch Checklist

AMIUbuntu 22.04 / Amazon Linux
Instance Typet3.micro (lab default)
Key PairDownload .pem before launch
VPC + SubnetPick correct subnet
Public IPEnable auto-assign
Security Group80 + 22
StorageRoot volume size
User Data#!/bin/bash script

SSH Access

bash
# Set permissions (required)
chmod 400 key.pem

# Ubuntu
ssh -i key.pem ubuntu@PUBLIC_IP

# Amazon Linux
ssh -i key.pem ec2-user@PUBLIC_IP

User Data — Nginx + HTML

bash (User Data)
#!/bin/bash

apt-get update -y
apt-get install -y nginx

systemctl enable nginx
systemctl start nginx

cat > /var/www/html/index.html <<'EOF'
<!DOCTYPE html>
<html>
<head><title>Portfolio</title></head>
<body>
  <h1>Welcome to My Portfolio</h1>
  <p>AWS Cloud Practical Assessment</p>
</body>
</html>
EOF

Nginx Commands

bash
sudo systemctl status nginx
sudo systemctl start nginx
sudo systemctl restart nginx
sudo systemctl enable nginx

# Test locally
curl localhost

# Check port 80
sudo ss -tulpn | grep :80
Default web root: /var/www/html

EBS — Attach & Mount

Rule: EBS must be in the SAME Availability Zone as the EC2 instance.
bash
# 1. See all block devices
lsblk

# 2. Format new disk (WARNING: destroys existing data)
sudo mkfs.ext4 /dev/nvme1n1

# 3. Create mount point
sudo mkdir /data

# 4. Mount
sudo mount /dev/nvme1n1 /data

# 5. Verify
df -h

# 6. Make persistent — get UUID
sudo blkid /dev/nvme1n1

# 7. Add to /etc/fstab
# UUID=YOUR-UUID  /data  ext4  defaults,nofail  0 2

# 8. Test fstab
sudo mount -a
Run lsblk first to confirm the device name before running mkfs. Formatting the wrong device destroys data.

EC2 Troubleshooting Chain

01 Instance running?
02 2/2 status checks passed?
03 Has a public IP?
04 In a public subnet?
05 Route table has 0.0.0.0/0 → IGW?
06 Security Group allows port 80?
07 Nginx running?
08 App listening on port 80?
09 OS firewall blocking?
If curl localhost works but browser fails → the problem is AWS networking/security, not the application.
🪣

S3 — Object Storage

Static Website Flow

Create Bucket
→
Enable Versioning
→
Create materials/
→
Upload index.html
→
Modify + Re-upload
→
Show Versions
→
Unblock Public Access
→
Bucket Policy
→
Enable Website Hosting
→
Open Endpoint ✓

Public Read Bucket Policy

New S3 buckets have Block Public Access ON by default. Disable it first, then apply this policy.
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::BUCKET-NAME/*"
    }
  ]
}

S3 CLI

bash
aws s3 ls
aws s3 ls s3://BUCKET-NAME/
aws s3 cp index.html s3://BUCKET-NAME/
aws s3 cp index.html s3://BUCKET-NAME/materials/
aws s3 cp s3://BUCKET-NAME/index.html .

Storage Classes

Access PatternClass
StandardFrequently accessed
S3-IALess frequent, rapid access
GlacierRare / archive (hours to retrieve)
Index path trap: index.html and materials/index.html are different objects. If the assessment needs both, keep them at both paths.
🗄

RDS — Managed Database

Common Ports
  • MySQL / MariaDB → 3306
  • PostgreSQL → 5432
  • MS SQL → 1433
Multi-AZ vs Read Replica
  • Multi-AZ → Availability / failover
  • Read Replica → Read scaling
"Primary fails?" → Multi-AZ
"Too many reads?" → Read Replica
RDS Security Group: allow the DB port from the EC2 Security Group, not from 0.0.0.0/0.

EC2 → RDS Architecture

Internet
→
ALB
→
EC2 (Public/Private)
→
RDS (Private)
⚖️

ALB + Auto Scaling

ALB Three Words
Listener
HTTP :80
→
Target Group
EC2 instances
→
Health Check
GET /

ALB Troubleshooting

Auto Scaling Group

Capacity Settings
MinimumAlways running (e.g. 1)
DesiredNormal capacity (e.g. 2)
MaximumPeak limit (e.g. 4)
Launch Template
  • AMI
  • Instance type
  • Security Group
  • IAM Role
  • Storage
  • User Data

Route 53

RecordPurpose
AMaps to IPv4 address
AAAAMaps to IPv6 address
CNAMEMaps to another hostname
Alias APoints to ALB (preferred)
MXMail servers
TXTText / verification records
⚡

Lambda + CloudWatch

Lambda Triggers
S3 upload → Lambda → Process object
API Gateway → Lambda → Response
CloudWatch → Lambda → Scheduled task
CloudWatch vs CloudTrail
CloudWatch
What is happening? Metrics, Logs, Alarms
CloudTrail
Who did what? API activity, Audit history
🐧

Linux Command Reference

Files & Navigation
pwd  ls  ls -la  cd
mkdir  touch  cp  mv  rm
cat  less  head  tail
Disk & Network
lsblk  df -h  du -sh *
ip addr  ip route
ss -tulpn  curl  ping

Useful Patterns

bash
# Search for errors in log
grep "error" app.log

# Find HTML files
find /var/www -name "*.html"

# Fix web root ownership
sudo chown -R www-data:www-data /var/www/html

# Check what's on port 80
sudo ss -tulpn | grep :80

# Running processes
ps aux | grep nginx
🗝

Requirement → Service Map

The core skill: translate assessment words into AWS services.

Static HTML filesS3
Previous file versionsS3 Versioning
Public S3 websiteS3 Website + Bucket Policy
Linux serverEC2
Automatic server setupUser Data
Persistent EC2 diskEBS
Private networkVPC
Public subnet InternetIGW + Route
Private outbound InternetNAT Gateway
HTTP/HTTPS distributionALB
Automatic EC2 scalingAuto Scaling Group
Managed relational DBRDS
Domain name / DNSRoute 53
Serverless codeLambda
Monitor CPU / logsCloudWatch
API audit historyCloudTrail
Identity & permissionsIAM
Developers isolated, testers need InternetVPC + Private & Public Subnets

Resource Creation Orders

VPC + EC2
VPC → Subnet → Route Table → IGW → Route → Security Group → EC2 → Public IP → Application
EC2 + EBS
EC2 → EBS (same AZ!) → Attach → lsblk → Format → Mount → Use
ALB + EC2
VPC → Subnets → SGs → Launch Template → Target Group → ALB → Listener → Health Check
EC2 + RDS
VPC → Private subnets → EC2 → RDS subnet group → RDS → DB SG allows EC2 SG
✅

Verification Checklists

Tick each item before submitting. These are the most common points assessors check.
🪣 S3 Static Website
0 / 11
🖥 EC2 + Nginx + EBS
0 / 16
🌐 VPC Networking
0 / 12
⚠️

Common Traps

🪣 S3 Traps
  • Forgetting to enable Versioning before first upload
  • Uploading index2.html instead of the same index.html again
  • Forgetting to click Show Versions
  • Wrong bucket ARN in policy (missing /*)
  • Block Public Access still ON when making site public
  • Confusing materials/index.html with root index.html
🖥 EC2 Traps
  • Wrong Ubuntu version (use 22.04, not 20.04)
  • Wrong instance type
  • No public IP assigned at launch
  • Port 80 missing in Security Group
  • SSH port 22 opened to 0.0.0.0/0 unnecessarily
  • User Data syntax error (script runs silently)
  • EBS created in a different AZ than EC2
  • EBS attached but NOT mounted
  • Running mkfs on the wrong device
  • Nginx installed but not started / not enabled
🌐 VPC Traps
  • Creating Route Table but forgetting subnet association
  • Creating IGW but not attaching it to the VPC
  • Attaching IGW but forgetting to add 0.0.0.0/0 route
  • Adding IGW route to the private Route Table
  • Assuming a public subnet automatically gives EC2 Internet access
🔍

Universal Debug Chain

Rule: Change one thing → test → continue. Never randomly change five settings.
Resource
→
Region / AZ
→
VPC / Subnet
→
Route Table
→
IGW / NAT
→
SG / NACL
→
IAM / Policy
→
Service
→
Port
→
Application
→
Test ✓
🛡

Security Rules

Use least privilege — give only what is required.
SSH port 22 should be restricted to your IP in a lab (YOUR-IP/32).
Databases stay in private subnets; never expose DB ports to the Internet.
Prefer SG-to-SG rules between application tiers.
Do not make S3 buckets public unless the requirement explicitly needs it.
Never use root credentials for normal AWS work.
Never put long-lived access keys in application code — use an IAM Role.
Never open all ports just because troubleshooting is hard.
⚡

30-Second Recall

S3
Bucket → Versioning → Upload → Modify → Re-upload → Show versions → Unblock public → Bucket policy → Website hosting → index.html → Endpoint
EC2
AMI → Type → Key → VPC → Subnet → SG → User Data → Launch → EBS (same AZ) → Attach → Mount → Nginx → index.html → curl → Browser
VPC
VPC → Subnets → Route Tables → Associations → IGW → Public route (0.0.0.0/0) → Private stays without IGW route
PUBLIC
0.0.0.0/0 → IGW
PRIVATE
Private → NAT Gateway → IGW → Internet (outbound only)
SG
80 HTTP · 22 SSH (your IP) · DB port only from application SG
DEBUG
Resource → Network → Route → SG/NACL → Service → Application
Golden Rule: Translate every requirement → AWS service → resource dependency → configuration → security → verification. This pattern solves variations you haven't seen before.
🧹

Cleanup After Practice

Stopping an EC2 does not stop charges from every related resource. Delete everything.
EC2Terminate instance
ASGDelete if created
ALBDelete load balancer
Target GroupRemove if unused
NAT GatewayDelete (expensive!)
Elastic IPRelease if unused
RDSDelete instance
EBSDelete unattached volumes
SnapshotsRemove unnecessary
S3Empty + delete bucket
CloudWatchRemove alarms