refactor(backend): lift shared CA cert select + fingerprint helpers
Both backends' provision_ca duplicated _select_ca_cert and the SHA-256 fingerprint computation verbatim. Lift them into the shared backend/util.py as select_ca_cert + log_ca_fingerprint; docker and smolmachines now call the shared helpers. No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,9 +4,17 @@ deeper (e.g. bot_bottle/backend/docker/util.py)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
import ssl
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..log import die
|
||||
from ..log import die, info
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..egress import EgressPlan
|
||||
from ..pipelock import PipelockProxyPlan
|
||||
|
||||
|
||||
def host_skill_dir(name: str) -> str:
|
||||
@@ -16,3 +24,45 @@ def host_skill_dir(name: str) -> str:
|
||||
if not home:
|
||||
die("HOME not set")
|
||||
return f"{home}/.claude/skills/{name}"
|
||||
|
||||
|
||||
def select_ca_cert(
|
||||
egress_plan: EgressPlan, proxy_plan: PipelockProxyPlan
|
||||
) -> tuple[Path, str]:
|
||||
"""Pick the agent-facing CA cert (and a short label for the log
|
||||
line) that matches the proxy the agent's HTTP_PROXY points at.
|
||||
Egress wins when the bottle declares any routes (it sits in front
|
||||
of pipelock); else pipelock.
|
||||
|
||||
Shared by every backend's `provision_ca`: launch mints the chosen
|
||||
CA(s) and re-binds their host paths into these inner plans before
|
||||
provision runs, so an empty/missing path here means launch's
|
||||
bringup is broken — fatal."""
|
||||
if egress_plan.routes:
|
||||
cert = egress_plan.mitmproxy_ca_cert_only_host_path
|
||||
if cert == Path() or not cert.is_file():
|
||||
die(
|
||||
f"egress CA cert missing at {cert or '(empty)'}; "
|
||||
f"launch must have called egress_tls_init and "
|
||||
f"re-bound the plan before provision"
|
||||
)
|
||||
return cert, "egress"
|
||||
cert = proxy_plan.ca_cert_host_path
|
||||
if not cert or not cert.is_file():
|
||||
die(
|
||||
f"pipelock CA cert missing at {cert or '(empty)'}; "
|
||||
f"launch must have called pipelock_tls_init and re-bound "
|
||||
f"the plan before provision"
|
||||
)
|
||||
return cert, "pipelock"
|
||||
|
||||
|
||||
def log_ca_fingerprint(cert_host_path: Path, label: str) -> None:
|
||||
"""Compute the cert's SHA-256 fingerprint over its DER bytes
|
||||
(stdlib `ssl` + `hashlib`) and log it once to stderr — the
|
||||
standard fingerprint form. Only ever touches the public cert;
|
||||
the private key stays on the host under the stage dir until
|
||||
teardown."""
|
||||
der = ssl.PEM_cert_to_DER_cert(cert_host_path.read_text())
|
||||
fingerprint = hashlib.sha256(der).hexdigest()
|
||||
info(f"{label} ca fingerprint: sha256:{fingerprint[:32]}...")
|
||||
|
||||
Reference in New Issue
Block a user