Chapter 3 — Programming foundations
Lesson map
Lesson 03 published. Map, example, EX007.
flowchart TD
N0["Learning outcomes"]
N1["3.1 Why technologists program"]
N2["3.2 One function, one decision"]
N3["3.3 Standard library first"]
N4["3.4 Failing closed"]
N5["3.5 Tests as evidence"]
N6["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6
N6 --> EX["Worked example"]
EX --> Q["Exercise EX007"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["3.1 Why technologists program"]
N2["3.2 One function, one decision"]
N3["3.3 Standard library first"]
N4["3.4 Failing closed"]
N5["3.5 Tests as evidence"]
N6["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> Q["EX007"]
[Learning outcomes]
|
v
[3.1 Why technologists program]
|
v
[3.2 One function, one decision]
|
v
[3.3 Standard library first]
|
v
[3.4 Failing closed]
|
v
[3.5 Tests as evidence]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX007]
Learning outcomes
You will (1) write small, readable Python functions that make one decision each; (2) use only the standard library so a lab runs on any approved workstation; (3) test a function with known inputs before trusting it; (4) explain why assessment tooling should fail closed.
3.1 Why technologists program
Assessment work produces lists: hosts, accounts, findings, evidence items, retest dates. Scripts that check, sort and summarise those lists remove copying errors and make decisions repeatable. They are not attack tools. In this book every script reads invented data held in the file itself and prints a verdict.
Priya automates host and finding lists so humans spend time on HOLDs and severity, not on copying rows. Scripts that classify scope and hash evidence are in bounds; scripts that invent attack paths are not. ENG-712's operator log is generated from gate-passing actions only.
3.2 One function, one decision
A function such as verdict(addr) in Chapter 2 answers one question and returns a small set of labels. That design makes it testable: feed it an address you already know the answer for and compare. When a function both decides and prints and writes files, a bug in one part hides in the others.
verdict(addr) returns IN-SCOPE, EXCLUDED or OUT-OF-SCOPE and nothing else. That single decision is unit-tested with 192.0.2.10, 192.0.2.70 and 192.0.2.200 before every window. A helper that also edits the inventory it reads fails TRT code review, because it no longer answers one decision and a bug in the edit would hide in the verdict.
3.3 Standard library first
The Python standard library includes ipaddress, datetime, hashlib, json, csv and collections. These cover scope arithmetic, time windows, evidence hashing, structured records and counting. Avoiding third-party packages means no dependency review, no supply-chain surprise, and identical behaviour on the reviewer's machine.
ipaddress, datetime, hashlib and json cover ENG-712's classroom labs without third-party scanners. Priya pins the standard-library choice in the kit inventory so supply-chain arguments stay about TRT tools, not random PyPI packages pulled mid-window. If Northpoint later brings a commercial scanner, that tool gets its own row, owner and data-handling note.
3.4 Failing closed
If a scope file is missing or a date cannot be parsed, the safe default is "do not proceed". A checker that returns "allowed" when it hits an exception is worse than none, because it creates false confidence. Write the deny path first, then add the allow conditions.
Missing scope files make the checker fail closed to "do not proceed". Returning allowed on exception would have green-lit 192.0.2.200 in a broken parse. Priya's tests assert the closed path with a deleted-file fixture: removing the scope file in CI must yield do-not-proceed, never allowed. The fixture sits beside the ENG-712 test table so auditors can rerun the closed path.
3.5 Tests as evidence
A short table of inputs and expected outputs, run before each engagement, is evidence that the tooling behaves. Keep it with the engagement records so a reviewer can rerun it.
The pre-engagement test table for verdict() is filed under ENG-712 beside the ROE. When Northpoint asks whether the tool drifted, she shows the table run at kickoff, not a memory of green output. Because the run is attached to the ticket before tools start, nobody can later claim the checker was 'probably fine' without producing that artefact.
Worked example
Priya writes a helper that returns "allowed" only when a date string parses and falls inside the window. Her first draft caught ValueError and returned "allowed". She rewrites it so the exception returns "STOP: unreadable time", and adds three known cases — inside, outside, malformed — to a test list that runs before each night's work.
Synthetic case. Priya's helper and its test inputs are invented for teaching.
Errors and limits
Copy-pasted snippets from forums may hide network calls or unsafe defaults; read every line. Programming skill does not create permission to test anything.
Exercises
- EX007 — Exception default. A parser receives "2026-11-31 23:00" (an invalid date). What should a fail-closed window checker return? Rubric: 3 = a stop/deny label and the reason, never "allowed"; 2 = deny without reason; 1 = allowed; 0 = none.
- EX008 — Library choice. Name the standard-library module you would use to compute SHA-256 digests and one reason to prefer it over a third-party package. Rubric: 3 = hashlib + no extra dependency/supply-chain review/same behaviour for reviewer; 2 = module only; 1 = third-party; 0 = none.
- EX009 — Known-answer table. Give three test inputs with expected outputs for the Chapter 2
verdictfunction. Rubric: 3 = three correct pairs covering IN-SCOPE, EXCLUDED and OUT-OF-SCOPE; 2 = two correct; 1 = one; 0 = none.
Synthesis
Small functions, standard library, deny by default, and a known-answer table kept as evidence.
Continue studying — chapter 03 of 30
← Chapter 02 (draft) · Course chapter index · Chapter 04 (draft) →