Chapter 22 — Quantum and post-quantum security: automation
Lesson map
Lesson 22 published. Map, example, EX043.
flowchart TD
N0["Learning outcomes"]
N1["22.1 Inventory and audits in pipelines"]
N2["22.2 Policy-driven selection"]
N3["22.3 Practical activity — Lab A"]
N4["22.4 Regression gates"]
N5["22.5 Certificate automation"]
N6["22.7 Automation risks"]
N7["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX043"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["22.1 Inventory and audits in pipelines"]
N2["22.2 Policy-driven selection"]
N3["22.3 Practical activity — Lab A"]
N4["22.4 Regression gates"]
N5["22.5 Certificate automation"]
N6["22.7 Automation risks"]
N7["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX043"]
[Learning outcomes]
|
v
[22.1 Inventory and audits in pipelines]
|
v
[22.2 Policy-driven selection]
|
v
[22.3 Practical activity — Lab A]
|
v
[22.4 Regression gates]
|
v
[22.5 Certificate automation]
|
v
[22.7 Automation risks]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX043]
Learning outcomes
You will (1) automate inventory, configuration audits and negotiation checks in CI/CD; (2) implement policy-driven algorithm selection; (3) prevent regressions with gates; and (4) automate certificate issuance with algorithm awareness.
22.1 Inventory and audits in pipelines
Pipelines already build images and deploy configuration; add steps that extract library versions from images, compare TLS profiles with the approved profile, and update the CBOM. A pull request that changes an ingress profile should show its cryptographic diff, just as it shows a code diff.
KLS's pipeline prints the cryptographic diff as a comment on the pull request: groups added or removed, preference order changes and library versions in the new image. Reviewers approve it the same way as code.
22.2 Policy-driven selection
Applications that sign or encrypt data should look up algorithms from configuration and record identifiers with data, so that migration is a policy change.
KLS's manifest-signing service stores an algorithm identifier with every signature, and the verifier reads which identifiers are acceptable from configuration. When ML-DSA becomes available in the signing library, switching is a policy edit followed by a canary, and old manifests still verify until the classical identifier is retired.
A manifest signed before identifiers were added is checked against a dated list of legacy signatures, not by assuming ECDSA; anything outside that list fails verification and goes to the logistics team for re-signing.
22.3 Practical activity — Lab A
# Lab A (ch 22): crypto-agility through a policy-driven registry instead of hard-coded algorithms.
import hashlib, hmac
REGISTRY = {"hmac-sha256": lambda k, m: hmac.new(k, m, hashlib.sha256).digest(),
"hmac-sha3-256": lambda k, m: hmac.new(k, m, hashlib.sha3_256).digest()}
POLICY = {"tag-algorithm": "hmac-sha256", "accept": ["hmac-sha256", "hmac-sha3-256"]}
def protect(key, msg):
alg = POLICY["tag-algorithm"]; return alg, REGISTRY[alg](key, msg)
def check(key, msg, alg, tag):
if alg not in POLICY["accept"]: return False # algorithm identifier is authenticated by policy
return hmac.compare_digest(REGISTRY[alg](key, msg), tag)
k, m = b"k" * 32, b"shipment manifest 42"
a1, t1 = protect(k, m)
POLICY["tag-algorithm"] = "hmac-sha3-256" # migration = one policy change
a2, t2 = protect(k, m)
print("old tag still verifies during transition:", check(k, m, a1, t1))
print("new tag verifies:", check(k, m, a2, t2), "| algorithms:", a1, "->", a2)
POLICY["accept"] = ["hmac-sha3-256"] # retire the old algorithm
print("old tag after retirement:", check(k, m, a1, t1))
Expected output:
old tag still verifies during transition: True
new tag verifies: True | algorithms: hmac-sha256 -> hmac-sha3-256
old tag after retirement: False
The lab models the three phases of an algorithm migration. In transition, the policy produces new tags with HMAC-SHA3-256 while the accept list still contains HMAC-SHA256, so the old tag verifies and nothing breaks. After retirement, the old identifier is removed from the accept list, and the same valid old tag now fails. The algorithm identifier travels with the tag, but the verifier never trusts it on its own: it must also be on the policy's accept list, which is what stops an attacker relabelling a tag to choose a weaker algorithm. The same structure carries over to signatures when ML-DSA replaces ECDSA.
22.4 Regression gates
Gates fail a deployment if: a tier-1 listener's profile lacks the hybrid group or does not prefer it; a base image's TLS library is older than the approved minimum; a new dependency introduces a hard-coded classical algorithm where policy requires agility. Every gate needs an exception path with an owner and expiry.
KLS's exceptions are YAML entries in the gate's repository: listener, reason, owner and expiry date. The gate reads them, passes the listed listener with a warning, and fails again automatically when the expiry passes. That keeps exceptions visible and stops them from becoming silent permanent bypasses.
22.5 Certificate automation
ACME (RFC 8555) and internal issuance APIs automate certificate renewal. Make the requested key and signature algorithms explicit parameters, so that switching internal leaves to ML-DSA is a change of template, not of scripts. Test renewal of a post-quantum certificate in staging before relying on it.
KLS's internal issuance template already names ecdsa-p256 as an explicit parameter; the ML-DSA pilot uses the same template with ml-dsa-44. The staging test checks that renewal produces a valid chain and that every relying party accepts it before the template changes in production.
22.6 Worked example
KLS adds a CI job, crypto-gate, that parses rendered Kubernetes manifests, extracts ingress TLS groups, and fails if a tier-1 ingress lacks X25519MLKEM768 first. In its first week it blocks two releases that copied an old annotation; both are fixed in minutes rather than discovered weeks later by monitoring.
Both blocked releases had copied an annotation from an old service template. The fix was to correct the template as well as the two services, so the gate stopped the pattern at its source. The gate runs in under a minute and has a documented exception path.
22.7 Automation risks
Automation multiplies mistakes as efficiently as it multiplies fixes. Protect pipeline configuration with review, sign pipeline definitions where tooling allows, and stage changes to central profiles through the same canary process as code. A wrong profile pushed automatically to every ingress is a large outage; the same profile pushed to one canary ingress is a small, informative one.
KLS learned this in staging: a profile change merged without the canary stage removed X25519 from every staging ingress at once, breaking the Java test client across all services. Now profile changes reach one canary ingress first, and the pipeline definitions are reviewed by two people.
22.8 Common errors and limits
- Gates without exception paths.
- Automating issuance with hard-coded algorithms.
- Pushing central profile changes everywhere at once.
Each error turns automation against the team. A gate with no exception path gets disabled the first time it blocks an urgent release; KLS's exception file exists so that never happens. Issuance scripts with an algorithm hard-coded in a string would have to be rewritten for ML-DSA instead of changing a template. And a profile pushed to every ingress at once turns a small mistake into a platform-wide outage, as the staging incident showed.
Exercises
- EX043 — Gate rule. Write pseudo-code for a gate that checks hybrid preference on tier-1 listeners. Rubric: 3 = parses list, checks first element, tier condition, exit code.
- EX044 — Agility. Using Lab A, explain why old tags verify during transition but not after retirement. Rubric: 3 = accept list change with authenticated identifier.
Synthesis
Automation embeds inventory, audits, policy-driven selection and regression gates in the delivery pipeline, with exception paths and staged rollout of central changes.
Continue studying — chapter 22 of 30
← Chapter 21 (draft) · Course chapter index · Chapter 23 (draft) →