test: simulate permission errors in wireguard tests instead of chmod 000
All checks were successful
CI / lint (pull_request) Successful in 29s
CI / validate-json (pull_request) Successful in 23s
CI / markdown-links (pull_request) Successful in 21s
CI / test (pull_request) Successful in 1m47s

CI runs pytest as root, which ignores directory permissions, so the
0o000-directory tests didn't hit the error path: the enable test went on
to call the real systemctl and failed, and the status test passed only
by accident. Monkeypatch the PermissionError instead, and stub reload so
the enable test can never shell out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Robert Syrnicki 2026-10-07 16:24:51 +02:00
parent 2f6c31a26e
commit 9076b85304

View file

@ -6,6 +6,7 @@ to its pre-call state.
"""
import subprocess
from pathlib import Path
import pytest
@ -59,14 +60,20 @@ def test_enable_requires_wg_config(tmp_path):
wireguard.set_tunnel_enabled(True, conf_path=tmp_path / "furtka-gw.conf")
def test_enable_surfaces_clean_error_on_unreadable_conf_dir(tmp_path):
restricted = tmp_path / "restricted"
restricted.mkdir(mode=0o000)
try:
with pytest.raises(wireguard.WireguardError, match="could not access"):
wireguard.set_tunnel_enabled(True, wg=WG, conf_path=restricted / "furtka-gw.conf")
finally:
restricted.chmod(0o700)
def test_enable_surfaces_clean_error_on_unreadable_conf_dir(tmp_path, monkeypatch):
# Simulated rather than via a 0o000 directory: CI runs as root, which
# ignores directory permissions.
def denied(self, *a, **kw):
raise PermissionError(13, "Permission denied", str(self))
monkeypatch.setattr(Path, "mkdir", denied)
def must_not_reload(action):
raise AssertionError("systemctl must not run when the conf can't be written")
conf_path = tmp_path / "restricted" / "furtka-gw.conf"
with pytest.raises(wireguard.WireguardError, match="could not access"):
wireguard.set_tunnel_enabled(True, wg=WG, conf_path=conf_path, reload=must_not_reload)
def test_default_conf_path_uses_env_override(monkeypatch, tmp_path):
@ -157,20 +164,23 @@ def test_status_not_configured(tmp_path):
assert s == {"configured": False, "latest_handshake": None}
def test_status_survives_unreadable_conf_path(tmp_path):
def test_status_survives_unreadable_conf_path(tmp_path, monkeypatch):
"""Regression: an inaccessible parent directory raises PermissionError
even for a path that doesn't exist yet — confirmed by actually hitting
this against a real box's /etc/wireguard/ as a non-root user, which
crashed the whole /api/gateway/status request with a raw traceback.
A read-only status check must degrade to "not configured", never 500.
"""
restricted = tmp_path / "restricted"
restricted.mkdir(mode=0o000)
try:
s = wireguard.status(conf_path=restricted / "furtka-gw.conf")
assert s == {"configured": False, "latest_handshake": None}
finally:
restricted.chmod(0o700) # so tmp_path cleanup can remove it
# Simulated rather than via a 0o000 directory: CI runs as root, which
# ignores directory permissions.
def denied(self):
raise PermissionError(13, "Permission denied", str(self))
monkeypatch.setattr(Path, "is_file", denied)
s = wireguard.status(conf_path=tmp_path / "restricted" / "furtka-gw.conf")
assert s == {"configured": False, "latest_handshake": None}
def test_status_configured_reports_handshake(tmp_path):