☁ CLOUD ENGAGEMENT Cloud Security — Operation: OPEN BUCKET

☁ Engagement — Operation: OPEN BUCKET

Cloud Security
Hands-On Workbook

You've just been hired as the first dedicated Cloud Security Engineer at Meridian Retail Group, an e-commerce company that moved fast to AWS three years ago and never looked back to check what it left open. Their first SOC 2 audit is in 90 days. Your job: audit identity, storage, and logging across their account, automate what you find, and get them ready to expand into Azure and GCP — all using free-tier sandboxes and intentionally vulnerable practice environments before you ever touch their real infrastructure.

Engagement : Meridian Retail Group — Pre-Audit Cloud Security Review
Environment : AWS (primary), Azure + GCP (planned expansion)
Trigger : SOC 2 audit in 90 days — no prior cloud security review on record
Your mandate : IAM → Storage → Logging → Automated Auditing → Multi-Cloud
Status : Engagement OPEN — practice environment only, see safety rules below
Difficulty:Intermediate
Est. time:12–16 hours
Modules:6
Labs:18

⚠ Read This Before Lab 0.1 — The Rules That Keep You (And Your Wallet) Safe

Cloud security has two failure modes new learners hit: testing infrastructure you don't own, and accidentally running up a real bill on infrastructure you do. Every lab in this workbook is built to avoid both.

This is general training guidance, not legal or financial advice. Cloud provider free-tier terms change — always check current limits before deploying a lab.

📑 Table of Contents

Module 0 – Orientation & Lab Setup
Module 1 – IAM Misconfigurations
Module 2 – Storage & Data Exposure
Module 3 – Logging & Detection
Module 4 – Automated Auditing (CSPM)
Module 5 – Multi-Cloud Expansion
🧭

Module 0 – Orientation & Lab Setup

3 labs · The shared responsibility model, your lab environment, and every practice target you'll use
0.1
Why Cloud Security Is DifferentThe shared responsibility model · why misconfig beats 0-days
ObjectiveUnderstand the shared responsibility model and why nearly every major cloud breach is a misconfiguration, not a zero-day — before you touch a single tool.
LayerProvider's JobYours
Physical security, hypervisorAlways
OS patching (EC2/IaaS)You patch the instance OS
IAM configurationEntirely yours, in every model
Data encryption settingsYou choose to enable it
Network ACLs / Security GroupsYou configure them
Managed DB engine patching (RDS)Provider patches the engineYou still configure access to it

Meridian Retail Group moved to AWS three years ago. The provider has held up its half perfectly — there's no datacenter breach in this story. Every single thing you'll find in this workbook lives in the "yours" column.

📋
"Of" vs "in" the cloud is the single most useful mental model in this workbook. Every lab from here tests something squarely in the "in the cloud" half — the half that's 100% your responsibility, regardless of provider.
0.2
Build Your Cloud Security LabFree-tier account · billing alarm · AWS CLI · Prowler
ObjectiveCreate a free-tier AWS account the safe way, and install the tools you'll use for the rest of this workbook.AWSCLI
  1. Create an AWS Free Tier account

    Use a personal email, never a work one.

  2. Enable MFA on the root account immediately

    Then never use root again for daily work.

  3. Set a billing alarm

    AWS Budgets console, alert at $1 and $10 — before you do anything else.

  4. Create a dedicated IAM user for yourself

    With AdministratorAccess for lab purposes, and generate access keys for it.

  5. Install and configure the AWS CLI

    Using that IAM user's keys, never root's.

  6. Install Prowler

    You'll use it from Module 4 onward.

# verify your CLI is talking to the right account
aws sts get-caller-identity

