Chapter 10 — Cryptography and trust services: control configuration
Lesson map
Lesson 10 published. Map, example, EX037.
flowchart TD
N0["Learning outcomes"]
N1["10.1 Configuration goals"]
N2["10.2 A safe client default"]
N3["Lab — Default client context"]
N4["10.3 Change control"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Worked example"]
EX --> Q["Exercise EX037"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["10.1 Configuration goals"]
N2["10.2 A safe client default"]
N3["Lab — Default client context"]
N4["10.3 Change control"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX037"]
[Learning outcomes]
|
v
[10.1 Configuration goals]
|
v
[10.2 A safe client default]
|
v
[Lab — Default client context]
|
v
[10.3 Change control]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX037]
Learning outcomes
You will (1) configure TLS version and verification settings in line with NIST SP 800-52 Rev. 2; (2) inspect Python's default client context; (3) apply changes through change control.
10.1 Configuration goals
Priya gives Tomás the goals for every Lumen TLS endpoint, drawn from NIST SP 800-52 Rev. 2: offer TLS 1.3, allow TLS 1.2 only where older clients need it, disable earlier versions, serve a complete certificate chain and use certificates whose names match the service. On clients, the goals are to verify certificates and host names and to trust only the intended roots. Tomás learns that many breaches come from a client that silently accepts any certificate, so client settings deserve as much review as server settings, especially in scripts and integrations written in a hurry.
10.2 A safe client default
Tomás inspects Python's ssl.create_default_context on the lab box. The lab below prints its verification mode, host-name checking and minimum version. These defaults are what a well-behaved script should keep. A common anti-pattern is setting check_hostname to False and verify_mode to CERT_NONE to make an error go away; that turns TLS into encryption with an unknown party. When a script needs to trust an internal root, the right fix is to load that root with load_verify_locations, keeping every check on, rather than switching checks off.
Lab — Default client context
# Inspect Python's default TLS client context; no network access.
import ssl, sys
ctx = ssl.create_default_context()
print("python", sys.version.split()[0], "|", ssl.OPENSSL_VERSION)
print("verify_mode:", ctx.verify_mode.name)
print("check_hostname:", ctx.check_hostname)
print("minimum_version:", ctx.minimum_version.name)
ctx.minimum_version = ssl.TLSVersion.TLSv1_2 # make the policy floor explicit
print("after policy, minimum_version:", ctx.minimum_version.name)
Run with python3 lab_tlsctx.py. Verified output:
python 3.13.5 | OpenSSL 3.5.7 9 Jun 2026
verify_mode: CERT_REQUIRED
check_hostname: True
minimum_version: MINIMUM_SUPPORTED
after policy, minimum_version: TLSv1_2
10.3 Change control
Changing a TLS setting on a shared load balancer can cut off old handhelds or partner systems. Tomás writes a change request listing the setting, the expected effect, the clients that might break, a test plan and a rollback step. He checks handshake logs first to see whether any client still negotiates TLS 1.0 or 1.1. The change runs in a maintenance window, and he retests afterwards with s_client and the Python lab. Recording before and after evidence lets the team prove the control works and quickly reverse it if a partner reports problems.
Worked example
Tomás writes a change request to disable TLS 1.0 and 1.1 on the portal load balancer, checks logs for old clients, applies the change and records before and after tests.
Synthetic case. Endpoints and clients are synthetic; SP 800-52 Rev. 2 is real.
Errors and limits
Defaults change across Python and OpenSSL versions; record versions. Disabling old versions may break legacy devices that need a separate plan.
Exercises
- EX037 — Version policy. Which TLS versions does the Lumen policy allow? Rubric: 3 = TLS 1.3, plus TLS 1.2 only where older clients need it; earlier disabled;; 2 = 1.3 and 1.2;; 1 = includes 1.0;; 0 = none.
- EX038 — Default context output. What did the lab report for verify_mode and check_hostname? Rubric: 3 = CERT_REQUIRED and True;; 2 = one value;; 1 = CERT_NONE;; 0 = none.
- EX039 — Internal root fix. How should a script trust Lumen's internal root? Rubric: 3 = load it with load_verify_locations and keep all checks on;; 2 = load root;; 1 = disable checks;; 0 = none.
- EX040 — Before the change. What should Tomás check before disabling TLS 1.1? Rubric: 3 = handshake logs for clients still negotiating old versions;; 2 = logs;; 1 = vague;; 0 = none.
Synthesis
Good control configuration keeps verification on, follows published TLS guidance and changes settings only through tested, reversible requests.
Continue studying — chapter 10 of 18
← Chapter 09 (draft) · Course chapter index · Chapter 11 (draft) →