Chapter 2 — Cloud and container security: advanced seminar
Lesson map
Lesson 02 published. Map, example, EX008.
flowchart TD
N0["Learning outcomes"]
N1["2.1 Access control models"]
N2["2.2 Least privilege in practice"]
N3["Lab — permission use"]
N4["2.3 Lab result"]
N5["2.4 Zero trust"]
N6["2.5 Seminar argument"]
N7["Access history quality"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX008"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["2.1 Access control models"]
N2["2.2 Least privilege in practice"]
N3["Lab — permission use"]
N4["2.3 Lab result"]
N5["2.4 Zero trust"]
N6["2.5 Seminar argument"]
N7["Access history quality"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX008"]
[Learning outcomes]
|
v
[2.1 Access control models]
|
v
[2.2 Least privilege in practice]
|
v
[Lab — permission use]
|
v
[2.3 Lab result]
|
v
[2.4 Zero trust]
|
v
[2.5 Seminar argument]
|
v
[Access history quality]
|
v
[Worked example] --> [Exercise EX008]
Learning outcomes
You will (1) discuss access control, least privilege and configuration in depth; (2) analyse permission use; (3) connect identity to storage exposure; (4) present a seminar argument.
2.1 Access control models
Sandhu et al. (1996) formalised role-based access control, where permissions attach to roles rather than individuals. Cloud platforms implement roles and policies at large scale. NIST SP 800-210 gives guidance specific to cloud systems, including managing access across service models. For Lucas, the relevance is that bucket access settings are themselves permissions held by roles. If many roles can change those settings, the number of paths to an exposure grows whatever tool is used. This is the basis of explanation C later in the study, and it is why he measures identities with storage administration rights per account.
2.2 Least privilege in practice
A role that holds permissions it never uses widens what an error or stolen credential can do. Cloud providers offer access history that shows which permissions were used, which allows evidence-based trimming. The lab measures this for three synthetic roles at Larkspur. The seminar later adds a caution: a permission unused in 90 days may still be needed for a quarterly task, so unused permissions become candidates for review with the owner rather than automatic removal. Lucas adds that nuance to his framework before the main study.
Lab — permission use
"""Compare granted and used permissions for synthetic cloud roles over 90 days (stdlib only)."""
roles = {
"ci-deployer": ({"storage.write", "storage.read", "compute.deploy", "iam.passRole", "logs.read"}, {"storage.write", "compute.deploy", "iam.passRole"}),
"analytics-job": ({"storage.read", "storage.write", "db.read", "db.admin"}, {"storage.read", "db.read"}),
"support-ro": ({"logs.read", "compute.describe"}, {"logs.read", "compute.describe"}),
}
tg = tu = 0
for r, (granted, used) in roles.items():
unused = sorted(granted - used)
tg += len(granted); tu += len(unused)
print(f"{r:14} granted {len(granted)}, used {len(used)}, unused: {', '.join(unused) or 'none'}")
print(f"unused share {tu}/{tg} = {100*tu/tg:.0f}%")
Run with python3 lab_iam.py. Verified output:
ci-deployer granted 5, used 3, unused: logs.read, storage.read
analytics-job granted 4, used 2, unused: db.admin, storage.write
support-ro granted 2, used 2, unused: none
unused share 4/11 = 36%
2.3 Lab result
Over 90 synthetic days, ci-deployer used 3 of 5 granted permissions (unused: logs.read, storage.read), analytics-job used 2 of 4 (unused: db.admin, storage.write) and support-ro used both of its 2. In total 4 of 11 granted permissions, 36%, went unused. The analytics job's unused storage.write matters for Lucas's question: a job that can write storage settings could also change them. Lucas reports the result as a property of three synthetic roles, not as a rate for Larkspur. Its value for the study is the method: access history can show which identities hold storage-changing rights they do not use.
2.4 Zero trust
NIST SP 800-207 argues that access should be decided per request using identity and context, not network location. For storage, that means private by default, with access granted to named identities. At Larkspur this principle points to two controls that later appear in Lucas's recommendations: blocking public access by default at account level, and granting bucket access to named identities instead of to everyone. Both work regardless of whether a change comes through the console or a template, which is why they address all three explanations at once.
2.5 Seminar argument
Lucas argues that exposure is partly an identity problem: if few identities can change bucket access settings, fewer paths to exposure exist, regardless of console or IaC. His seminar peers accepted the argument but challenged the 90-day usage window as a measure of need. Lucas therefore kept identity breadth as a separate explanation to test, counting identities with storage administration rights per account, instead of folding it into either of the platform team's or data team's explanations. Counting breadth does not depend on usage logs, so it stays testable even if the 90-day window is a poor measure of need.
Access history quality
Access history can omit some actions, so Lucas checks the provider documentation for gaps before relying on it.
Worked example
Seminar peers challenge him: unused permissions over 90 days may still be needed for rare tasks such as quarterly reports. Lucas agrees to treat unused permissions as candidates for review with the owner, not automatic removal, and adds this nuance to his framework.
Synthetic case. Roles and usage are synthetic.
Errors and limits
Absence of use in a window is not proof a permission is unneeded.
Exercises
- EX008 — RBAC idea. What is the core RBAC idea? Rubric: 3 = permissions attach to roles; 2 = partial; 1 = vague; 0 = none.
- EX009 — Lab share. What share of permissions went unused? Rubric: 3 = 4/11, 36%; 2 = partial; 1 = vague; 0 = none.
- EX010 — analytics-job. Which permissions did analytics-job not use? Rubric: 3 = db.admin, storage.write; 2 = partial; 1 = vague; 0 = none.
- EX011 — Why storage.write. Why does analytics-job's unused storage.write matter? Rubric: 3 = could change bucket settings; 2 = partial; 1 = vague; 0 = none.
- EX012 — ZTA for storage. What does zero trust mean for storage? Rubric: 3 = private by default, named identities; 2 = partial; 1 = vague; 0 = none.
- EX013 — Peer challenge. What did peers challenge? Rubric: 3 = rare tasks need unused permissions; 2 = partial; 1 = vague; 0 = none.
- EX014 — Response. How did Lucas respond? Rubric: 3 = review with owner, not auto-remove; 2 = partial; 1 = vague; 0 = none.
Synthesis
Identity and least privilege shape how exposures can happen.
Continue studying — chapter 02 of 08
← Chapter 01 (draft) · Course chapter index · Chapter 03 (draft) →