fix(exposure): thread nginx reload off event loop + strengthen mesh test (ref #793)

set_exposure's two _reload_nginx() call sites now run via
asyncio.to_thread, closing the same event-loop SPOF the Tor apply path
was already fixed for (up to ~40s of synchronous nginx -t + reload
blocking every concurrent aggregator request on the rollback path).

Also adds a localhost+mesh acceptance case: the existing lan+mesh test
used 10.10.0.5, which already falls inside lan's 10.0.0.0/8 allow, so it
passed regardless of the mesh allow line. localhost does not admit LAN,
so asserting mesh-allow/lan-deny/external-deny/localhost-allow there
uniquely proves the mesh allow is doing the work.
This commit is contained in:
CyberMind-FR 2026-07-04 07:33:20 +02:00
parent e9ebb245ff
commit ce3de5dc11
2 changed files with 13 additions and 2 deletions

View File

@ -164,14 +164,14 @@ async def set_exposure(vhost: str, body: ExposureSet, user: dict = Depends(requi
except OSError:
prev = None
_reach.write_snippet(vhost, body.reach, body.mesh)
if not _reload_nginx(): # nginx -t failed → roll back
if not await asyncio.to_thread(_reload_nginx): # nginx -t failed → roll back
try:
if prev is not None:
p.write_text(prev)
else:
p.unlink(missing_ok=True)
finally:
_reload_nginx() # best-effort restore of last-good
await asyncio.to_thread(_reload_nginx) # best-effort restore of last-good
raise HTTPException(status_code=500,
detail="nginx validation failed; exposure unchanged")
# nginx reloaded OK — now apply Tor, then audit the confirmed change.

View File

@ -64,6 +64,17 @@ def test_lan_plus_mesh_allows_mesh_denies_external():
assert _would_allow(s, "203.0.113.7") is False
def test_localhost_plus_mesh_allows_mesh_denies_lan_and_external():
# 10.10.0.5 already falls inside lan's 10.0.0.0/8, so the lan+mesh case
# above would pass even without the mesh allow line. localhost does NOT
# admit LAN, so this case uniquely isolates the mesh allow's effect.
s = reach_snippet("localhost", True)
assert _would_allow(s, "10.10.0.5") is True # mesh — allowed
assert _would_allow(s, "10.20.30.40") is False # LAN — still denied
assert _would_allow(s, "203.0.113.7") is False # external — denied
assert _would_allow(s, "127.0.0.1") is True # localhost — allowed
def test_wan_snippet_allows_external():
s = reach_snippet("wan", False)
assert _would_allow(s, "203.0.113.7") is True