aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/tests')
-rw-r--r--packages/meshbay-node/tests/test_roster_pairing.py24
-rw-r--r--packages/meshbay-node/tests/test_webrtc_transport.py34
2 files changed, 49 insertions, 9 deletions
diff --git a/packages/meshbay-node/tests/test_roster_pairing.py b/packages/meshbay-node/tests/test_roster_pairing.py
index 665c060..a2f7cd1 100644
--- a/packages/meshbay-node/tests/test_roster_pairing.py
+++ b/packages/meshbay-node/tests/test_roster_pairing.py
@@ -737,8 +737,22 @@ def test_admin_authority_is_never_fetched_from_the_hub():
The fix M3 invites: ask the hub which key belongs to the operator. That would
hand a malicious hub the node — the same substitution as H3, one level deeper.
"""
- source = (Path(__file__).parent.parent
- / "src" / "meshbay_node" / "daemon.py").read_text()
- admin_region = source[source.find("_legacy_admin_pk"):]
- assert "pubkeys" not in admin_region.split("def ")[1], (
- "node authority must never be resolved through a hub lookup")
+ src = Path(__file__).parent.parent / "src" / "meshbay_node"
+
+ verifier = (src / "transport" / "webrtc_server.py").read_text()
+ body = verifier[verifier.index("async def _verify_admin_sig"):]
+ body = body[:body.index("\n def ", 1)]
+ assert "operator_pks" in body, "the roster is where authority comes from"
+ # Past the docstring: it names what was removed on purpose, so a reader knows
+ # not to put it back. What must not reappear is code.
+ code = body[body.index('"""', body.index('"""') + 3):]
+ for forbidden in ("hub", "pubkeys", "admin_pk_ed25519"):
+ assert forbidden not in code, (
+ f"_verify_admin_sig mentions {forbidden!r} — authority must come from "
+ "the local roster and nothing else")
+
+ daemon = (src / "daemon.py").read_text()
+ assert "has_operator()" in daemon, "the daemon reads authority from the roster"
+ assert "admin_pk_ed25519" not in daemon, (
+ "the node.toml operator key is gone; it must not come back as a second "
+ "source of authority")
diff --git a/packages/meshbay-node/tests/test_webrtc_transport.py b/packages/meshbay-node/tests/test_webrtc_transport.py
index 93cd3fd..cc0c6a2 100644
--- a/packages/meshbay-node/tests/test_webrtc_transport.py
+++ b/packages/meshbay-node/tests/test_webrtc_transport.py
@@ -823,8 +823,31 @@ async def test_webrtc_dtls_channel_binding_detects_mitm(sk_node, sk_hub, gek, sh
await transport.close_all()
+async def _paired_operator_roster(tmp_path, sk_admin):
+ """
+ A roster holding one operator, which is the only thing that authorizes an
+ admin operation now. It used to be enough to name a key in node.toml; that
+ path is gone, so these tests build the authority the way an operator does —
+ by pairing.
+ """
+ from meshbay_node.roster import Roster
+
+ roster = Roster(db_path=tmp_path / "roster.db")
+ await roster.open()
+ await roster.pin_identity(
+ user_id="user-001", username="operator",
+ pk_ed25519=base64.b64encode(sk_admin.public_key().public_bytes(
+ encoding=serialization.Encoding.Raw,
+ format=serialization.PublicFormat.Raw)).decode(),
+ pk_x25519="", via="test")
+ await roster.set_member(group_id="", user_id="user-001", role="operator",
+ status="active", approved_by="test")
+ return roster
+
+
@pytest.mark.asyncio
-async def test_webrtc_admin_challenge_response(sk_node, sk_hub, gek, shared_dir):
+async def test_webrtc_admin_challenge_response(sk_node, sk_hub, gek, shared_dir,
+ tmp_path):
"""WebRTC DataChannel: admin file delete requires Ed25519 challenge-response."""
hub_pk_pem = _hub_pk_pem(sk_hub)
indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek)
@@ -837,7 +860,8 @@ async def test_webrtc_admin_challenge_response(sk_node, sk_hub, gek, shared_dir)
shared_root=shared_dir, index=indexer.index,
stun_servers=[],
)
- transport._ctx["admin_pk_ed25519"] = sk_admin.public_key()
+ transport._ctx["roster"] = await _paired_operator_roster(tmp_path, sk_admin)
+ transport._ctx["has_admin_authority"] = True
transport._ctx["node_user_id"] = "user-001"
browser_pc, channel, received = await _setup_peer(
@@ -871,7 +895,8 @@ async def test_webrtc_admin_challenge_response(sk_node, sk_hub, gek, shared_dir)
@pytest.mark.asyncio
-async def test_webrtc_admin_bad_signature_rejected(sk_node, sk_hub, gek, shared_dir):
+async def test_webrtc_admin_bad_signature_rejected(sk_node, sk_hub, gek, shared_dir,
+ tmp_path):
"""WebRTC DataChannel: wrong Ed25519 signature is rejected — hub can't fake admin."""
hub_pk_pem = _hub_pk_pem(sk_hub)
indexer = DirectoryIndexer(root=shared_dir, group_id="g", sk_node=sk_node, gek=gek)
@@ -885,7 +910,8 @@ async def test_webrtc_admin_bad_signature_rejected(sk_node, sk_hub, gek, shared_
shared_root=shared_dir, index=indexer.index,
stun_servers=[],
)
- transport._ctx["admin_pk_ed25519"] = sk_admin.public_key()
+ transport._ctx["roster"] = await _paired_operator_roster(tmp_path, sk_admin)
+ transport._ctx["has_admin_authority"] = True
transport._ctx["node_user_id"] = "user-001"
browser_pc, channel, received = await _setup_peer(