diff --git a/.gitea/workflows/cd.yaml b/.gitea/workflows/cd.yaml index f6890ae93..1a2ed80c5 100644 --- a/.gitea/workflows/cd.yaml +++ b/.gitea/workflows/cd.yaml @@ -3223,7 +3223,8 @@ jobs: # NetworkPolicy boundary and the target replied. Keep host # service readiness separate from this security-boundary # verifier; a stopped sshd must not make a healthy rollout - # look like a policy failure. + # look like a policy failure. This is bounded to the fixed + # targets whose exact CIDRs were verified immediately above. refused.append(host) except OSError: # Endpoint availability is a separate runtime signal. The @@ -3243,7 +3244,13 @@ jobs: "broker_ssh_allowlisted_endpoint_unavailable=" + ",".join(unavailable) ) - raise SystemExit(0 if connected else 1) + # Static verification already proves the exact five-destination + # allowlist. The live probe only needs one positive route signal; + # requiring every host to answer confuses host/service availability + # (for example a booted host with sshd down) with NetworkPolicy + # correctness. Arbitrary OSError values remain non-evidence, so an + # all-timeout/unreachable result still fails closed. + raise SystemExit(0 if connected or refused else 1) PY } verify_ssh_denied awoooi-api api || { @@ -3253,7 +3260,7 @@ jobs: echo "❌ signal worker can still establish host SSH connections"; exit 1; } verify_broker_ssh_allowed || { - echo "❌ execution broker cannot reach any allowlisted SSH endpoint"; exit 1; + echo "❌ execution broker has no live route evidence for allowlisted SSH endpoints"; exit 1; } echo "executor_boundary_stage=live_socket_boundary_verified" diff --git a/apps/api/tests/test_executor_network_policy_boundary.py b/apps/api/tests/test_executor_network_policy_boundary.py index aaace571d..84048096a 100644 --- a/apps/api/tests/test_executor_network_policy_boundary.py +++ b/apps/api/tests/test_executor_network_policy_boundary.py @@ -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