feat(cells): Phase 3 tests + Phase 4 UI for cell service-sharing
Phase 3 — tests (50 new, total now 1071): - test_cell_link_manager: atomicity (WG fail → DNS not called, link not persisted), DNS warning non-fatal, inbound_services arg, unknown service filtered, update/get permissions, lazy migration of legacy entries - test_wireguard_manager: subnet overlap rejection (exact, supernet, adjacent non-overlapping, different class-A, honours wg0.conf configured network) - test_firewall_manager: _cell_tag sanitisation, apply_cell_rules emits correct ACCEPT/DROP per service + catch-all DROP, clear_cell_rules no-op and exact line removal, apply_all_cell_rules iterates with correct args - test_cells_endpoints: RuntimeError→400, GET /services, GET/PUT permissions (200/400/404 paths, service name validation, arg forwarding) Phase 4 — UI: - CellNetwork.jsx: replace flat cell list with CellPanel expandable cards; add ServiceShareToggle (ARIA switch, saves immediately), InboundServiceBadge (read-only), DisconnectConfirmModal (replaces window.confirm); relative timestamps; paste validation on blur; WireGuard status merged by public_key - api.js: add cellLinkAPI.getPermissions, updatePermissions, getServices Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -629,5 +629,80 @@ class TestWireGuardSysctlAndPortCheck(unittest.TestCase):
|
||||
self.assertEqual(statuses, {})
|
||||
|
||||
|
||||
class TestAddCellPeerSubnetOverlap(unittest.TestCase):
|
||||
"""Verify that add_cell_peer rejects a vpn_subnet that overlaps the local WG network."""
|
||||
|
||||
def setUp(self):
|
||||
self.test_dir = tempfile.mkdtemp()
|
||||
self.data_dir = os.path.join(self.test_dir, 'data')
|
||||
self.config_dir = os.path.join(self.test_dir, 'config')
|
||||
os.makedirs(self.data_dir, exist_ok=True)
|
||||
os.makedirs(self.config_dir, exist_ok=True)
|
||||
patcher = patch.object(WireGuardManager, '_syncconf', return_value=None)
|
||||
self.mock_sync = patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
self.wg = WireGuardManager(self.data_dir, self.config_dir)
|
||||
# Write a known wg0.conf so _get_configured_network() returns 10.0.0.0/24
|
||||
self._write_wg_conf(address='10.0.0.1/24')
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.test_dir)
|
||||
|
||||
def _write_wg_conf(self, address='10.0.0.1/24', port=51820):
|
||||
conf = (
|
||||
f'[Interface]\n'
|
||||
f'PrivateKey = dummykey\n'
|
||||
f'Address = {address}\n'
|
||||
f'ListenPort = {port}\n'
|
||||
)
|
||||
cf = self.wg._config_file()
|
||||
os.makedirs(os.path.dirname(cf), exist_ok=True)
|
||||
with open(cf, 'w') as f:
|
||||
f.write(conf)
|
||||
|
||||
# Public key is 44 chars ending in '=' — required by validation in add_cell_peer
|
||||
_CELL_PUBKEY = 'cmVtb3RlcHVia2V5X2Zvcl90ZXN0c193Z3Rlc3QxMiE='
|
||||
|
||||
def test_add_cell_peer_overlapping_subnet_returns_false(self):
|
||||
"""vpn_subnet that exactly matches the local WG network must be rejected."""
|
||||
# local is 10.0.0.0/24; remote is also 10.0.0.0/24 — clear overlap
|
||||
ok = self.wg.add_cell_peer(
|
||||
'remote', self._CELL_PUBKEY, '5.6.7.8:51821', '10.0.0.0/24'
|
||||
)
|
||||
self.assertFalse(ok)
|
||||
|
||||
def test_add_cell_peer_partially_overlapping_subnet_returns_false(self):
|
||||
"""A remote subnet that contains the local network (e.g. /16 ⊃ /24) is rejected."""
|
||||
# 10.0.0.0/16 contains 10.0.0.0/24 → overlaps
|
||||
ok = self.wg.add_cell_peer(
|
||||
'remote', self._CELL_PUBKEY, '5.6.7.8:51821', '10.0.0.0/16'
|
||||
)
|
||||
self.assertFalse(ok)
|
||||
|
||||
def test_add_cell_peer_non_overlapping_subnet_accepted(self):
|
||||
"""A remote subnet distinct from the local WG network must be accepted."""
|
||||
# local is 10.0.0.0/24; remote is 10.0.1.0/24 — no overlap
|
||||
ok = self.wg.add_cell_peer(
|
||||
'remote', self._CELL_PUBKEY, '5.6.7.8:51821', '10.0.1.0/24'
|
||||
)
|
||||
self.assertTrue(ok)
|
||||
|
||||
def test_add_cell_peer_no_overlap_different_class_a(self):
|
||||
"""A completely different address space is accepted."""
|
||||
# local is 10.0.0.0/24; remote is 192.168.5.0/24 — no overlap
|
||||
ok = self.wg.add_cell_peer(
|
||||
'remote', self._CELL_PUBKEY, '5.6.7.8:51821', '192.168.5.0/24'
|
||||
)
|
||||
self.assertTrue(ok)
|
||||
|
||||
def test_add_cell_peer_overlap_check_uses_configured_network(self):
|
||||
"""When wg0.conf says 172.16.0.1/12, overlapping that range is rejected."""
|
||||
self._write_wg_conf(address='172.16.0.1/12')
|
||||
ok = self.wg.add_cell_peer(
|
||||
'remote', self._CELL_PUBKEY, '5.6.7.8:51821', '172.16.0.0/12'
|
||||
)
|
||||
self.assertFalse(ok)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user