# install Prowler
pip install prowler
CheckExpected Result
get-caller-identityReturns YOUR IAM user ARN, never "root"
Billing alarmActive in AWS Budgets, even before your first lab
MFA on rootEnabled, root access keys deleted if any existed
⚠️
Every lab in this workbook assumes you're working from an IAM user, never root. If you've been using root, fix that first — it's the one habit that protects you from every other mistake.
0.3
Meet Your Practice TargetsflAWS · CloudGoat · AWSGoat · AzureGoat · GCPGoat
ObjectiveA quick map of every intentionally vulnerable environment you'll use, and the one rule that applies to all of them.AWSAzureGCP
TargetProviderUsed InNeeds Your Own Account?
flAWS.cloudAWSModule 1No — hosted, temp creds per level
flAWS2.cloudAWSModule 2Yes, for the final container-escape level
CloudGoatAWSModule 1Yes — deploys into your free-tier account
AzureGoatAzureModule 5Yes — Azure free account
GCPGoatGCPModule 5Yes — GCP free trial
💡
Destroy-after-use isn't optional housekeeping — it's half the skill. A cloud security engineer who deploys CloudGoat and forgets to tear it down has just created a real vulnerability in a real account.
🔑

Module 1 – IAM Misconfigurations

3 labs · Reading policies, exploiting privilege escalation, and the access layer behind almost every cloud breach
1.1
Reading IAM Policies Like an AttackerPolicy JSON anatomy · wildcards · the Policy Simulator
ObjectiveLearn to read an IAM policy document for what it allows, not just what it's named.AWS
  1. Open a policy in your own account

    Find one attached to any role in the IAM console.

  2. Read it line by line

    What does each Action/Resource pair actually permit?

  3. Look for wildcards

    "*" in either the Action or Resource field.

  4. Run it through the IAM Policy Simulator

    Simulate a specific action and see whether it's actually allowed.

  5. Spot misleading names

    Any policy whose name undersells what it actually permits.

// danger sign #1: wildcard action AND wildcard resource together
{
  "Effect": "Allow",
  "Action": "*",
  "Resource": "*"
}

// danger sign #2: LOOKS like read access — iam:PassRole + compute is a privesc primitive
{
  "Effect": "Allow",
  "Action": ["iam:PassRole", "lambda:CreateFunction", "lambda:InvokeFunction"],
  "Resource": "*"
}
PatternWhy It's Dangerous
"Action": "*"Allows every action on whatever resources are matched
"Resource": "*"Allows the action against every resource the account has
iam:PassRole + a compute serviceClassic privilege-escalation primitive — hand a more powerful role to a service you control
No Condition keyNo restriction by IP, MFA status, or time — the policy means exactly what it says
💡
"ReadOnlyAccess"-sounding policy names are exactly where real privilege-escalation paths hide. Never trust a name — read the JSON.
1.2
flAWS.cloud WalkthroughFree, hosted, no-account-required AWS misconfiguration CTF
ObjectiveWork through flAWS.cloud's first levels — public buckets and leaked credentials, the most common root cause in real breaches.AWSCLI
  1. Read the Level 1 hint carefully

    At flaws.cloud — it's written like a real engagement note, on purpose.

  2. Level 1

    Find a publicly listable S3 bucket and read its contents directly.

  3. Level 2

    Same misconfiguration class, slightly less obvious entry point.

  4. Level 3

    Find credentials accidentally exposed inside the bucket, then use them with the AWS CLI.

  5. Document the root cause

    One sentence per level — that sentence is the skeleton of a real finding.

# levels 1/2 pattern: list a bucket's contents directly via its REST endpoint
aws s3 ls s3://[bucket-name] --no-sign-request

# level 3 pattern: once you have leaked keys, check what they can see
aws sts get-caller-identity --profile flaws
aws s3 ls --profile flaws
LevelRoot Misconfiguration
1S3 bucket allows public LIST, revealing its contents to anyone
2Same bucket-policy mistake, with a less obvious entry point
3Credentials left inside a publicly-readable object, reused to pivot further
📋
Every flAWS level traces back to one root cause: someone trusted "nobody will guess this" instead of explicitly denying public access. That sentence describes a huge share of real-world cloud breaches.
1.3
Privilege Escalation with CloudGoatDeploy, exploit, and fully tear down a real privesc scenario
ObjectiveDeploy a real privilege-escalation scenario into your own free-tier account, exploit it, then destroy it completely.AWSYour Account
  1. Clone CloudGoat

    And install its Python requirements.

  2. Create a dedicated IAM user for CloudGoat

    Never root — and configure an AWS CLI profile for it.

  3. Whitelist your IP

    CloudGoat locks every scenario's vulnerable resources to your IP only.

  4. Deploy an IAM privilege-escalation scenario

    E.g. iam_privesc_by_rollback or iam_privesc_by_attachment.

  5. Enumerate from low privilege

    Starting from the credentials CloudGoat gives you, find the escalation path.

  6. Confirm, then destroy

    Verify admin-equivalent access, then immediately tear the scenario down.

