Lab 01 — Cloud IAM Attack Path Solver

Operation Cedar Lattice, Phase 09. FIN-LATTICE has a foothold on the Meridian Freight CI/CD runner. The runner has the meridian-cicd-runner IAM role. Your job is to implement a graph-solver that finds the lowest-detection-cost path through the IAM permission graph from the compromised principal to the target resource — and maps every edge to its CloudTrail event.

Safety boundary. This lab operates entirely on synthetic Python dictionaries representing IAM permission graphs. No real cloud credentials. No real API calls. No deployable exploit. The output is an attack path report and CloudTrail detection mapping.


Objective

Implement four functions in lab.py:

FunctionDescription
can_reach(graph, start, target)BFS: is there any permission path from start to target?
attack_path(graph, start, target)Dijkstra: find lowest-detection-cost path
privilege_escalation_edges(graph)Filter edges whose action is a known privesc primitive
detection_for_edge(edge)Return CloudTrail event description for an edge

Graph Format

graph = {
    "nodes": ["dev-user", "ec2-role", "admin-role", "s3-data"],
    "edges": [
        {"principal": "dev-user", "action": "sts:AssumeRole",
         "resource": "ec2-role", "condition": None},
        {"principal": "ec2-role", "action": "iam:AttachUserPolicy",
         "resource": "admin-role", "condition": None},
        {"principal": "admin-role", "action": "s3:GetObject",
         "resource": "s3-data", "condition": None},
    ]
}

An edge {principal: A, action: X, resource: B} means: principal A has permission X on resource B. When resource B is itself a principal (e.g., an IAM role), reaching B means you can use B's edges. This is the IAM sts:AssumeRole mechanic: assuming a role gives you that role's permissions.


Visibility Costs

Each action has a detection cost (lower = less visible in SIEM):

ActionCostReason
sts:AssumeRole, s3:GetObject, s3:ListBucket, ec2:DescribeInstances1Extremely common; low signal
lambda:InvokeFunction2Common in automated workloads
lambda:CreateFunction, iam:PassRole3Less common, moderate signal
iam:CreateLoginProfile4High signal — creating console access
iam:CreatePolicyVersion, iam:AttachUserPolicy, iam:AttachRolePolicy, etc.5Very high signal IAM writes

attack_path minimizes total cost across the path.


Running the Lab

pip install -r requirements.txt

# Run your implementation (should raise NotImplementedError until you implement):
pytest -q

# Run reference solution:
LAB_MODULE=solution pytest -q

Deliverable

When all 12 tests pass with LAB_MODULE=solution pytest -q, you understand how to:

  • Model IAM as a directed graph and perform BFS reachability analysis
  • Apply Dijkstra to find the stealthiest path (fewest SIEM-detectable events)
  • Identify privilege escalation primitives in a permission graph
  • Map each attack step to its specific CloudTrail event

« Phase 09 README | Lab 02: IMDS & Container Escape »