fix(cd): accept bounded partial SSH route proof

This commit is contained in:
ogt
2026-07-14 10:45:15 +08:00
parent a677199bb6
commit a5030e9fe0
2 changed files with 134 additions and 4 deletions

View File

@@ -1,10 +1,24 @@
from __future__ import annotations
import json
import os
import re
import subprocess
import sys
import textwrap
from pathlib import Path
from typing import Any
import yaml
_BROKER_PROBE_HOSTS = (
"192.168.0.110",
"192.168.0.112",
"192.168.0.120",
"192.168.0.121",
"192.168.0.188",
)
def _network_policies() -> dict[str, dict[str, Any]]:
repo_root = Path(__file__).resolve().parents[3]
@@ -24,6 +38,64 @@ def _ports(policy: dict[str, Any]) -> set[int]:
}
def _broker_probe_script() -> str:
repo_root = Path(__file__).resolve().parents[3]
workflow = (repo_root / ".gitea/workflows/cd.yaml").read_text()
function = re.search(
r"verify_broker_ssh_allowed\(\) \{.*?<<'PY'\n"
r"(?P<script>.*?)\n\s+PY\n\s+\}",
workflow,
re.DOTALL,
)
assert function is not None
return textwrap.dedent(function.group("script"))
def _run_broker_probe(
tmp_path: Path,
*,
outcomes: dict[str, str],
) -> subprocess.CompletedProcess[str]:
fake_socket = tmp_path / "socket.py"
fake_socket.write_text(
textwrap.dedent(
"""
import json
import os
_OUTCOMES = json.loads(os.environ["AWOOOI_TEST_SOCKET_OUTCOMES"])
class _Connection:
def close(self):
return None
def create_connection(address, timeout):
del timeout
outcome = _OUTCOMES.get(address[0], "unreachable")
if outcome == "connected":
return _Connection()
if outcome == "refused":
raise ConnectionRefusedError(address[0])
raise TimeoutError(address[0])
"""
),
encoding="utf-8",
)
env = os.environ.copy()
env["PYTHONPATH"] = str(tmp_path)
env["AWOOOI_TEST_SOCKET_OUTCOMES"] = json.dumps(outcomes)
return subprocess.run(
[sys.executable, "-", *_BROKER_PROBE_HOSTS],
input=_broker_probe_script(),
text=True,
capture_output=True,
check=False,
env=env,
)
def test_common_egress_does_not_grant_ssh() -> None:
policies = _network_policies()
@@ -121,6 +193,57 @@ def test_cd_applies_rolls_back_and_verifies_network_boundary() -> None:
assert "except ConnectionRefusedError:" in workflow
assert "broker_ssh_refused_but_egress_permitted=" in workflow
assert "broker_ssh_allowlisted_endpoint_unavailable=" in workflow
assert "raise SystemExit(0 if connected else 1)" in workflow
assert "raise SystemExit(0 if connected or refused else 1)" in workflow
assert "len(permitted) == len(sys.argv) - 1" not in workflow
assert "ssh-mcp-key known_hosts 更新失敗,停止部署" in workflow
def test_broker_probe_accepts_partial_live_route_evidence(tmp_path: Path) -> None:
result = _run_broker_probe(
tmp_path,
outcomes={
"192.168.0.110": "connected",
"192.168.0.112": "unreachable",
"192.168.0.120": "connected",
"192.168.0.121": "connected",
"192.168.0.188": "connected",
},
)
assert result.returncode == 0
assert result.stdout.splitlines() == [
"broker_ssh_connected="
"192.168.0.110,192.168.0.120,192.168.0.121,192.168.0.188",
"broker_ssh_refused_but_egress_permitted=",
"broker_ssh_allowlisted_endpoint_unavailable=192.168.0.112",
]
def test_broker_probe_accepts_refusal_as_bounded_route_evidence(
tmp_path: Path,
) -> None:
result = _run_broker_probe(
tmp_path,
outcomes={"192.168.0.112": "refused"},
)
assert result.returncode == 0
assert result.stdout.splitlines() == [
"broker_ssh_connected=",
"broker_ssh_refused_but_egress_permitted=192.168.0.112",
"broker_ssh_allowlisted_endpoint_unavailable="
"192.168.0.110,192.168.0.120,192.168.0.121,192.168.0.188",
]
def test_broker_probe_rejects_arbitrary_socket_errors(tmp_path: Path) -> None:
result = _run_broker_probe(tmp_path, outcomes={})
assert result.returncode == 1
assert result.stdout.splitlines() == [
"broker_ssh_connected=",
"broker_ssh_refused_but_egress_permitted=",
"broker_ssh_allowlisted_endpoint_unavailable="
"192.168.0.110,192.168.0.112,192.168.0.120,"
"192.168.0.121,192.168.0.188",
]