git clone https://github.com/RhinoSecurityLabs/cloudgoat.git
cd cloudgoat
pip3 install -r ./core/python/requirements.txt

# deploy a privilege-escalation scenario into YOUR account
./cloudgoat.py create iam_privesc_by_rollback --profile cloudgoat

# when you're done — every time, no exceptions
./cloudgoat.py destroy iam_privesc_by_rollback --profile cloudgoat
StepExpected Result
cloudgoat.py createOutputs starting IAM credentials and a hint
Enumerate your own permissionsReveals a policy-rollback or role-attachment escalation path
After escalationget-caller-identity shows admin-equivalent access
cloudgoat.py destroyEvery CloudGoat-created resource removed
⚠️
CloudGoat can only destroy resources it created. If you created anything yourself while exploring, delete those manually first, then check the console once more to be sure.
🪣

Module 2 – Storage & Data Exposure

3 labs · The layers that control bucket access, and what "encrypted" actually protects
2.1
Finding Public Storage BucketsBlock Public Access · bucket policies · ACLs
ObjectiveAudit the three layers that combine to determine S3 bucket access — the way Meridian's three-year-old buckets need auditing before the SOC 2 review.AWS

Three layers stack to decide bucket access: Bucket Policy (resource-based), ACLs (legacy, mostly deprecated), and Block Public Access (an account- and bucket-level override switch). AWS now defaults Block Public Access ON for new buckets — but Meridian's buckets predate that default.

  1. List every bucket in your account

    Or Meridian's shared practice set, if your instructor has provided one.

  2. Check Block Public Access settings

    For each bucket.

  3. Check the bucket policy directly

    For any Principal: "*" statement.

  4. Check object-level ACLs

    For "AllUsers" or "AuthenticatedUsers" grants.

  5. Identify which layer allowed it

    For any bucket that's actually public — Policy, ACL, or a disabled Block Public Access switch.

# check Block Public Access at the bucket level
aws s3api get-public-access-block --bucket [bucket-name]

# check the bucket policy itself
aws s3api get-bucket-policy --bucket [bucket-name]
LayerWhat To CheckRed Flag
Block Public Accessget-public-access-block outputAny of the four settings set to false
Bucket Policyget-bucket-policy output"Principal": "*" with no Condition
Object ACLsget-bucket-acl / per-objectGrantee URI ending in AllUsers
💡
Block Public Access is the easiest fix and the easiest thing to check first — if it's fully enabled, a misconfigured policy or ACL underneath it usually can't expose the bucket anyway.
2.2
flAWS2.cloud — Container Escape ChallengeStorage misconfiguration meets compute, in your own account
ObjectiveWork through flAWS2's container-focused path, taking storage misconfiguration one step further into compute.AWSYour Account
  1. Read the two-path structure

    At flaws2.cloud — the second half requires your own AWS account.

  2. Complete the first path

    Focused on S3/CloudFront misconfiguration.

  3. Move into the container-escape path

    You're given access to a container and need to find a way out.

  4. Identify what allows the escape

    Privileges, mounted volumes, or metadata service access.

  5. Document the root cause

    Same one-sentence format as Lab 1.2.

PathSkill Tested
Path 1CloudFront/S3 origin misconfiguration
Path 2Container privilege/escape, IMDS credential theft
📋
The instance metadata service (IMDS) showing up here isn't a coincidence — stolen IMDS credentials are one of the most common ways a single compromised container turns into full account compromise. You'll see this exact pattern in real incident reports.
2.3
Encryption-At-Rest ReviewSSE-S3 vs SSE-KMS · EBS encryption-by-default
ObjectiveCheck whether Meridian's data is actually encrypted at rest, and understand "encrypted" vs "encrypted with a key you control."AWS
  1. Check default encryption

    On every S3 bucket in your account.

  2. Identify the key type

    SSE-S3 (AWS-managed) or SSE-KMS (a key you control and can audit).

  3. Check EBS encryption-by-default

    At the account/region level.

  4. Know which choice fits where

    SSE-S3 is fine for low-sensitivity data; SSE-KMS is what lets you audit exactly who can decrypt.

