Files
computer-playbook/tests/unit/python/plugins/lookup/test_network_siblings.py
T
kevinveenbirkenbachandClaude Opus 5.5 66c8df6729 feat(network): serve roles on clearnet and onion from one registry
A node runs in NETWORK_MODE clearnet, tor or multi; empty derives multi when svc-net-tor is deployed. meta/networks.yml reachability narrows a role (modes, single_mode, each justified by a network-reachability nocheck), and utils/networks/reachability.py is the one registry every network decision goes through. services.tor keeps only the dependency bond; exclusive and primary are gone and Matrix is single_mode.

Every canonical domain gains one sibling per effective network, clearnet first. sys-stk-front-proxy renders one vhost per sibling, and TLS, CSP, injected snippets, redirects, the web health probe and the CSP crawler are decided per vhost. Cross-app URLs follow the network of the vhost being rendered, the SSO issuer stays single, clearnet vhosts of multi roles send Onion-Location, and the shared location forwards X-Forwarded-Host, which lets Wazuh derive its OIDC redirect per request again. The to_onion_url filter is removed; its two consumers render per vhost instead.

Measured before commit: on a clearnet node the domain map of all 108 apps and every CSP header are identical to HEAD; on a multi node every role keeps its clearnet domains first and only gains onion siblings, and no CSP source crosses networks except the SSO issuer.

Refs: docs/requirements/037-multi-network-serving.md

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 19:42:05 +02:00

69 lines
2.4 KiB
Python

"""Contract of ``lookup('network_siblings')``: every logical domain renders
once per network its app is served on, and exactly once overall."""
from __future__ import annotations
import unittest
from plugins.lookup.network_siblings import served_siblings
ONION = "abc123def456ghij789klmno000pqrstuvwx111yz222abc333def444gh.onion"
PRIMARY = "infinito.test"
class TestServedSiblings(unittest.TestCase):
def test_multi_app_renders_both_networks_from_the_canonical_domain(self) -> None:
domains = {"web-app-x": ["x.infinito.test", f"x.{ONION}"]}
self.assertEqual(
served_siblings("x.infinito.test", domains, PRIMARY, ONION),
["x.infinito.test", f"x.{ONION}"],
)
def test_multi_app_skips_the_non_canonical_sibling(self) -> None:
domains = {"web-app-x": ["x.infinito.test", f"x.{ONION}"]}
self.assertEqual(served_siblings(f"x.{ONION}", domains, PRIMARY, ONION), [])
def test_tor_only_app_maps_a_raw_clearnet_domain_to_its_onion(self) -> None:
domains = {"web-app-x": [f"x.{ONION}"]}
self.assertEqual(
served_siblings("x.infinito.test", domains, PRIMARY, ONION), [f"x.{ONION}"]
)
def test_clearnet_only_app_renders_one_vhost(self) -> None:
domains = {"web-app-x": ["x.infinito.test"]}
self.assertEqual(
served_siblings("x.infinito.test", domains, PRIMARY, ONION),
["x.infinito.test"],
)
def test_named_canonicals_fan_out_per_key(self) -> None:
domains = {
"web-app-x": {
"api": "api.infinito.test",
"web": "web.infinito.test",
"api_onion": f"api.{ONION}",
"web_onion": f"web.{ONION}",
}
}
self.assertEqual(
served_siblings("web.infinito.test", domains, PRIMARY, ONION),
["web.infinito.test", f"web.{ONION}"],
)
def test_unknown_domain_renders_as_given(self) -> None:
self.assertEqual(
served_siblings("elsewhere.example", {}, PRIMARY, ONION),
["elsewhere.example"],
)
def test_node_without_tor_renders_as_given(self) -> None:
domains = {"web-app-x": ["x.infinito.test"]}
self.assertEqual(
served_siblings("x.infinito.test", domains, PRIMARY, ""),
["x.infinito.test"],
)
if __name__ == "__main__":
unittest.main()