"""Extract mitmproxy's CA cert and install it into the agent container's trust store. mitmproxy generates a fresh CA on first launch inside its sidecar. This provisioner pulls the public cert through a host stage dir, drops it into the agent at `/usr/local/share/ca-certificates/...`, runs `update-ca-certificates` to rebuild the system bundle, and emits a single stderr log line with the SHA-256 fingerprint.""" from __future__ import annotations import hashlib import ssl import subprocess from ....log import info from ..bottle_plan import DockerBottlePlan from ..launch import AGENT_CA_PATH from ..mitmproxy import DockerMitmproxyProxy, mitmproxy_container_name def provision_ca(plan: DockerBottlePlan, target: str) -> None: """Pull mitmproxy's CA cert, install in the agent, log fingerprint. Called from BottleBackend.provision after the agent container is up. The mitmproxy sidecar is already running (started during `launch`).""" sidecar = mitmproxy_container_name(plan.mitmproxy_plan.slug) stage_cert = plan.stage_dir / "mitm-ca.crt" DockerMitmproxyProxy().extract_ca_cert(sidecar, stage_cert) container = target subprocess.run( ["docker", "cp", str(stage_cert), f"{container}:{AGENT_CA_PATH}"], stdout=subprocess.DEVNULL, check=True, ) subprocess.run( ["docker", "exec", "-u", "0", container, "chmod", "644", AGENT_CA_PATH], stdout=subprocess.DEVNULL, check=True, ) subprocess.run( ["docker", "exec", "-u", "0", container, "update-ca-certificates"], stdout=subprocess.DEVNULL, check=True, ) # SHA-256 of the cert's DER bytes — the standard fingerprint # form. stdlib only; never the private key (which stays in the # sidecar). Logged once at launch as an audit signal. pem = stage_cert.read_text() der = ssl.PEM_cert_to_DER_cert(pem) fingerprint = hashlib.sha256(der).hexdigest() info(f"mitm ca fingerprint: sha256:{fingerprint[:32]}...")