# check a bucket's default encryption configuration
aws s3api get-bucket-encryption --bucket [bucket-name]

# check account-level EBS encryption-by-default
aws ec2 get-ebs-encryption-by-default
SettingWhat It Tells You
SSE-S3Encrypted, but AWS holds and manages the key entirely
SSE-KMSEncrypted with a key you control — every decrypt is auditable via CloudTrail
EBS encryption-by-default: falseNew volumes from here on will NOT be encrypted unless told to be
📋
Encryption-at-rest doesn't protect against a misconfigured IAM policy or public bucket — it protects the data if someone gets a raw copy of the storage media itself. Modules 1 and 2.1's access controls are still your first line of defense.
📡

Module 3 – Logging & Detection

3 labs · Turning on the right logs, then reading your own Module 1 attack back out of them
3.1
Turning On The LightsCloudTrail · GuardDuty
ObjectiveEnable the two services that turn "we have no idea what happened" into "here's the exact API call that did it."AWS
  1. Check for an existing trail

    Many accounts have only the default 90-day event history, not a full trail.

  2. Enable a multi-region CloudTrail trail

    Logging to an S3 bucket, if one doesn't already exist.

  3. Enable GuardDuty

    AWS's managed threat detection — mindful of its free trial period and cost after.

  4. Confirm both are receiving data

    Not just configured — actually logging.

# check for an existing multi-region trail
aws cloudtrail describe-trails

# enable GuardDuty (mindful of cost after the free trial period)
aws guardduty create-detector --enable
CheckExpected Result
describe-trailsAt least one trail with IsMultiRegionTrail: true
CloudTrail S3 bucketReceiving new log files every few minutes
GuardDuty detectorStatus: ENABLED
⚠️
GuardDuty has a free trial period, then bills per analyzed event/log volume. Check current pricing before leaving it on indefinitely in a personal account — a short enable/review/disable cycle is enough to learn the skill here.
3.2
Reading CloudTrail Like an InvestigatorFind your own Lab 1.3 escalation, sitting in the logs
ObjectiveFind evidence of your own Module 1 privilege escalation in CloudTrail — the attack you ran is now the log entry a detection engineer hunts for.AWS
  1. Open CloudTrail Event History

    Or query the S3-stored logs if you disabled the default history.

  2. Filter for the right time window

    Around when you ran Lab 1.3's CloudGoat scenario.

  3. Find the escalation API calls

    Look for iam:AttachRolePolicy, iam:CreatePolicyVersion, or sts:AssumeRole.

  4. Trace the sequence

    Which identity made which call, in what order, leading to elevated access.

  5. Write a CISO-ready summary

    3–4 sentences describing exactly what you found.

# search Event History for a specific event type around your CloudGoat exercise
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=AttachRolePolicy
Event NameWhat It Usually Means
AttachRolePolicyAn identity attached a (possibly more powerful) policy to a role
CreatePolicyVersionA new policy version was created — check if it's more permissive
AssumeRoleOne identity assumed another role — trace why it had permission to
PutUserPolicyAn inline policy attached directly to a user — often undocumented
🎯
If you can find your own Module 1 escalation in these logs and describe it in plain language, you've just done the core job of cloud detection engineering — the rest is mostly automating this exact process at scale.
3.3
Incident Tabletop — Operation: OPEN BUCKETModules 1–3, combined into one written narrative
ObjectivePull Modules 1–3 together into one incident narrative, the way you'd actually report a finding chain to Meridian's leadership.
📋
This is your Module 1–3 capstone. No new tools — just synthesis.
  1. Re-read your evidence

    Lab 1.2's flAWS findings, Lab 1.3's CloudGoat escalation, Lab 3.2's CloudTrail evidence.

  2. Write one incident narrative

    How would an attacker chain these three weaknesses together, start to finish, in a real account?

  3. Name the control for each step

    What would have stopped it — Block Public Access, least-privilege IAM, MFA, alerting on AttachRolePolicy?

  4. Conclude with an executive summary

    One paragraph, written for someone who has never seen a terminal.

