chore(security): pin TLSv1.2 floor on control-plane mTLS clients
Follow-up to V9.1.4 (which covered only the syslog forwarder/listener): set ctx.minimum_version = TLSVersion.TLSv1_2 on the remaining DECNET-owned mTLS client contexts — AgentClient (_build_client + _fetch_peer_fingerprint), UpdaterClient (_build_client + _fetch_peer_fingerprint), and the updater executor's worker context. Pure hardening, no behavior change for TLS1.2+ peers (confirmed by the existing mTLS round-trip suites). Deliberately EXCLUDED — hardening these would be counterproductive: - templates/https/server.py, templates/rdp/server.py: honeypot listeners, where looking weak/old is part of the deception. - prober/tlscert.py: outbound TLS fingerprinting prober, which must speak whatever the attacker's target offers. Added a floor-assertion test (spies httpx.AsyncClient to capture the real verify= context).
This commit is contained in:
@@ -150,6 +150,7 @@ class AgentClient:
|
||||
# purpose/ALPN/default-CA logic that doesn't compose with private-CA
|
||||
# mTLS in all combinations. A bare SSLContext is predictable.
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
|
||||
ctx.load_cert_chain(
|
||||
str(self._identity.cert_path), str(self._identity.key_path)
|
||||
)
|
||||
@@ -168,6 +169,7 @@ class AgentClient:
|
||||
|
||||
def _fetch_peer_fingerprint(self) -> str:
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
|
||||
ctx.load_cert_chain(
|
||||
str(self._identity.cert_path), str(self._identity.key_path)
|
||||
)
|
||||
|
||||
@@ -72,6 +72,7 @@ class UpdaterClient:
|
||||
|
||||
def _build_client(self, timeout: httpx.Timeout) -> httpx.AsyncClient:
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
|
||||
ctx.load_cert_chain(
|
||||
str(self._identity.cert_path), str(self._identity.key_path),
|
||||
)
|
||||
@@ -89,6 +90,7 @@ class UpdaterClient:
|
||||
SHA-256 hex of the leaf cert it presents. Mirrors
|
||||
``AgentClient._fetch_peer_fingerprint`` exactly."""
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
|
||||
ctx.load_cert_chain(
|
||||
str(self._identity.cert_path), str(self._identity.key_path),
|
||||
)
|
||||
|
||||
@@ -519,6 +519,7 @@ def _probe_agent(
|
||||
if not (worker_key.is_file() and worker_crt.is_file() and ca.is_file()):
|
||||
return False, f"no mTLS bundle at {agent_dir}"
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
|
||||
ctx.load_cert_chain(certfile=str(worker_crt), keyfile=str(worker_key))
|
||||
ctx.load_verify_locations(cafile=str(ca))
|
||||
ctx.verify_mode = ssl.CERT_REQUIRED
|
||||
|
||||
Reference in New Issue
Block a user