Chapter 15 — Critical infrastructure and sector security: integration and dependencies
Lesson map
Lesson 15 published. Map, example, EX057.
flowchart TD
N0["Learning outcomes and connection"]
N1["15.1 Interdependency"]
N2["15.2 Dependencies as a graph"]
N3["15.4 Integration points are boundaries"]
N4["15.5 Practical activity"]
N5["Chapter synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Worked example"]
EX --> Q["Exercise EX057"]
Logical drawing
flowchart LR
N0["Learning outcomes and connection"]
N1["15.1 Interdependency"]
N2["15.2 Dependencies as a graph"]
N3["15.4 Integration points are boundaries"]
N4["15.5 Practical activity"]
N5["Chapter synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX057"]
[Learning outcomes and connection]
|
v
[15.1 Interdependency]
|
v
[15.2 Dependencies as a graph]
|
v
[15.4 Integration points are boundaries]
|
v
[15.5 Practical activity]
|
v
[Chapter synthesis]
|
v
[Worked example] --> [Exercise EX057]
Learning outcomes and connection
After this chapter you should be able to:
- model technical dependencies — virtualization, directory, time, storage, telecom, power — as a graph and compute what a single failure affects;
- find components shared across services and sectors, including indirect sharing through a dependency of a dependency;
- treat every integration point (station routers, carrier networks, vendor gateways, data exports) as a boundary to be modelled, controlled and monitored;
- turn a dependency analysis into concrete checks and controls.
Chapter 13 found a path to KW-04 that bypassed the firewall through a carrier network. That was a dependency nobody had drawn. This chapter draws them systematically.
15.1 Interdependency
Critical infrastructures depend on each other physically (power for pumps), through information (telemetry over a carrier network), geographically (shared ducts and sites) and logically (shared staff, software and administration). This classification comes from Rinaldi, Peerenboom and Kelly's widely cited paper (Rinaldi et al., 2001). For a technician the most frequent surprises are logical: a directory, a hypervisor cluster, a time source or a monitoring collector shared by systems whose owners each think it is theirs.
For a technician the most frequent surprises are logical: a directory, a hypervisor or a time source that several services share without any one owner claiming them. Draw those first, then the physical and carrier links. Lab 15 makes the shared nodes visible as counts across services.
15.2 Dependencies as a graph
Write each dependency as "A needs B". To find what fails when B fails, follow the edges backwards — everything that needs B, everything that needs those, and so on. That is a breadth-first search on the reversed graph. Two results matter: the set of services affected, and the path by which each is affected, because the path tells you where a control or a redundancy would break the chain.
Indirect sharing is the important case. In the KVROC model the hospital BMS server and the SCADA server both authenticate against ad-ops, which runs on esx-03, while the grid front end also runs on esx-03. No service owner lists esx-03 as "theirs"; all three depend on it.
15.3 Worked example: KVROC dependencies (synthetic)
Lab 15 (save as lab15.py, run with python3 lab15.py):
# Lab 15 - trace failure impact through technical dependencies (offline, standard library only)
# Synthetic dependency map for the Kestrel Vale operations centre: "A needs B" edges.
from collections import deque
needs = {
"water-telemetry": ["scada-01", "cell-router-kw", "fw-01"],
"scada-01": ["ad-ops", "ntp-ops", "hist-02", "esx-02"],
"hist-02": ["esx-02", "san-01"],
"hospital-bms": ["bms-server", "fw-02"],
"bms-server": ["esx-02", "ad-ops"],
"grid-ss3-telecontrol": ["fep-01", "telco-mpls"],
"fep-01": ["ntp-ops", "esx-03"],
"ad-ops": ["esx-03"],
"ntp-ops": ["gps-clock"],
}
def impacted(failed):
rev = {}
for a, bs in needs.items():
for b in bs: rev.setdefault(b, []).append(a)
seen, q = set(), deque([failed])
while q:
for a in rev.get(q.popleft(), []):
if a not in seen: seen.add(a); q.append(a)
return sorted(seen)
services = {"water-telemetry", "hospital-bms", "grid-ss3-telecontrol"}
for comp in ["esx-02", "esx-03", "gps-clock", "san-01", "telco-mpls"]:
hit = impacted(comp)
print(f"{comp:<10} -> services {sorted(services & set(hit))} via {len(hit)} dependants")
counts = {c: len(services & set(impacted(c))) for c in {b for bs in needs.values() for b in bs}}
print("shared by all three services:", sorted(c for c, n in counts.items() if n == 3))
Expected output (Python 3.13.5):
esx-02 -> services ['hospital-bms', 'water-telemetry'] via 5 dependants
esx-03 -> services ['grid-ss3-telecontrol', 'hospital-bms', 'water-telemetry'] via 7 dependants
gps-clock -> services ['grid-ss3-telecontrol', 'water-telemetry'] via 5 dependants
san-01 -> services ['water-telemetry'] via 3 dependants
telco-mpls -> services ['grid-ss3-telecontrol'] via 1 dependants
shared by all three services: ['esx-03']
esx-02 hosts the SCADA server, the historian and the BMS server, so its failure affects water and hospital monitoring. esx-03 is the only component that affects all three services — directly for the grid front end, indirectly through the directory for the other two. gps-clock, the reference for ntp-ops, affects water and grid: losing it does not stop anything immediately, but Chapter 7 showed what drifting clocks do to every later investigation. telco-mpls affects only the grid, and san-01 only water.
Technical actions follow: the directory needs a second domain controller on a different host (and the SCADA server's behaviour when the directory is unreachable must be tested — can operators still log in to the HMI?); ntp-ops needs a second, independent reference and monitoring of offset; esx-03 capacity and administrator group become a cross-sector concern reviewed with all three owners.
15.4 Integration points are boundaries
Every place the service connects to something it does not control is a boundary:
- Station communication equipment — cellular routers, radios, the carrier's private network. Chapter 13's port-forward was here. Each router's configuration belongs in the asset inventory, under change control and drift detection (Chapter 14).
- Vendor remote-support gateways — Chapter 10.
- Data exports — the historian's daily push to the corporate report server (Chapter 6 conduit C4). Exports should be pushed outward from the control side, never pulled by a corporate host with credentials into the control zone.
- Shared services — directory, time, monitoring. Their administrators effectively administer every dependant.
CISA's National Critical Functions work frames these dependencies at national scale (National Critical Functions); the technician applies the same reasoning to one operations centre.
15.5 Practical activity
Add a power-ups-a node that esx-02 and esx-03 both need, and a cell-carrier node that cell-router-kw and telco-mpls both need. Re-run Lab 15 and record which components are now shared by all three services. Then propose one technical change for each.
After the change, record which components are shared by all three services and propose one technical response for each, such as a second domain controller or a second power feed. Keep the new edges in the same format as the lab so that the graph stays runnable. Review the proposals with the three service owners before any change.
15.6 Common errors and limits
- Treating the directory and time service as "infrastructure" with no service owner.
- Counting dependants instead of looking at which services and through which paths.
-
Lab 15's graph is binary (needs / does not need); real dependencies have degraded modes and timers (a cached credential works for hours; a clock drifts slowly).
-
Listing only direct dependencies and missing the hypervisor under the directory.
- Leaving gps-clock without a named owner, although Lab 15 shows grid telecontrol and water telemetry both depending on it.
- Assuming a carrier isolates customer private networks without checking.
- Ranking esx-03 by its seven dependants instead of noting that it is the one asset shared by all three services.
Exercises — chapter 15
EX057 — Paths matter. Objective: trace an impact path. Inputs: Lab 15. Steps: modify the program to print, for esx-03, one dependency path from it to each affected service. Expected evidence: code and three paths. Rubric: 3 = for example esx-03 → fep-01 → grid-ss3-telecontrol; esx-03 → ad-ops → scada-01 → water-telemetry; esx-03 → ad-ops → bms-server → hospital-bms; explains that a second directory on another host breaks two of the three; 2 = paths without interpretation; 1 = attempted; 0 = none.
EX058 — New shared components. Objective: run the activity. Inputs: activity 15.5. Steps: run and interpret. Expected evidence: output and two technical changes. Rubric: 3 = power-ups-a and esx-03 shared by all three (and cell-carrier affecting water and grid); changes such as separate UPS feeds for the two hosts and a second carrier or radio path for the most critical stations; 2 = output only; 1 = partial; 0 = none.
EX059 — Degraded-mode test. Objective: test behaviour when a dependency fails. Inputs: ad-ops unavailable. Steps: write a scoped test plan, in a maintenance window, to establish whether operators can still log in to the HMI and whether SCADA polling continues. Expected evidence: test plan with stop conditions. Rubric: 3 = test on a standby or lab replica first; in production, blocks only the HMI's path to the directory for a short window with operations present; checks cached logins, local emergency accounts, polling continuity; stop conditions; evidence; 2 = no replica step; 1 = "turn off the domain controller"; 0 = none.
EX060 — Export direction. Objective: configure a boundary correctly. Inputs: the corporate report server currently logs in to hist-02 every night with a stored password to pull the CSV. Steps: redesign and list the configuration changes on both hosts and on fw-01. Expected evidence: design and changes. Rubric: 3 = hist-02 pushes over HTTPS to one endpoint; corporate credential into Z2 removed; fw-01 rule direction reversed (Z2 → Z6 only, specific host and port); push integrity checked (digest in the payload or a signed file); monitoring for failed pushes; 2 = push without removing old credential; 1 = vague; 0 = none.
Chapter synthesis
Services fail through what they depend on, and the most dangerous dependencies are shared ones that no owner claims. Model dependencies as a graph, search it backwards from each component, and look at the paths, not just the counts. Treat every integration point — station routers, carriers, vendor gateways, exports, directory and time — as a boundary under the same control, change and monitoring discipline as the firewall.
Continue studying — chapter 15 of 18
← Chapter 14 · Course chapter index · Chapter 16 →
Continue to the next authored lesson.