Chain StepControl That Would Stop It
Public bucket discovery (Lab 1.2)Block Public Access enabled by default
Leaked credentials reusedSecrets scanning, short-lived credentials instead of long-lived keys
IAM privilege escalation (Lab 1.3)Least-privilege policies, no wildcard actions/resources
Escalation went undetectedCloudTrail + an alert on sensitive API calls like AttachRolePolicy
🎯
Ready for Module 4 when: you can explain this entire chain out loud, in under two minutes, without looking at your notes.
🛰️

Module 4 – Automated Auditing (CSPM)

3 labs · Scaling manual review with Prowler, then turning findings into a plan
4.1
Auditing Your Account With ProwlerThe same class of tool a real cloud security team runs continuously
ObjectiveRun an automated cloud security scan and read its output like a triage queue, not a checklist.AWSCLI
  1. Install Prowler

    If you haven't already from Lab 0.2.

  2. Grant read-only audit access

    Attach the AWS-managed SecurityAudit and ViewOnlyAccess policies to your lab IAM user — enough to see everything, not enough to change anything.

  3. Run a full scan

    Against your account.

  4. Generate an HTML report

    And open it.

  5. Read the top 10 by severity

    Note how many map directly to what you found manually in Modules 1–2.

# run a full AWS scan with HTML output
prowler aws --output-formats html json --output-directory ./prowler-results
OutputWhat To Do With It
HTML reportBest for a first read-through — filterable by severity and service
JSON outputBest for feeding into another tool or tracking findings over time
High/Critical findingsCross-check against your Module 1–2 manual findings — overlap confirms you found real issues
💡
Prowler will surface things you didn't find manually — that's the point of automation. The manual skill from Modules 1–3 is what lets you tell a genuine finding from noise once Prowler hands you a list of 80.
4.2
Mapping Findings to a FrameworkProwler output → NIST CSF functions
ObjectiveTie Prowler's output to a compliance framework — the same NIST CSF functions from your earlier workbook, applied to a live finding set.AWSCLI
  1. List supported frameworks

    Prowler supports several compliance frameworks for AWS.

  2. Re-run scoped to one framework

    E.g. CIS or NIST 800-53.

  3. Map five findings to NIST CSF functions

    Identify, Protect, Detect, Respond, Recover — using what you already know.

  4. Recognize the real-world parallel

    This mapping is exactly what auditors expect walking into Meridian's SOC 2 review.

# list available compliance frameworks for AWS
prowler aws --list-compliance

# run scoped to a specific framework
prowler aws --compliance cis_2.0_aws
Finding TypeTypical NIST CSF Function
Public S3 bucketProtect
No MFA on IAM usersProtect
CloudTrail disabledDetect
No incident response runbook for cloudRespond
No tested backup/restore for critical dataRecover
📋
This is the exact bridge between your existing NIST CSF workbook and this one — a framework on paper only matters once you can point it at real findings from a real account.
4.3
Building a Remediation PlanFrom a wall of findings to a plan engineering can execute
ObjectiveTurn your top findings into a remediation plan Meridian's engineering team can actually execute against the 90-day deadline.
  1. Take your top 5 Critical/High findings

    From Lab 4.1.

  2. Write five fields per finding

    The finding, the business risk in plain language, the specific fix, an owner role, a target date relative to the 90-day deadline.

  3. Flag quick wins vs. projects

    Fixable in under an hour, versus needing a structural project (e.g. account-wide key rotation).

  4. Sequence the plan

    Quick wins first, so visible progress happens before the audit even if everything isn't finished.

ColumnWhat Belongs There
FindingExactly what Prowler/your manual review found, in one line
Business riskWhat actually happens if this isn't fixed — no jargon
FixThe specific configuration change, not "improve security"
Owner role"Platform team", not "fix it" — someone has to own it
Target dateTied to the 90-day deadline, not open-ended
🎯
A remediation plan a non-technical executive can read end-to-end without translation is the actual deliverable of a cloud security engagement — the scan is just how you got the inputs.
🌐

