Chapter 29 — Cloud and container security: measurement
Lesson map
Lesson 29 published. Map, example, EX085.
flowchart TD
N0["Learning outcomes"]
N1["29.1 Coverage measures"]
N2["Lab — Lab — control coverage"]
N3["29.2 Lab result"]
N4["29.3 Interpreting"]
N5["29.4 Weighting"]
N6["29.5 Trends"]
N7["Sensitivity weighting"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX085"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["29.1 Coverage measures"]
N2["Lab — Lab — control coverage"]
N3["29.2 Lab result"]
N4["29.3 Interpreting"]
N5["29.4 Weighting"]
N6["29.5 Trends"]
N7["Sensitivity weighting"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX085"]
[Learning outcomes]
|
v
[29.1 Coverage measures]
|
v
[Lab — Lab — control coverage]
|
v
[29.2 Lab result]
|
v
[29.3 Interpreting]
|
v
[29.4 Weighting]
|
v
[29.5 Trends]
|
v
[Sensitivity weighting]
|
v
[Worked example] --> [Exercise EX085]
Learning outcomes
You will (1) define control coverage measures; (2) compute coverage per namespace; (3) track progress; (4) interpret measures carefully.
29.1 Coverage measures
For each production namespace, Elena records whether four controls are in place: default-deny network policy, Restricted pod security, image signature enforcement and resource limits on all pods.
These four controls address the main risks found earlier: open networking, risky pod settings, unverified images and unbounded resource use. Recording them per namespace shows where each service stands. Elena chooses controls that can be checked automatically from cluster configuration, so the measure stays current without manual effort. She writes down the exact test for each control, so the same configuration always gives the same answer.
Lab — Lab — control coverage
"""Control coverage per namespace for four controls (stdlib only)."""
ctrl = ["netpol-default-deny", "pod-security-restricted", "image-signature", "resource-limits"]
ns = {"meterhub": [1, 1, 1, 1], "billing": [1, 1, 0, 1], "reports": [0, 1, 0, 1], "legacy-import": [0, 0, 0, 1]}
for n, v in ns.items():
miss = [c for c, x in zip(ctrl, v) if not x]
print(f"{n:14} {sum(v)}/4 {'missing: ' + ', '.join(miss) if miss else ''}")
allv = [x for v in ns.values() for x in v]
print(f"overall coverage {sum(allv)}/{len(allv)} = {100*sum(allv)/len(allv):.0f}%")
Run with python3 lab_coverage.py. Verified output:
meterhub 4/4
billing 3/4 missing: image-signature
reports 2/4 missing: netpol-default-deny, image-signature
legacy-import 1/4 missing: netpol-default-deny, pod-security-restricted, image-signature
overall coverage 10/16 = 62%
29.2 Lab result
meterhub has 4 of 4 controls. billing has 3 of 4 (missing image-signature). reports has 2 of 4 (missing netpol-default-deny and image-signature). legacy-import has 1 of 4 (missing netpol-default-deny, pod-security-restricted and image-signature). Overall coverage is 10 of 16 controls, 62%.
Ten of sixteen means six control gaps remain. Image signatures are missing in three namespaces, so that control is the most common gap. legacy-import has the most work, missing three of four. Elena uses these results to plan the next rollout steps, starting with the gaps that affect the most sensitive services.
29.3 Interpreting
Coverage says a control is configured, not that it is effective; an allow-all policy would count as a policy. Elena's checker therefore requires a default-deny policy specifically, and verification tests (later chapters) check behaviour.
A coverage figure can look good while protection is weak, if controls are present in name only. Requiring a specific default-deny policy prevents an allow-all policy from counting. Behaviour tests in the laboratory then check that controls actually block what they should. Coverage and effectiveness together give a truer picture.
29.4 Weighting
Namespaces differ in sensitivity; a missing control in billing matters more than in reports. The dashboard shows both raw and sensitivity-weighted coverage.
Treating all namespaces equally would make a gap in a low-risk service look as serious as one in billing. Weighting by sensitivity directs attention to where harm would be greatest. Showing both raw and weighted figures lets readers see progress overall and where it matters most. Sensitivity weights come from the data model's classes: namespaces holding readings or payment data count three times as much as internal tools.
29.5 Trends
Monthly coverage is plotted; a drop signals new namespaces without controls or removed controls.
A single month's figure shows status; a trend shows direction. A falling trend often means new namespaces were created without the standard controls, pointing to a gap in the onboarding process. A rising trend shows the rollout working. Elena adds a note to each month explaining any significant change. Trend charts go to Solent's managers each month with a one-line summary. When coverage falls, the summary names the namespaces responsible and the action planned, so the chart prompts decisions rather than just reporting a number.
Sensitivity weighting
Weights are set with the data protection officer: namespaces handling readings or payments count three times, others once. Weighted coverage starts at 58%, lower than raw coverage, because the biggest gaps are in billing. This helps focus effort where data are most sensitive. Elena reports both numbers so neither hides the other.
Reporting cadence
Coverage is reported monthly to the platform lead and quarterly to Solent's risk committee, with the causes of gaps and the plan for each.
Worked example
The image-signature gap across three namespaces traces to one cause: their images were built by an older pipeline without signing. Moving them to the standard pipeline closes all three gaps in a sprint, raising coverage to 13 of 16.
Synthetic case. Namespaces and figures are synthetic.
Errors and limits
Measures can be gamed; check what each one counts.
Exercises
- EX085 — Lab overall. What was overall coverage? Rubric: 3 = 10/16, 62%; 2 = partial; 1 = vague; 0 = none.
- EX086 — legacy-import. What was legacy-import missing? Rubric: 3 = netpol, pod security, image signature; 2 = two; 1 = one; 0 = none.
- EX087 — Signature cause. Why were signatures missing? Rubric: 3 = older pipeline without signing; 2 = partial; 1 = vague; 0 = none.
Synthesis
Measure coverage, then check effectiveness.
Continue studying — chapter 29 of 50
← Chapter 28 (draft) · Course chapter index · Chapter 30 (draft) →