feat(device-edge): add canonical core channel deployment
This commit is contained in:
@@ -92,7 +92,7 @@ class DeviceEdgeVpsArtifactTest(unittest.TestCase):
|
||||
|
||||
def test_builders_are_deterministic_narrow_and_secret_free(self):
|
||||
self.require_runtime_cache()
|
||||
for phase in ("foundation", "backhaul", "relay"):
|
||||
for phase in ("foundation", "backhaul", "relay", "core-channel"):
|
||||
with self.subTest(phase=phase), tempfile.TemporaryDirectory(
|
||||
prefix=f"nodedc-vps-{phase}-"
|
||||
) as directory:
|
||||
@@ -164,7 +164,7 @@ class DeviceEdgeVpsArtifactTest(unittest.TestCase):
|
||||
old_inbox = RUNNER.INBOX_ROOT
|
||||
RUNNER.INBOX_ROOT = inbox
|
||||
try:
|
||||
for phase in ("foundation", "backhaul", "relay"):
|
||||
for phase in ("foundation", "backhaul", "relay", "core-channel"):
|
||||
result = self.build(
|
||||
inbox,
|
||||
phase,
|
||||
@@ -217,10 +217,55 @@ class DeviceEdgeVpsArtifactTest(unittest.TestCase):
|
||||
self.assertIn("b2_routes=unchanged", rendered)
|
||||
self.assertIn("command_transport=disabled", rendered)
|
||||
|
||||
def test_core_channel_plan_is_exact_and_keeps_tracker_ingress_closed(self):
|
||||
with tempfile.TemporaryDirectory(prefix="nodedc-vps-channel-plan-") as directory:
|
||||
inbox = Path(directory) / "inbox"
|
||||
inbox.mkdir()
|
||||
result = self.build(
|
||||
inbox,
|
||||
"core-channel",
|
||||
"device-edge-vps-core-channel-plan-001",
|
||||
)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
artifact = Path(json.loads(result.stdout)["artifact"])
|
||||
old_inbox = RUNNER.INBOX_ROOT
|
||||
RUNNER.INBOX_ROOT = inbox
|
||||
try:
|
||||
with patch.object(RUNNER, "assert_root"), patch.object(
|
||||
RUNNER,
|
||||
"preflight",
|
||||
return_value={"predecessor": "accepted-foundation-closed-channel"},
|
||||
), patch("builtins.print") as output:
|
||||
RUNNER.plan_artifact(str(artifact))
|
||||
finally:
|
||||
RUNNER.INBOX_ROOT = old_inbox
|
||||
rendered = "\n".join(
|
||||
" ".join(str(arg) for arg in call.args)
|
||||
for call in output.call_args_list
|
||||
)
|
||||
self.assertIn("phase=core-channel", rendered)
|
||||
self.assertIn(
|
||||
"predecessor=accepted-foundation-closed-channel",
|
||||
rendered,
|
||||
)
|
||||
self.assertIn(
|
||||
"public_core_channel=155.212.211.15:8443/tcp:tls13-mtls-h2",
|
||||
rendered,
|
||||
)
|
||||
self.assertIn("tracker_tcp_9921=closed", rendered)
|
||||
self.assertIn("public_b2_ingress=disabled", rendered)
|
||||
self.assertIn(
|
||||
"peer_trust=preprovisioned-pinned-self-signed-core-certificate+fingerprint",
|
||||
rendered,
|
||||
)
|
||||
self.assertIn("command_transport=disabled", rendered)
|
||||
self.assertIn("gelios=untouched", rendered)
|
||||
|
||||
def test_units_and_firewalls_keep_the_required_boundaries(self):
|
||||
source_root = SCRIPT_DIR.parent.parent / "device-plane"
|
||||
foundation = (source_root / "vps/config/nftables-foundation.conf").read_text()
|
||||
relay = (source_root / "vps/config/nftables-relay.conf").read_text()
|
||||
channel = (source_root / "vps/config/nftables-core-channel.conf").read_text()
|
||||
sshd = (source_root / "vps/config/00-nodedc-b2-vps.conf").read_text()
|
||||
backhaul = (source_root / "vps/config/backhaul_ssh_config").read_text()
|
||||
tailscale_unit = (
|
||||
@@ -230,11 +275,16 @@ class DeviceEdgeVpsArtifactTest(unittest.TestCase):
|
||||
backhaul_unit = (
|
||||
source_root / "vps/systemd/nodedc-b2-backhaul.service"
|
||||
).read_text()
|
||||
channel_unit = (
|
||||
source_root / "vps/systemd/nodedc-device-edge-channel.service"
|
||||
).read_text()
|
||||
|
||||
self.assertIn("policy drop", foundation)
|
||||
self.assertIn("tcp dport 22", foundation)
|
||||
self.assertNotIn("tcp dport 9921", foundation)
|
||||
self.assertIn("tcp dport 9921", relay)
|
||||
self.assertIn("tcp dport 8443", channel)
|
||||
self.assertNotIn("tcp dport 9921", channel)
|
||||
self.assertIn("PasswordAuthentication no", sshd)
|
||||
self.assertIn("AllowTcpForwarding no", sshd)
|
||||
self.assertIn("StrictHostKeyChecking yes", backhaul)
|
||||
@@ -248,6 +298,15 @@ class DeviceEdgeVpsArtifactTest(unittest.TestCase):
|
||||
self.assertNotIn("User=nodedc-edge", relay_unit)
|
||||
self.assertIn("DEVICE_EDGE_RELAY_SOURCE_POLICY=public-ipv4-only", relay_unit)
|
||||
self.assertIn("MemoryMax=192M", relay_unit)
|
||||
self.assertIn("User=nodedc-channel", channel_unit)
|
||||
self.assertIn("node --jitless", channel_unit)
|
||||
self.assertIn("MemoryMax=128M", channel_unit)
|
||||
self.assertIn("MemorySwapMax=0", channel_unit)
|
||||
self.assertIn("CPUQuota=50%", channel_unit)
|
||||
self.assertIn("TasksMax=64", channel_unit)
|
||||
self.assertIn("LimitNOFILE=1024", channel_unit)
|
||||
self.assertNotIn("LocalForward", channel_unit)
|
||||
self.assertNotIn("DEVICE_EDGE_RELAY_UPSTREAM", channel_unit)
|
||||
|
||||
def test_runner_has_registered_rollback_and_no_generic_latest(self):
|
||||
source = RUNNER_PATH.read_text(encoding="utf-8")
|
||||
@@ -344,6 +403,82 @@ class DeviceEdgeVpsArtifactTest(unittest.TestCase):
|
||||
"old-source\n",
|
||||
)
|
||||
|
||||
def test_backup_restore_preserves_core_channel_source_trust_and_firewall(self):
|
||||
with tempfile.TemporaryDirectory(prefix="nodedc-vps-channel-backup-") as directory:
|
||||
root = Path(directory)
|
||||
live = root / "live"
|
||||
backups = root / "backups"
|
||||
nft = root / "etc/nftables.conf"
|
||||
channel_unit = root / "etc/nodedc-device-edge-channel.service"
|
||||
trust = root / "state/channel-trust"
|
||||
backups.mkdir()
|
||||
nft.parent.mkdir(parents=True)
|
||||
trust.mkdir(parents=True)
|
||||
nft.write_text("foundation-firewall\n", encoding="utf-8")
|
||||
channel_unit.parent.mkdir(parents=True, exist_ok=True)
|
||||
channel_unit.write_text("old-channel-unit\n", encoding="utf-8")
|
||||
(trust / "runtime.json").write_text("old-runtime\n", encoding="utf-8")
|
||||
for relative in RUNNER.CORE_CHANNEL_ENTRIES:
|
||||
target = live / relative
|
||||
if relative.endswith("/src"):
|
||||
target.mkdir(parents=True)
|
||||
(target / "server.mjs").write_text("old-channel-source\n", encoding="utf-8")
|
||||
else:
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
target.write_text(f"old:{relative}\n", encoding="utf-8")
|
||||
|
||||
old_live = RUNNER.LIVE_ROOT
|
||||
old_backups = RUNNER.BACKUP_ROOT
|
||||
old_nft = RUNNER.NFTABLES_CONFIG
|
||||
old_unit = RUNNER.CHANNEL_UNIT
|
||||
old_trust = RUNNER.CHANNEL_TRUST_ROOT
|
||||
RUNNER.LIVE_ROOT = live
|
||||
RUNNER.BACKUP_ROOT = backups
|
||||
RUNNER.NFTABLES_CONFIG = nft
|
||||
RUNNER.CHANNEL_UNIT = channel_unit
|
||||
RUNNER.CHANNEL_TRUST_ROOT = trust
|
||||
completed = subprocess.CompletedProcess([], 0, "table inet old {}\n", "")
|
||||
try:
|
||||
with patch.object(RUNNER, "run", return_value=completed), patch.object(
|
||||
RUNNER,
|
||||
"service_active",
|
||||
return_value=False,
|
||||
), patch.object(
|
||||
RUNNER,
|
||||
"systemctl",
|
||||
return_value=completed,
|
||||
), patch.object(
|
||||
RUNNER,
|
||||
"user_exists",
|
||||
return_value=False,
|
||||
):
|
||||
_backup_id, backup = RUNNER.create_backup(
|
||||
"channel-unit",
|
||||
"core-channel",
|
||||
)
|
||||
nft.write_text("candidate-firewall\n", encoding="utf-8")
|
||||
channel_unit.write_text("candidate-channel-unit\n", encoding="utf-8")
|
||||
(trust / "runtime.json").write_text("candidate-runtime\n", encoding="utf-8")
|
||||
(live / "services/device-edge-channel/src/server.mjs").write_text(
|
||||
"candidate-channel-source\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
RUNNER.restore_backup(backup, "core-channel")
|
||||
finally:
|
||||
RUNNER.LIVE_ROOT = old_live
|
||||
RUNNER.BACKUP_ROOT = old_backups
|
||||
RUNNER.NFTABLES_CONFIG = old_nft
|
||||
RUNNER.CHANNEL_UNIT = old_unit
|
||||
RUNNER.CHANNEL_TRUST_ROOT = old_trust
|
||||
|
||||
self.assertEqual(nft.read_text(), "foundation-firewall\n")
|
||||
self.assertEqual(channel_unit.read_text(), "old-channel-unit\n")
|
||||
self.assertEqual((trust / "runtime.json").read_text(), "old-runtime\n")
|
||||
self.assertEqual(
|
||||
(live / "services/device-edge-channel/src/server.mjs").read_text(),
|
||||
"old-channel-source\n",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
||||
|
||||
Reference in New Issue
Block a user