fix: clean-install bugs — Tor false-installed, WG port-check honesty, encrypted backup upload
Unit Tests / test (push) Successful in 13m7s
Unit Tests / test (push) Successful in 13m7s
Three independent bugs surfaced during pic1 clean-install testing: 1. Tor _exit_status hardcoded configured=True regardless of whether Tor was actually installed. Status now flows through the same store-installed / container-running bridge used by every other optional service, so Tor only reports installed when the container is present and running. 2. check_port_open compared the port from wg0.conf against the kernel-reported listening port, causing false "port closed" results whenever the conf and the running container were momentarily out of sync. The function is now an honest liveness check: any wg0 interface that is up and has a "listening port:" line in `wg show` is considered open. The check-port API endpoint now also returns the actual kernel listening_port and a port_mismatch flag so the UI can inform the user when a container recreate is needed. (The recreate machinery already exists via the port-change pending-restart path; this fix makes the mismatch visible rather than silently lying about reachability.) 3. upload_backup only handled .zip archives; encrypted .age blobs were rejected with a generic error. The endpoint now calls backup_crypto.is_encrypted() to detect Age-encrypted blobs and stores them verbatim as <id>.tar.gz.age with mode 0600 so they can be uploaded and then restored with a passphrase. The plaintext zip path is unchanged. Tests added/updated: test_connectivity_manager.py (Tor status bridge), test_wireguard_manager.py + test_wireguard_endpoints.py (port-check liveness and mismatch flag), test_config_backup_restore_http.py (encrypted upload round-trip). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -615,27 +615,44 @@ class TestWireGuardSysctlAndPortCheck(unittest.TestCase):
|
||||
self.assertTrue(result)
|
||||
|
||||
@patch('subprocess.run')
|
||||
def test_check_port_open_wrong_port_returns_false(self, mock_run):
|
||||
# wg0 is up but listening on 51820 while wg0.conf says 51821 — must return False
|
||||
def test_check_port_open_true_despite_port_mismatch(self, mock_run):
|
||||
# wg0 is up and listening on 51820 while wg0.conf says 51821. The kernel
|
||||
# port is what actually serves traffic, so this is a reachability success;
|
||||
# check_port_open must NOT return False merely because of the mismatch.
|
||||
mock_run.return_value.returncode = 0
|
||||
mock_run.return_value.stdout = 'interface: wg0\n listening port: 51820\n'
|
||||
# Write wg0.conf with a different port so _get_configured_port() returns 51821
|
||||
cfg_path = os.path.join(self.wg.wireguard_dir, 'wg0.conf')
|
||||
with open(cfg_path, 'w') as f:
|
||||
f.write('[Interface]\nListenPort = 51821\nPrivateKey = abc\n')
|
||||
self.assertFalse(self.wg.check_port_open())
|
||||
self.assertTrue(self.wg.check_port_open())
|
||||
|
||||
@patch('subprocess.run')
|
||||
def test_check_port_open_explicit_port_matches(self, mock_run):
|
||||
def test_kernel_listening_port_parses_actual_bound_port(self, mock_run):
|
||||
mock_run.return_value.returncode = 0
|
||||
mock_run.return_value.stdout = 'interface: wg0\n listening port: 51820\n'
|
||||
self.assertEqual(self.wg._kernel_listening_port(), 51820)
|
||||
|
||||
@patch('subprocess.run')
|
||||
def test_kernel_listening_port_none_when_down(self, mock_run):
|
||||
mock_run.return_value.returncode = 1
|
||||
mock_run.return_value.stdout = ''
|
||||
self.assertIsNone(self.wg._kernel_listening_port())
|
||||
|
||||
@patch('subprocess.run')
|
||||
def test_check_port_open_true_when_interface_bound(self, mock_run):
|
||||
# check_port_open is a liveness check: an up interface with a bound port
|
||||
# is reachable, regardless of which port number it is.
|
||||
mock_run.return_value.returncode = 0
|
||||
mock_run.return_value.stdout = 'interface: wg0\n listening port: 12345\n'
|
||||
self.assertTrue(self.wg.check_port_open(port=12345))
|
||||
|
||||
@patch('subprocess.run')
|
||||
def test_check_port_open_explicit_port_mismatch(self, mock_run):
|
||||
def test_check_port_open_true_even_when_bound_port_differs(self, mock_run):
|
||||
# Bound port (51820) differs from the configured/expected port (51821),
|
||||
# but the interface is up and serving — this is reachable, not closed.
|
||||
mock_run.return_value.returncode = 0
|
||||
mock_run.return_value.stdout = 'interface: wg0\n listening port: 51820\n'
|
||||
self.assertFalse(self.wg.check_port_open(port=51821))
|
||||
self.assertTrue(self.wg.check_port_open(port=51821))
|
||||
|
||||
# ── get_peer_status ───────────────────────────────────────────────────────
|
||||
|
||||
|
||||
Reference in New Issue
Block a user