Files
bot-bottle/tests/integration/test_pipelock_allows_normal_https.py
2026-05-28 17:56:14 -04:00

84 lines
3.2 KiB
Python

"""Integration: with pipelock's tls_interception enabled (PRD 0006),
a clean HTTPS GET to an allowlisted host succeeds end-to-end through
the bumped tunnel.
Complement to test_pipelock_blocks_secret_https_post — together they
pin pipelock's two paths (block on body match, allow on clean
traffic). This test is also the implicit TLS-trust check: if
provision_ca had failed to install pipelock's CA into the agent's
trust store, curl would have rejected the bumped leaf cert and the
fetch would have failed before any HTTP response could come back."""
from __future__ import annotations
import os
import shutil
import tempfile
import unittest
from pathlib import Path
from bot_bottle.backend import BottleSpec, get_bottle_backend
from tests._docker import skip_unless_docker
from tests.fixtures import fixture_minimal
# raw.githubusercontent.com is in the baked-in DEFAULT_ALLOWLIST.
# `git`'s own README on the master branch is a long-lived raw file
# (~3 KB) that any CI runner with internet can fetch.
_TARGET_URL = "https://raw.githubusercontent.com/git/git/master/README.md"
@skip_unless_docker()
class TestPipelockAllowsNormalHttps(unittest.TestCase):
@unittest.skipIf(
os.environ.get("GITEA_ACTIONS") == "true",
"skipped under act_runner: docker socket mount topology breaks "
"in-process visibility of networks created on the host daemon",
)
def test_https_get_to_allowed_host_succeeds(self):
backend = get_bottle_backend()
stage_dir = Path(tempfile.mkdtemp(prefix="cb-test-stage."))
try:
spec = BottleSpec(
manifest=fixture_minimal(),
agent_name="demo",
copy_cwd=False,
user_cwd=str(stage_dir),
)
plan = backend.prepare(spec, stage_dir=stage_dir)
with backend.launch(plan) as bottle:
script = (
"set -eu\n"
'curl --proxy "$HTTPS_PROXY" -s --max-time 10 \\\n'
" -w 'status=%{http_code}\\n' \\\n"
" -o /tmp/probe-body.txt \\\n"
f" {_TARGET_URL}\n"
'echo "len=$(wc -c < /tmp/probe-body.txt)"\n'
)
result = bottle.exec(script)
finally:
shutil.rmtree(stage_dir, ignore_errors=True)
self.assertEqual(
0, result.returncode,
f"exec wrapper failed: stdout={result.stdout!r} stderr={result.stderr!r}",
)
# 200 from the upstream (pipelock forwarded after the body
# scan passed). If curl had failed the bumped-cert trust
# check, the exit code or status would be non-200 here.
self.assertIn(
"status=200", result.stdout,
f"expected 200 from raw.githubusercontent.com; got: {result.stdout!r}",
)
# The git README is ~3 KB. Anything substantially non-zero
# proves the response body actually transferred — i.e. the
# CONNECT tunnel + bumped TLS + body forwarding all worked.
self.assertNotIn(
"len=0\n", result.stdout,
f"response body was empty: {result.stdout!r}",
)
if __name__ == "__main__":
unittest.main()