Chapter 5 — Cloud and container security: tools and interpretation
Lesson map
Lesson 05 published. Map, example, EX021.
flowchart TD
N0["Learning outcomes"]
N1["5.1 The data"]
N2["Lab — role usage"]
N3["5.2 Reading the result"]
N4["5.3 Interpreting"]
N5["5.4 Checking with owners"]
N6["Removal plan"]
N7["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX021"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["5.1 The data"]
N2["Lab — role usage"]
N3["5.2 Reading the result"]
N4["5.3 Interpreting"]
N5["5.4 Checking with owners"]
N6["Removal plan"]
N7["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX021"]
[Learning outcomes]
|
v
[5.1 The data]
|
v
[Lab — role usage]
|
v
[5.2 Reading the result]
|
v
[5.3 Interpreting]
|
v
[5.4 Checking with owners]
|
v
[Removal plan]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX021]
Learning outcomes
You will (1) interpret permission usage data; (2) identify unused permissions; (3) plan safe removals.
5.1 The data
Hannah prepares a synthetic summary of three roles: permits-app (used by web and worker), reporting and deploy-bot, with permissions granted and used over 90 days. The synthetic summary mirrors the shape of the real exports without exposing them, so the course lab can be shared with Kingsbridge assessors. Each role lists the permissions it was granted and those that appear in the usage logs. Comparing the two sets for each role shows which permissions were never used during the ninety days.
Lab — role usage
"""Compare granted and used permissions for synthetic cloud roles over 90 days (stdlib only)."""
roles = {"permits-app": ({"db.read", "db.write", "storage.read", "storage.write", "storage.admin", "queue.send"},
{"db.read", "db.write", "storage.read", "queue.send"}),
"reporting": ({"db.read", "storage.read", "iam.admin"}, {"db.read"}),
"deploy-bot": ({"cluster.deploy", "registry.push", "registry.delete", "iam.admin"}, {"cluster.deploy", "registry.push"})}
tg = tu = 0
for r, (g, u) in roles.items():
tg += len(g); tu += len(g & u)
print(f"{r}: used {len(g & u)}/{len(g)}; unused: {', '.join(sorted(g - u))}")
print(f"overall unused {tg-tu}/{tg} ({(tg-tu)/tg*100:.0f}%)")
Run with python3 lab_roles.py. Verified output:
permits-app: used 4/6; unused: storage.admin, storage.write
reporting: used 1/3; unused: iam.admin, storage.read
deploy-bot: used 2/4; unused: iam.admin, registry.delete
overall unused 6/13 (46%)
5.2 Reading the result
Six of thirteen permissions (46%) were unused. Permits-app never used storage.admin or storage.write; reporting never used iam.admin or storage.read; deploy-bot never used iam.admin or registry.delete. The lab counts permissions granted but not used; it does not show whether they are needed for rare tasks. Hannah treats each unused permission as a candidate for removal and lists them by role, ready to check with the owners. The two iam.admin grants stand out, because they belong to roles that have no reason to manage permissions. 46% unused is high but common for roles that grew during early development. The aim is not zero for its own sake, but no unused high-risk permissions.
5.3 Interpreting
The two iam.admin grants are the most dangerous: they allow changing permissions, which could let a compromised workload give itself more access. Storage.admin could change bucket policies. Storage.admin is a concern because the bucket holds residents' proof-of-address documents, so a change to its policy could expose them. Registry.delete could let a compromised deploy bot remove images the service depends on. Hannah ranks the removals by what each permission could do if misused, which puts the iam.admin grants first.
5.4 Checking with owners
The digital team confirms storage.write is needed only for a yearly archive job; it is moved to a separate, rarely used role. Registry.delete is used manually by Dev for clean-ups and can be removed from the bot. The reporting team confirms that neither iam.admin nor storage.read is needed, since the job reads only from the database. Checking with owners turns the unused list into decisions each owner has agreed. Hannah records each owner's answer with the date, so audit can see that every removal was confirmed before it happened. The role summary is shared with each owning team before any change.
Removal plan
Removals are scheduled one role at a time, each on a weekday morning with the owning team available. Each change is tested in staging first with the team running their normal tasks. If anything fails, the permission is restored immediately and the failure is analysed before trying again.
Hannah records each removal with the evidence used, the owner's confirmation and the test result.
Worked example
The reporting team asks why iam.admin was there. History shows it was added during an early test and never removed. They agree to remove it.
Synthetic case. Synthetic.
Errors and limits
Usage data shows what happened, not what is needed; confirm with owners.
Exercises
- EX021 — Lab total. What share of permissions was unused? Rubric: 3 = 6/13 (46%); 2 = partial; 1 = vague; 0 = none.
- EX022 — Most dangerous. Which unused permissions were most dangerous and why? Rubric: 3 = iam.admin; can change permissions; 2 = partial; 1 = vague; 0 = none.
- EX023 — Yearly job. How was storage.write handled? Rubric: 3 = moved to separate rarely used role; 2 = partial; 1 = vague; 0 = none.
- EX024 — Registry delete. Why could registry.delete be removed from the bot? Rubric: 3 = Dev does clean-ups manually; 2 = partial; 1 = vague; 0 = none.
- EX025 — Origin. Why was iam.admin on reporting? Rubric: 3 = early test, never removed; 2 = partial; 1 = vague; 0 = none.
Synthesis
Read usage data, then confirm with owners before removing.
Continue studying — chapter 05 of 12
← Chapter 04 (draft) · Course chapter index · Chapter 06 (draft) →