test(pipelock): HTTPS integration tests for the bumped path
test / unit (pull_request) Successful in 11s
test / integration (pull_request) Successful in 13s

Fourth and final step of PRD 0006. Two new end-to-end tests pin
the two paths through pipelock's tls_interception layer.

- test_pipelock_blocks_secret_https_post: posts a GitHub-PAT-shaped
  body to api.anthropic.com over HTTPS through the bottle. With
  pipelock now bumping the CONNECT and seeing the decrypted body,
  it returns 403 with the documented `blocked: request body
  contains secret: GitHub Token` body. The probe is a single curl
  invocation — curl natively does CONNECT through HTTPS_PROXY, the
  agent's trust store now contains pipelock's CA, no hand-rolled
  TLS in the test.

- test_pipelock_allows_normal_https: GETs git's README from
  raw.githubusercontent.com (a baked-in allowlist host). 200 +
  non-zero body length proves the full chain works:
  pipelock_tls_init → docker cp of CA into sidecar → bumped CONNECT
  → provision_ca installed CA in agent → curl trusts pipelock's
  bumped leaf → body forwarded back through the tunnel.

- test_pipelock_sidecar_smoke: pre-existing direct-start smoke
  test updated to call pipelock_tls_init and populate the CA
  paths on the plan. (The full launch flow does this in launch.py;
  this test exercises the proxy class in isolation.)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-12 15:01:17 -04:00
parent fb10c8dd8a
commit d3115ae5fd
3 changed files with 188 additions and 0 deletions
@@ -28,6 +28,7 @@ from claude_bottle.backend.docker.pipelock import (
PIPELOCK_PORT,
DockerPipelockProxy,
pipelock_container_name,
pipelock_tls_init,
)
from tests._docker import skip_unless_docker
from tests.fixtures import fixture_minimal
@@ -79,10 +80,17 @@ class TestPipelockSidecarSmoke(unittest.TestCase):
self.internal_net = network_create_internal(self.slug)
self.egress_net = network_create_egress(self.slug)
# PRD 0006: pipelock's tls_interception block in the rendered
# YAML references in-container CA paths; .start docker-cp's
# those files in. The full launch flow generates the CA via
# `pipelock_tls_init`; this smoke test calls it directly.
ca_cert_host, ca_key_host = pipelock_tls_init(self.work_dir)
plan = dataclasses.replace(
prep,
internal_network=self.internal_net,
egress_network=self.egress_net,
ca_cert_host_path=ca_cert_host,
ca_key_host_path=ca_key_host,
)
self.sidecar_name = proxy.start(plan)