PC set-up: one line per PC (/setup/<name>.ps1), the admin laptop always let in, and the admin check no longer breaks the script

- the inserted administrator check split the header comment, leaving '} for ... run ONCE' as code: WS and SC
  join.ps1 failed to parse (Windows' parser: Missing opening '(' after keyword 'for'); now after the whole line
- site.admin_ips / admin_keys (laptop 10.6.7.38, fixed in UniFi) go into every PC script's firewall rule and key
  files, and into the Mac join line, so running a set-up again never shuts the laptop out
- scripts verified by Windows' own PowerShell parser on the NA Lighting PC

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 16:29:36 -04:00
co-authored by Claude Opus 5.5
parent 0813734e78
commit afd2758d87
11 changed files with 117 additions and 11 deletions
+40
View File
@@ -627,3 +627,43 @@ class TestLongerHolds(unittest.TestCase):
self.assertEqual(pages, {"down": [], "up": [1], "2000": [19], "3000": [98]})
self.assertEqual(st["options"]["runWhileHeld"], [2000, 3000])
self.assertEqual(schema.validate(cfg)[0], [])
class TestPcScripts(unittest.TestCase):
"""The PC scripts: the admin check after the whole header line, the admin laptop let in, one line per PC."""
def cfg(self):
cfg = json.load(open(os.path.join(ROOT, "config.json")))
cfg["site"]["admin_ips"] = ["10.6.7.38"]
cfg["site"]["admin_keys"] = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITESTKEY christian-laptop@waters"]
return cfg
def test_the_admin_check_never_splits_a_line(self):
from settings import scripts
text = scripts.with_admin_check(scripts.windows_setup(self.cfg(), "bibletv"))
lines = text.split("\n")
i = next(i for i, ln in enumerate(lines) if ln.startswith("if (-not ([Security.Principal"))
self.assertTrue(lines[i - 1].startswith("# Status panel remote access for "))
self.assertEqual(lines[i + 2], "}") # nothing left after the brace
self.assertIn("$IngestIPs = @('10.1.1.1', '10.6.3.222', '10.6.7.38')", text) # the laptop through the firewall
self.assertIn("christian-laptop@waters", text)
join = campus.join_windows(self.cfg(), "http://10.5.2.60:8020").split("\n")
self.assertTrue(join[1].startswith("# Status panel remote access for "))
self.assertEqual(join[4], "}")
def test_a_bad_admin_key_is_refused(self):
from settings import scripts
cfg = self.cfg()
cfg["site"]["admin_keys"] = ["ssh-ed25519 AAAA'; rm -rf / #"]
with self.assertRaises(ValueError):
scripts.admin_keys(cfg)
def test_the_mac_join_line_takes_the_admin_key_too(self):
from settings import scripts
real = scripts.public_key
scripts.public_key = lambda cfg: ("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPANELKEY status-panel@sc", "status-panel@sc")
try:
text = campus.join_mac(self.cfg(), "http://10.5.2.60:8020")
finally:
scripts.public_key = real
self.assertIn("for A in 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITESTKEY christian-laptop@waters'; do", text)
+1 -1
View File
@@ -177,7 +177,7 @@ class TestSchemaMatchesCode(unittest.TestCase):
def test_every_declared_key_is_read_somewhere(self):
"""Dead settings are caught; keys only the settings page uses are listed here."""
ui_only = {"site.id", "site.name", "site.ingest_hostname", "site.ingest_ips", "site.contacts", "site.editing_code",
ui_only = {"site.id", "site.name", "site.ingest_hostname", "site.ingest_ips", "site.admin_ips", "site.admin_keys", "site.contacts", "site.editing_code",
"site.settings_port", "site.dvs_helper", "site.solo_dir", "hosts.*.name", "hosts.*.role",
"hosts.*.notes", "hosts.*.pingable", "hosts.*.runs", "hosts.*.networks", "hosts.*.manual_done",
"gear", "gear.*.location", "gear.*.notes", "gear.*.kind", "gear.*.address", "ready.ltc_campuses[].name", "ready.ltc_campuses[].short", "ready.ltc_campuses[].service_type", "atem.source_folder", "fixes.*.template", "fixes.*.params",
+1 -1
View File
@@ -29,7 +29,7 @@ class TestScripts(unittest.TestCase):
text = scripts.windows_setup(CFG, "lighting")
self.assertIn("$Key = '%s'" % KEY[0], text)
self.assertIn("$KeyMark = 'status-panel@NA-Ingest'", text)
self.assertIn("$IngestIPs = @('10.1.1.1', '10.6.3.222')", text)
self.assertIn("$IngestIPs = @('10.1.1.1', '10.6.3.222', '10.6.7.38')", text) # NA Ingest, then the admin laptop
for exe in ("Vista.exe", "Arena.exe", "rtpMIDI.exe"):
self.assertIn("(Find-Exe '%s')" % exe, text)
self.assertIn("foreach ($svc in @('rtpMIDIService'))", text)