Chapter 11 — Cloud and container security: verification
Lesson map
Lesson 11 published. Map, example, EX041.
flowchart TD
N0["Learning outcomes"]
N1["11.1 Why verify"]
N2["Lab — bucket verification"]
N3["11.2 Reading the result"]
N4["11.3 Acting"]
N5["11.4 Re-check"]
N6["Why verification found more"]
N7["Evidence of fixes"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX041"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["11.1 Why verify"]
N2["Lab — bucket verification"]
N3["11.2 Reading the result"]
N4["11.3 Acting"]
N5["11.4 Re-check"]
N6["Why verification found more"]
N7["Evidence of fixes"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX041"]
[Learning outcomes]
|
v
[11.1 Why verify]
|
v
[Lab — bucket verification]
|
v
[11.2 Reading the result]
|
v
[11.3 Acting]
|
v
[11.4 Re-check]
|
v
[Why verification found more]
|
v
[Evidence of fixes]
|
v
[Worked example] --> [Exercise EX041]
Learning outcomes
You will (1) verify that controls are in place; (2) compare bucket settings with policy; (3) report differences.
11.1 Why verify
Configuring is not the same as confirming. Tomás verifies each bucket against the policy. A change applied through the repository can still fail, be overridden or miss a bucket nobody knew existed. Verification compares each bucket's live settings with the four policy rules and lists every difference, without judging which ones matter. That judgement comes afterwards, with the data labels from the system model. The lab below uses synthetic settings for four buckets that mirror Fairway's real ones. Running it daily turns a one-off check into ongoing assurance.
Lab — bucket verification
"""Verify synthetic bucket settings against Fairway's storage policy (stdlib only)."""
policy = {"block_public_access": True, "encryption": True, "versioning": True, "access_logging": True}
buckets = {"manifests": {"block_public_access": True, "encryption": True, "versioning": False, "access_logging": True},
"site-assets": {"block_public_access": False, "encryption": True, "versioning": True, "access_logging": False},
"backups": {"block_public_access": True, "encryption": True, "versioning": True, "access_logging": True},
"driver-photos": {"block_public_access": True, "encryption": False, "versioning": False, "access_logging": False}}
total = 0
for b, s in buckets.items():
f = [k for k in policy if s[k] != policy[k]]; total += len(f)
print(f"{b}: {'OK' if not f else 'differs: ' + ', '.join(f)}")
print(f"{total} differences across {len(buckets)} buckets")
Run with python3 lab_verify.py. Verified output:
manifests: differs: versioning
site-assets: differs: block_public_access, access_logging
backups: OK
driver-photos: differs: encryption, versioning, access_logging
6 differences across 4 buckets
11.2 Reading the result
Six differences across four buckets. Manifests lacks versioning. Site-assets has no public block, which is expected under its exception, and no access logging. Backups passes. Driver-photos lacks encryption, versioning and logging. The figure of six comes from one difference on manifests, two on site-assets and three on driver-photos. Only one of the six, the public access on site-assets, is intended. The remaining five are real gaps, and driver-photos alone accounts for three of them. The script reports differences in dictionary order; Tomás reorders them by sensitivity in his report.
11.3 Acting
Driver-photos is the most serious because it holds personal data unencrypted. It is fixed first. Site-assets logging is added; its public access is recorded as the approved exception. Order follows data sensitivity: personal data without encryption first, then the missing versioning on manifests, then logging on site-assets. Each fix goes through the repository and is tested in staging, like the earlier configuration changes. The exception is recorded with an owner and an annual review date. Driver-photos is fixed with the HR owner present, since the photos are their data.
11.4 Re-check
After fixes, the check shows only the approved exception. The rerun shows one remaining difference, site-assets without a public access block, which matches the recorded exception. That result is saved with the date as evidence that the fixes took effect, not just that changes were submitted. Tomás compares it with the first run so the drop from six differences to one is documented. Each bucket owner signs the result for their bucket, and the confirmations are stored with the evidence. From then on, the daily run shows whether the count stays at one or creeps up again.
Why verification found more
The original incident concerned only manifests, but verification across all buckets found problems elsewhere. This is common: one incident reveals a pattern. Checking every bucket against the same policy finds similar gaps before they cause their own incidents.
Tomás reports the findings in order of data sensitivity, not in the order the script prints them, so readers see the most important first.
Evidence of fixes
After fixes, the check output is saved as evidence, alongside the change records.
Exceptions register
The site-assets exception is recorded with owner, reason and annual review date.
Next run
The check is scheduled daily so new buckets are covered automatically.
Lessons
Tomás recommends checking every similar resource after any incident.
Worked example
Grace asks why driver-photos was missed. Tomás finds it was created by a mobile app project using a copied example with no encryption setting.
Synthetic case. Synthetic.
Errors and limits
Verification checks settings, not that data was never exposed.
Exercises
- EX041 — Lab total. How many differences, across how many buckets? Rubric: 3 = 6 across 4; 2 = partial; 1 = vague; 0 = none.
- EX042 — Worst bucket. Which bucket was fixed first and why? Rubric: 3 = driver-photos; personal data unencrypted; 2 = partial; 1 = vague; 0 = none.
- EX043 — Approved exception. Which difference is acceptable? Rubric: 3 = site-assets public access; 2 = partial; 1 = vague; 0 = none.
- EX044 — Root cause. Why was driver-photos misconfigured? Rubric: 3 = copied example; 2 = partial; 1 = vague; 0 = none.
Synthesis
Verify after configuring, and fix the worst first.
Continue studying — chapter 11 of 18
← Chapter 10 (draft) · Course chapter index · Chapter 12 (draft) →