Chapter 7 — Cloud and container security: data and telemetry
Lesson map
Lesson 07 published. Map, example, EX025.
flowchart TD
N0["Learning outcomes"]
N1["7.1 Audit events"]
N2["Lab — storage events"]
N3["7.2 Reading the result"]
N4["7.3 Interpreting the reads"]
N5["7.5 Reporting"]
N6["Preserving the timeline"]
N7["Clock alignment"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX025"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["7.1 Audit events"]
N2["Lab — storage events"]
N3["7.2 Reading the result"]
N4["7.3 Interpreting the reads"]
N5["7.5 Reporting"]
N6["Preserving the timeline"]
N7["Clock alignment"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX025"]
[Learning outcomes]
|
v
[7.1 Audit events]
|
v
[Lab — storage events]
|
v
[7.2 Reading the result]
|
v
[7.3 Interpreting the reads]
|
v
[7.5 Reporting]
|
v
[Preserving the timeline]
|
v
[Clock alignment]
|
v
[Worked example] --> [Exercise EX025]
Learning outcomes
You will (1) read cloud storage audit events; (2) reconstruct a timeline; (3) count exposure and access.
7.1 Audit events
Cloud providers can record management actions, such as policy changes, and data access, such as object reads. Fairway had data access logging enabled on the manifests bucket, which makes the timeline possible. Management events, such as the PutBucketPolicy changes, are recorded by default; object reads appear only where data access logging is switched on. Without that logging on manifests, the two anonymous reads would have left no trace, and the timeline would end with an unanswerable question about who downloaded files.
Lab — storage events
"""Summarise synthetic cloud storage audit events and flag public-access changes (stdlib only)."""
events = [("2026-03-02 09:14", "dev-sam", "PutObject", "manifests"), ("2026-03-02 09:20", "dev-sam", "PutObject", "manifests"),
("2026-03-03 16:41", "dev-sam", "PutBucketPolicy:public-read", "manifests"),
("2026-03-04 08:05", "ci-deploy", "PutObject", "site-assets"), ("2026-03-05 11:30", "anonymous", "GetObject", "manifests"),
("2026-03-05 11:31", "anonymous", "GetObject", "manifests"), ("2026-03-06 10:02", "grace", "PutBucketPolicy:private", "manifests"),
("2026-03-06 10:05", "ci-deploy", "PutObject", "site-assets")]
print(f"events {len(events)}")
for t, who, act, b in events:
if "PutBucketPolicy" in act or who == "anonymous":
print(f" {t} {who:10} {act:28} {b}")
pub = [e for e in events if e[2].endswith("public-read")][0][0]; fix = [e for e in events if e[2].endswith("private")][0][0]
print(f"public from {pub} to {fix}; anonymous reads {sum(1 for e in events if e[1]=='anonymous')}")
Run with python3 lab_events.py. Verified output:
events 8
2026-03-03 16:41 dev-sam PutBucketPolicy:public-read manifests
2026-03-05 11:30 anonymous GetObject manifests
2026-03-05 11:31 anonymous GetObject manifests
2026-03-06 10:02 grace PutBucketPolicy:private manifests
public from 2026-03-03 16:41 to 2026-03-06 10:02; anonymous reads 2
7.2 Reading the result
Of 8 events, 4 matter. dev-sam set the bucket policy to public-read on 3 March at 16:41. Two anonymous reads followed on 5 March at 11:30 and 11:31. Grace set the policy back to private on 6 March at 10:02. The bucket was public for about two days and seventeen hours. Only the policy changes and anonymous reads matter for exposure; the other four events are routine uploads by dev-sam and CI deploy. The script counts the exposure from the public-read change to the private change, which Tomás checks by hand: 3 March 16:41 to 6 March 10:02 is two days, seventeen hours and twenty-one minutes.
7.3 Interpreting the reads
The two anonymous reads could be the partner, who was sent the link, or someone else. The records show the source network for each request; Tomás compares them with the partner's published address range and finds they match the partner. Matching an address range is strong but not complete evidence, since another user on the partner's network would match as well. Tomás records the match as the basis for the conclusion and lists that limit beside it. The data protection lead then decides with both in view.
7.4 Limits
Logs show requests that reached the service. They do not prove that no other copies exist, for example if the partner forwarded the file. The two reads are the whole picture only for this bucket and only for requests the provider logged. Copies made by the partner after downloading, or shared within their company, are outside Fairway's logs. Other buckets had no data access logging during the period, so any reads there cannot be checked at all, as the evidence register notes.
7.5 Reporting
The timeline is written in plain words with times, sources and the limit stated. Tomás's timeline gives four lines: the public-read change by dev-sam at 16:41 on 3 March, two anonymous reads on 5 March at 11:30 and 11:31 matched to the partner, and Grace's private change at 10:02 on 6 March. Each line names its log source, so a reader can check it in the export. A closing line states that the logs cannot show copies made after download. Grace reads the draft and asks for one change: stating the time zone at the top. Tomás adds UTC with local time beside it, as the clock alignment note requires.
Preserving the timeline
The exported events and timeline are kept read-only with the evidence register.
Clock alignment
Provider log times are in UTC; Tomás converts them to local time and states both in the timeline, so readers comparing staff notes are not confused.
Worked example
Grace asks whether customers must be told. Tomás presents the timeline and the partner match. Grace consults Fairway's data protection lead, who decides, based on the evidence, that the exposure was limited to an authorised partner and records the decision.
Synthetic case. Events and times are synthetic.
Errors and limits
Without data access logs, the reads would have been invisible; the absence of logs is not evidence of no access.
Exercises
- EX025 — Lab timeline. Give the start and end of exposure. Rubric: 3 = 3 March 16:41 to 6 March 10:02; 2 = partial; 1 = vague; 0 = none.
- EX026 — Anonymous reads. How many anonymous reads occurred and who made them? Rubric: 3 = two; matched partner range; 2 = partial; 1 = vague; 0 = none.
- EX027 — Log limit. What can the logs not prove? Rubric: 3 = no other copies; 2 = partial; 1 = vague; 0 = none.
- EX028 — Decision owner. Who decided on notification? Rubric: 3 = data protection lead; 2 = partial; 1 = vague; 0 = none.
Synthesis
Logs turn guesses into a timeline; state what they cannot show.
Continue studying — chapter 07 of 18
← Chapter 06 (draft) · Course chapter index · Chapter 08 (draft) →