Module 5 – Multi-Cloud Expansion

3 labs · The same root causes, on Azure and GCP — plus the closing capstone
5.1
Azure Misconfiguration Practice with AzureGoatSame skill, Azure's identity model
ObjectiveAs Meridian expands into Azure, practice the same misconfiguration-hunting skill on a different provider's IAM model.AzureYour Account
  1. Create an Azure free account

    And set a budget alert immediately — same discipline as Lab 0.2.

  2. Install the Azure CLI

    And log in.

  3. Clone AzureGoat and deploy with Terraform

    Into a dedicated resource group.

  4. Work through identity-related escalation paths

    App registrations and managed identities — the closest analog to Module 1's AWS IAM work.

  5. Destroy the resource group

    Completely, when finished.

git clone https://github.com/ine-labs/AzureGoat.git
cd AzureGoat

# log in and create a dedicated resource group first
az login
az group create --name azuregoat_app --location eastus

terraform init
terraform apply
ConceptAWS Equivalent (Earlier Modules)
Azure AD App RegistrationIAM Role
Managed IdentityEC2 Instance Profile
Storage Account public accessS3 Bucket public access
Azure Activity LogCloudTrail
💡
The console screens differ completely between AWS and Azure — the underlying questions ("what can this identity actually do," "is this storage public," "are we logging the right things") are identical. That transferable instinct is what Module 5 is really testing.
5.2
GCP Misconfiguration Practice with GCPGoatCompleting the three-provider picture
ObjectiveComplete the three-provider picture by practicing the same skill on Google Cloud's IAM and storage model.GCPYour Account
  1. Create a GCP free trial account

    And set a budget alert.

  2. Install the gcloud CLI

    And authenticate.

  3. Clone GCPGoat and deploy with Terraform

    Into a dedicated project.

  4. Work through IAM roles, storage, and Cloud Functions

    The three areas its modules focus on.

  5. Destroy every resource

    And consider deleting the dedicated project entirely.

git clone https://github.com/ine-labs/GCPGoat.git
cd GCPGoat

gcloud auth login
gcloud config set project [your-dedicated-project-id]

terraform init
terraform apply
ConceptAWS EquivalentAzure Equivalent
GCP IAM RoleIAM PolicyAzure RBAC Role
Cloud Storage BucketS3 BucketStorage Account / Blob
Cloud FunctionsLambdaAzure Functions
Cloud Audit LogsCloudTrailActivity Log
📋
By now you've found the same handful of root causes — over-permissioned identity, public storage, missing logging — across three completely different consoles. That repetition is the actual lesson of Module 5.
5.3
Cross-Cloud CapstoneComparing all three providers, and closing the engagement
ObjectiveClose the engagement by comparing all three providers' default security posture and briefing Meridian on what "secure by default" means going into a multi-cloud future.
  1. Re-run Prowler multi-cloud

    Against any of the three accounts you still have available.

  2. Note one default-secure and one default-open setting per provider

    Based on what you actually saw, not general reputation.

  3. Write a comparison brief

    Which provider's defaults would you trust most out of the box, and why?

  4. Tear down everything, everywhere

    Confirm via each provider's console, not just CLI output.

ProviderSecure-By-Default TodayStill Requires Explicit Config
AWSS3 Block Public Access (new buckets)IAM least-privilege, CloudTrail beyond 90-day default
AzureStorage account public access often off on newer accountsRBAC scoping, diagnostic logging
GCPCloud Storage uniform bucket-level accessIAM role bindings, Cloud Audit Logs export
🎯
Engagement complete when: every CloudGoat/AzureGoat/GCPGoat/flAWS2 resource is destroyed and confirmed gone in each provider's console, and you can brief Meridian's leadership on IAM, storage, and logging posture across all three clouds in under five minutes.

🎉 Engagement Complete — Operation: OPEN BUCKET

Meridian Retail Group is audit-ready. You've reviewed IAM, closed storage exposure, turned on logging, automated the audit, and scoped the multi-cloud expansion — the same loop a real Cloud Security Engineer runs on every account they inherit.