mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-08 11:46:35 +00:00
fix(cache): refuse a tor deploy whose node onion is empty
get_merged_domains gated the onion injection on node_onion being set AND svc-net-tor being in group_names. When the node was empty it answered the clearnet map with no error and no log line, and because group_names is part of the cache key, a clearnet map and an onion map coexist in one process under separate keys. One render then serves onion while another freezes a clearnet asset URL into a stylesheet. That URL is unrecoverable at request time: body_filter.lua returns a CSS response before onionize(), so the <link href> in the head is rewritten while the url(...) inside the stylesheet body is not. The symptom is a single toHaveCSS mismatch and nothing else. An empty node under a deployed svc-net-tor now raises. A scope carrying no group_names at all stays silent, because that is indistinguishable from a legitimate non-tor deploy. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
0f6278873f
commit
e16d807e62
2 files changed
+48
-1
No files matched your search
+40
@@ -403,5 +403,45 @@ class TestOnionFlagsAreRendered(unittest.TestCase):
|
||||
)
|
||||
|
||||
|
||||
class TestOnionNodeIsRequiredWhenTorIsDeployed(unittest.TestCase):
|
||||
"""A deploy carrying `svc-net-tor` without a provisioned node used to
|
||||
answer the clearnet map and cache it under its own key, because
|
||||
`group_names` is part of that key. One scope then served onion while
|
||||
another froze a clearnet asset URL into a stylesheet, which
|
||||
`body_filter.lua`'s `onionize` returns before rewriting.
|
||||
"""
|
||||
|
||||
ONION = TestOnionDomainInjection.ONION
|
||||
|
||||
def setUp(self) -> None:
|
||||
_reset_cache_for_tests()
|
||||
|
||||
def _merge(self, node, group_names):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
roles = _seed_minimal_role(Path(tmp))
|
||||
with patch(
|
||||
"utils.cache.applications.get_merged_applications",
|
||||
return_value={"svc-net-tor": {"services": {"tor": {"node": node}}}},
|
||||
):
|
||||
return cache_domains.get_merged_domains(
|
||||
variables={
|
||||
"DOMAIN_PRIMARY": "infinito.test",
|
||||
"group_names": group_names,
|
||||
},
|
||||
roles_dir=roles,
|
||||
templar=None,
|
||||
)
|
||||
|
||||
def test_an_empty_node_is_an_error(self):
|
||||
with self.assertRaisesRegex(ValueError, "services.tor.node"):
|
||||
self._merge("", ["svc-net-tor", "web-app-x"])
|
||||
|
||||
def test_a_provisioned_node_is_accepted(self):
|
||||
self.assertIsInstance(self._merge(self.ONION, ["svc-net-tor"]), dict)
|
||||
|
||||
def test_an_empty_node_is_fine_without_tor_in_the_groups(self):
|
||||
self.assertIsInstance(self._merge("", ["web-app-x"]), dict)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user