Lesson map
Lesson 12 published. Map, example, EX023.
flowchart TD
N0["Learning outcomes"]
N1["12.1 Tracing flows"]
N2["12.2 The CBOM"]
N3["12.3 Practical activity — Lab I"]
N4["12.4 Controllers"]
N5["12.7 Keeping traces current"]
N6["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6
N6 --> EX["Worked example"]
EX --> Q["Exercise EX023"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["12.1 Tracing flows"]
N2["12.2 The CBOM"]
N3["12.3 Practical activity — Lab I"]
N4["12.4 Controllers"]
N5["12.7 Keeping traces current"]
N6["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> Q["EX023"]
[Learning outcomes]
|
v
[12.1 Tracing flows]
|
v
[12.2 The CBOM]
|
v
[12.3 Practical activity — Lab I]
|
v
[12.4 Controllers]
|
v
[12.7 Keeping traces current]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX023]
Learning outcomes
You will (1) trace data flows end to end across termination points; (2) build a cryptographic bill of materials (CBOM) from several sources; (3) compute coverage and unknown shares; and (4) identify which party controls each segment.
12.1 Tracing flows
A flow is protected only as strongly as its weakest segment. Trace shipment data from a customer's system through the CDN, origin load balancer, ingress, service mesh, message queue, database replication and backup copy. At each segment record protocol, key exchange, authentication, data lifetime and controller.
For KLS the trace of one shipment record has seven segments, and only the first was hybrid when the trace was drawn. The weakest-segment rule meant the flow was reported as classical, not as one-seventh migrated.
12.2 The CBOM
A CBOM lists, per asset and function, algorithm, parameters, implementation and evidence source. Build it by merging configuration exports, log summaries, image scans and vendor statements.
KLS's CBOM merges four feeds: ingress and load-balancer configuration exports, gateway handshake logs, registry image scans and vendor answers. Each row keeps its source, so a reader can see that the billing database's RSA-kex entry came from configuration while the scanner's key exchange came from passive capture. Conflicting rows are kept side by side and raise a task rather than being merged into one guessed value.
12.3 Practical activity — Lab I
# Lab I (ch 12): aggregate a synthetic cryptographic bill of materials (CBOM) and measure coverage.
records = [ # (asset, function, algorithm, source)
("api-gateway", "key-exchange", "X25519MLKEM768", "passive"), ("api-gateway", "signature", "RSA-2048", "config"),
("warehouse-scanner", "key-exchange", "ECDHE-P256", "passive"), ("warehouse-scanner", "signature", "ECDSA-P256", "code"),
("billing-db", "key-exchange", "RSA-kex", "config"), ("billing", "data-at-rest", "AES-256-GCM", "code"),
("forklift-telemetry", "unknown", "unknown", "none"), ("office-vpn", "key-exchange", "ECDHE-P384", "config")]
VULN = {"RSA-2048", "ECDHE-P256", "ECDSA-P256", "RSA-kex", "ECDHE-P384"}
assets = {r[0] for r in records}
unknown = {r[0] for r in records if r[2] == "unknown"}
vuln = [r for r in records if r[2] in VULN]
print(f"assets {len(assets)}, unknown {len(unknown)} ({100*len(unknown)/len(assets):.0f}%)")
print(f"quantum-vulnerable uses {len(vuln)}:", ", ".join(f"{a}/{f}" for a, f, _, _ in vuln))
print("hybrid key exchange present on:", [r[0] for r in records if "MLKEM" in r[2]])
Expected output:
assets 6, unknown 1 (17%)
quantum-vulnerable uses 5: api-gateway/signature, warehouse-scanner/key-exchange, warehouse-scanner/signature, billing-db/key-exchange, office-vpn/key-exchange
hybrid key exchange present on: ['api-gateway']
The forklift telemetry unit has no evidence at all; until the vendor answers, it stays unknown and blocks a tier decision for the warehouse network.
Lab I counts assets and uses separately, which matters for reporting. Six assets and eight uses produce two different denominators: one asset in six is unknown (17 %), while five uses in eight are quantum-vulnerable. The billing data-at-rest row, AES-256-GCM, is correctly absent from the vulnerable list. The api-gateway appears twice, as hybrid for key exchange and vulnerable for its RSA-2048 signature, which is the usual state of a service after its first migration step. Change one record to X25519MLKEM768 and rerun to see the counts move.
12.4 Controllers
KLS controls its load balancers, ingress and code; the CDN provider controls the edge; the cloud provider controls managed database replication; partners control their SFTP clients. Write controller next to every segment and open a ticket or vendor request for each segment KLS cannot change.
The controller column turns the trace into a work plan. Segments KLS controls get configuration tickets; segments others control get requests with a named contact and a follow-up date. For KLS, that meant tickets for the origin load balancer, ingress and Kafka, and requests to the CDN, the database provider and the object-storage SDK maintainers.
12.5 Worked example
Tracing a shipment record: customer API client → CDN edge (hybrid, CDN-controlled) → origin LB (classical, KLS) → ingress (classical, KLS) → API pod → Kafka (TLS classical, KLS) → managed Postgres replication (provider, algorithm undocumented) → nightly backup to object storage over HTTPS (provider SDK in KLS job, classical). Seven segments, four KLS can change, one unknown.
The four KLS-controlled segments, origin load balancer, ingress, Kafka and the backup job's SDK configuration, went into one sprint. The managed Postgres replication became a provider question with a deadline, and its unknown status kept the whole flow out of the migrated count until the provider answered in writing.
12.6 Common errors and limits
- Stopping the trace at the edge.
- Treating managed services as "secure by default" without evidence.
- Ignoring backup and replication paths.
Stopping at the edge produced KLS's first wrong claim that the customer path was hybrid. Treating the managed database as secure by default left its replication algorithm undocumented for months; "managed" says who operates it, not what it negotiates. And the nightly backup upload, carrying the same ten-year records, was missed entirely in the first trace because it runs from a batch job rather than a request path. Traces drawn from request paths alone routinely miss batch and replication traffic.
12.7 Keeping traces current
Architectures change faster than diagrams. Re-run the trace for each tier-1 flow whenever a hop is added or replaced — a new message queue, a new CDN feature, a migration from self-managed to managed databases — and add the trace to the change checklist for such work. Store the trace as structured data (segment, protocol, controller, algorithm, evidence) beside the CBOM so that a query can list every tier-1 flow with at least one classical or unknown segment. That query is the honest answer to "is this flow migrated?", because a single classical segment leaves the whole flow exposed to recording at that point.
Exercises
- EX023 — Unknown share. In Lab I, what share of crypto uses (not assets) is quantum-vulnerable? Rubric: 3 = 5 of 8 records ≈ 63 %, noting the unknown record.
- EX024 — Controller tickets. For the trace in this chapter's worked example, list the external requests KLS must open. Rubric: 3 = CDN (origin hop support), managed DB provider (replication crypto), object storage/SDK.
Synthesis
End-to-end traces and a multi-source CBOM show every segment's algorithm and controller; unknowns and external segments become explicit requests.
Continue studying — chapter 12 of 30
← Chapter 11 (draft) · Course chapter index · Chapter 13 (draft) →