Files
wehub-resource-sync 0418dc5cf9
CI / Python tests (3.10) (push) Has been cancelled
CI / Python tests (3.11) (push) Has been cancelled
CI / Python quality (push) Has been cancelled
CI / Frontend typecheck (push) Has been cancelled
Autopilot Pages / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:45:00 +08:00

155 lines
5.6 KiB
Python

"""Tests for outbound HTTP target validation."""
from __future__ import annotations
import ipaddress
import httpx
import pytest
from openharness.utils.network_guard import fetch_public_http_response
class FakeAsyncClient:
def __init__(self, **kwargs: object) -> None:
self.kwargs = kwargs
async def __aenter__(self):
return self
async def __aexit__(self, exc_type, exc, tb):
return None
async def get(self, url: str, **kwargs: object) -> httpx.Response:
request = httpx.Request("GET", url, params=kwargs.get("params"))
return httpx.Response(200, text="ok", request=request)
@pytest.fixture(autouse=True)
def isolated_config_dir(tmp_path, monkeypatch):
monkeypatch.setenv("OPENHARNESS_CONFIG_DIR", str(tmp_path / "config"))
@pytest.mark.asyncio
async def test_fetch_public_http_response_direct_rejects_non_public_dns(monkeypatch):
async def fake_resolve(host: str, port: int):
return {ipaddress.ip_address("100.64.1.2")}
monkeypatch.setattr("openharness.utils.network_guard._resolve_host_addresses", fake_resolve)
with pytest.raises(ValueError, match="synthetic DNS"):
await fetch_public_http_response("https://example.com/")
@pytest.mark.asyncio
async def test_fetch_public_http_response_synthetic_dns_allows_declared_cidr(monkeypatch):
async def fake_resolve(host: str, port: int):
return {ipaddress.ip_address("100.64.1.2")}
monkeypatch.setenv("OPENHARNESS_WEB_RESOLUTION_MODE", "synthetic_dns")
monkeypatch.setenv("OPENHARNESS_WEB_SYNTHETIC_DNS_CIDRS", "100.64.0.0/10")
monkeypatch.setattr("openharness.utils.network_guard._resolve_host_addresses", fake_resolve)
monkeypatch.setattr(httpx, "AsyncClient", FakeAsyncClient)
response = await fetch_public_http_response("https://example.com/")
assert response.status_code == 200
@pytest.mark.asyncio
async def test_fetch_public_http_response_synthetic_dns_uses_persisted_settings(
monkeypatch,
):
from openharness.config.settings import Settings, WebSettings, save_settings
async def fake_resolve(host: str, port: int):
return {ipaddress.ip_address("100.64.1.2")}
save_settings(
Settings(
web=WebSettings(
resolution_mode="synthetic_dns",
synthetic_dns_cidrs=["100.64.0.0/10"],
)
)
)
monkeypatch.setattr("openharness.utils.network_guard._resolve_host_addresses", fake_resolve)
monkeypatch.setattr(httpx, "AsyncClient", FakeAsyncClient)
response = await fetch_public_http_response("https://example.com/")
assert response.status_code == 200
@pytest.mark.asyncio
async def test_fetch_public_http_response_synthetic_dns_requires_declared_cidrs(monkeypatch):
monkeypatch.setenv("OPENHARNESS_WEB_RESOLUTION_MODE", "synthetic_dns")
with pytest.raises(ValueError, match="web.synthetic_dns_cidrs"):
await fetch_public_http_response("https://example.com/")
@pytest.mark.asyncio
async def test_fetch_public_http_response_synthetic_dns_rejects_literal_non_public_ip(
monkeypatch,
):
monkeypatch.setenv("OPENHARNESS_WEB_RESOLUTION_MODE", "synthetic_dns")
monkeypatch.setenv("OPENHARNESS_WEB_SYNTHETIC_DNS_CIDRS", "100.64.0.0/10")
with pytest.raises(ValueError, match="non-public"):
await fetch_public_http_response("http://100.64.1.2/")
@pytest.mark.asyncio
async def test_fetch_public_http_response_synthetic_dns_rejects_undeclared_private_dns(
monkeypatch,
):
async def fake_resolve(host: str, port: int):
return {ipaddress.ip_address("10.0.0.1")}
monkeypatch.setenv("OPENHARNESS_WEB_RESOLUTION_MODE", "synthetic_dns")
monkeypatch.setenv("OPENHARNESS_WEB_SYNTHETIC_DNS_CIDRS", "100.64.0.0/10")
monkeypatch.setattr("openharness.utils.network_guard._resolve_host_addresses", fake_resolve)
with pytest.raises(ValueError, match="non-public"):
await fetch_public_http_response("https://example.com/")
@pytest.mark.asyncio
async def test_fetch_public_http_response_proxy_mode_does_not_resolve_target_dns(monkeypatch):
async def fail_resolve(host: str, port: int):
raise AssertionError("proxy mode should not resolve ordinary target domains locally")
monkeypatch.setenv("OPENHARNESS_WEB_PROXY", "http://proxy.example.com:7890")
monkeypatch.setenv("OPENHARNESS_WEB_SYNTHETIC_DNS_CIDRS", "not-a-cidr")
monkeypatch.setattr("openharness.utils.network_guard._resolve_host_addresses", fail_resolve)
monkeypatch.setattr(httpx, "AsyncClient", FakeAsyncClient)
response = await fetch_public_http_response("https://example.com/")
assert response.status_code == 200
@pytest.mark.asyncio
async def test_fetch_public_http_response_proxy_mode_rejects_literal_non_public_ip(monkeypatch):
monkeypatch.setenv("OPENHARNESS_WEB_PROXY", "http://proxy.example.com:7890")
with pytest.raises(ValueError, match="non-public"):
await fetch_public_http_response("http://127.0.0.1/")
@pytest.mark.asyncio
async def test_fetch_public_http_response_rejects_non_public_redirect_in_proxy_mode(
monkeypatch,
):
class RedirectClient(FakeAsyncClient):
async def get(self, url: str, **kwargs: object) -> httpx.Response:
request = httpx.Request("GET", url, params=kwargs.get("params"))
return httpx.Response(302, headers={"Location": "http://127.0.0.1/"}, request=request)
monkeypatch.setenv("OPENHARNESS_WEB_PROXY", "http://proxy.example.com:7890")
monkeypatch.setattr(httpx, "AsyncClient", RedirectClient)
with pytest.raises(ValueError, match="non-public"):
await fetch_public_http_response("https://example.com/")