mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-06-07 14:53:53 +02:00
396 lines
15 KiB
Python
396 lines
15 KiB
Python
"""Small route-level smoke lane for private/runtime-critical flows.
|
|
|
|
This file is intentionally compact. It exercises the actual ASGI app for:
|
|
- wormhole join
|
|
- gate open/send on the encrypted path
|
|
- DM send
|
|
- public Meshtastic send
|
|
|
|
The goal is to catch route wiring and integration regressions that deep
|
|
targeted crypto tests can miss.
|
|
"""
|
|
|
|
import asyncio
|
|
import json
|
|
import time
|
|
from collections import deque
|
|
from types import SimpleNamespace
|
|
|
|
from httpx import ASGITransport, AsyncClient
|
|
from services.mesh.mesh_protocol import build_signed_context
|
|
|
|
|
|
class _TestGateManager:
|
|
_SECRET = "test-gate-secret-for-envelope-encryption"
|
|
|
|
def get_gate_secret(self, gate_id: str) -> str:
|
|
return self._SECRET
|
|
|
|
def can_enter(self, sender_id: str, gate_id: str):
|
|
return True, "ok"
|
|
|
|
def record_message(self, gate_id: str):
|
|
pass
|
|
|
|
def get_gate(self, gate_id: str):
|
|
return {"gate_id": gate_id, "welcome": "", "fixed": False}
|
|
|
|
|
|
def _fresh_gate_state(tmp_path, monkeypatch):
|
|
from services import wormhole_supervisor
|
|
from services.mesh import mesh_gate_mls, mesh_hashchain, mesh_reputation, mesh_secure_storage, mesh_wormhole_persona
|
|
|
|
monkeypatch.setattr(mesh_secure_storage, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_secure_storage, "MASTER_KEY_FILE", tmp_path / "wormhole_secure_store.key")
|
|
monkeypatch.setattr(mesh_gate_mls, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_gate_mls, "STATE_FILE", tmp_path / "wormhole_gate_mls.json")
|
|
monkeypatch.setattr(mesh_wormhole_persona, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_wormhole_persona, "PERSONA_FILE", tmp_path / "wormhole_persona.json")
|
|
monkeypatch.setattr(
|
|
mesh_wormhole_persona,
|
|
"LEGACY_DM_IDENTITY_FILE",
|
|
tmp_path / "wormhole_identity.json",
|
|
)
|
|
monkeypatch.setattr(wormhole_supervisor, "get_transport_tier", lambda: "private_transitional")
|
|
monkeypatch.setattr(
|
|
wormhole_supervisor,
|
|
"get_wormhole_state",
|
|
lambda: {"configured": True, "ready": True, "arti_ready": True, "rns_ready": False},
|
|
)
|
|
monkeypatch.setattr(mesh_reputation, "gate_manager", _TestGateManager(), raising=False)
|
|
monkeypatch.setattr(
|
|
mesh_hashchain,
|
|
"gate_store",
|
|
mesh_hashchain.GateMessageStore(data_dir=str(tmp_path / "gate_messages")),
|
|
)
|
|
mesh_gate_mls.reset_gate_mls_state()
|
|
return mesh_gate_mls, mesh_wormhole_persona
|
|
|
|
|
|
REQUEST_CLAIM = [{"type": "requests", "token": "request-claim-token"}]
|
|
_KNOWN_TOKEN_HASH = "a1b2c3d4e5f6789012345678abcdef0123456789abcdef0123456789abcdef01"
|
|
|
|
|
|
def _fake_consume_token(*, sender_token, recipient_id, delivery_class, recipient_token=""):
|
|
return {
|
|
"ok": True,
|
|
"sender_token_hash": _KNOWN_TOKEN_HASH,
|
|
"sender_id": "alice",
|
|
"public_key": "cHVi",
|
|
"public_key_algo": "Ed25519",
|
|
"protocol_version": "infonet/2",
|
|
"recipient_id": recipient_id or "bob",
|
|
"delivery_class": delivery_class,
|
|
"issued_at": int(time.time()) - 10,
|
|
"expires_at": int(time.time()) + 290,
|
|
}
|
|
|
|
|
|
def _fresh_dm_route_env(tmp_path, monkeypatch):
|
|
import main
|
|
from services import wormhole_supervisor
|
|
from services.config import get_settings
|
|
from services.mesh import (
|
|
mesh_crypto,
|
|
mesh_dm_relay,
|
|
mesh_hashchain,
|
|
mesh_secure_storage,
|
|
mesh_wormhole_contacts,
|
|
mesh_wormhole_sender_token,
|
|
)
|
|
|
|
monkeypatch.setattr(mesh_dm_relay, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_dm_relay, "RELAY_FILE", tmp_path / "dm_relay.json")
|
|
monkeypatch.setattr(mesh_secure_storage, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_secure_storage, "MASTER_KEY_FILE", tmp_path / "wormhole_secure_store.key")
|
|
get_settings.cache_clear()
|
|
relay = mesh_dm_relay.DMRelay()
|
|
monkeypatch.setattr(mesh_dm_relay, "dm_relay", relay)
|
|
|
|
monkeypatch.setattr(mesh_wormhole_contacts, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_wormhole_contacts, "CONTACTS_FILE", tmp_path / "wormhole_dm_contacts.json")
|
|
mesh_wormhole_contacts.observe_remote_prekey_identity("bob", fingerprint="aa" * 32)
|
|
monkeypatch.setattr(
|
|
mesh_wormhole_contacts,
|
|
"_derive_expected_contact_sas_phrase",
|
|
lambda *_args, **_kwargs: {"ok": True, "phrase": "able acid", "peer_ref": "bob", "words": 2},
|
|
)
|
|
mesh_wormhole_contacts.confirm_sas_verification("bob", "able acid")
|
|
|
|
monkeypatch.setattr(wormhole_supervisor, "get_transport_tier", lambda: "private_strong")
|
|
monkeypatch.setattr(
|
|
wormhole_supervisor,
|
|
"get_wormhole_state",
|
|
lambda: {"configured": True, "ready": True, "arti_ready": True, "rns_ready": True},
|
|
)
|
|
monkeypatch.setattr(main, "_current_private_lane_tier", lambda *_args, **_kwargs: "private_strong")
|
|
monkeypatch.setattr(main, "_verify_signed_write", lambda **_kwargs: (True, "ok"))
|
|
monkeypatch.setattr(main, "_secure_dm_enabled", lambda: False)
|
|
monkeypatch.setattr(mesh_hashchain.infonet, "validate_and_set_sequence", lambda *_args, **_kwargs: (True, "ok"))
|
|
monkeypatch.setattr(mesh_crypto, "verify_node_binding", lambda *_args, **_kwargs: True)
|
|
monkeypatch.setattr(main, "consume_wormhole_dm_sender_token", _fake_consume_token)
|
|
monkeypatch.setattr(mesh_wormhole_sender_token, "consume_wormhole_dm_sender_token", _fake_consume_token)
|
|
return relay
|
|
|
|
|
|
class _DummyBreaker:
|
|
def check_and_record(self, _priority):
|
|
return True, "ok"
|
|
|
|
|
|
class _FakeMeshtasticTransport:
|
|
NAME = "meshtastic"
|
|
|
|
def __init__(self, can_reach: bool = True, send_ok: bool = True):
|
|
self._can_reach = can_reach
|
|
self._send_ok = send_ok
|
|
self.sent = []
|
|
|
|
def can_reach(self, _envelope):
|
|
return self._can_reach
|
|
|
|
def send(self, envelope, _credentials):
|
|
from services.mesh.mesh_router import TransportResult
|
|
|
|
self.sent.append(envelope)
|
|
return TransportResult(self._send_ok, self.NAME, "sent")
|
|
|
|
|
|
class _FakeMeshRouter:
|
|
def __init__(self, meshtastic):
|
|
self.meshtastic = meshtastic
|
|
self.breakers = {"meshtastic": _DummyBreaker()}
|
|
self.route_called = False
|
|
|
|
def route(self, _envelope, _credentials):
|
|
self.route_called = True
|
|
return []
|
|
|
|
|
|
def _meshtastic_send_body(**overrides):
|
|
body = {
|
|
"destination": "!a0cc7a80",
|
|
"message": "hello mesh",
|
|
"sender_id": "!sb_sender",
|
|
"node_id": "!sb_sender",
|
|
"public_key": "pub",
|
|
"public_key_algo": "Ed25519",
|
|
"signature": "sig",
|
|
"sequence": 1,
|
|
"protocol_version": "1",
|
|
"channel": "LongFast",
|
|
"priority": "normal",
|
|
"ephemeral": False,
|
|
"transport_lock": "meshtastic",
|
|
"credentials": {"mesh_region": "US"},
|
|
}
|
|
body.update(overrides)
|
|
return body
|
|
|
|
|
|
def test_runtime_smoke_wormhole_join_route(monkeypatch):
|
|
import main
|
|
from routers import wormhole as wormhole_router
|
|
from services import node_settings
|
|
|
|
bootstrap_calls = []
|
|
node_setting_calls = []
|
|
refresh_calls = []
|
|
|
|
monkeypatch.setattr(
|
|
wormhole_router,
|
|
"read_wormhole_settings",
|
|
lambda: {
|
|
"enabled": True,
|
|
"transport": "direct",
|
|
"socks_proxy": "",
|
|
"socks_dns": True,
|
|
"anonymous_mode": False,
|
|
},
|
|
)
|
|
monkeypatch.setattr(wormhole_router, "write_wormhole_settings", lambda **kwargs: dict(kwargs))
|
|
monkeypatch.setattr(wormhole_router, "bootstrap_wormhole_identity", lambda: bootstrap_calls.append("identity"))
|
|
monkeypatch.setattr(
|
|
wormhole_router,
|
|
"bootstrap_wormhole_persona_state",
|
|
lambda: bootstrap_calls.append("persona"),
|
|
)
|
|
monkeypatch.setattr(
|
|
wormhole_router,
|
|
"connect_wormhole",
|
|
lambda **kwargs: {"ok": True, "ready": True, "reason": kwargs.get("reason", "")},
|
|
)
|
|
monkeypatch.setattr(wormhole_router, "get_transport_identity", lambda: {"node_id": "!sb_test_join"})
|
|
monkeypatch.setattr(node_settings, "write_node_settings", lambda **kwargs: node_setting_calls.append(kwargs))
|
|
monkeypatch.setattr(main, "_refresh_node_peer_store", lambda **kwargs: refresh_calls.append(kwargs) or {"ok": True})
|
|
|
|
async def _run():
|
|
async with AsyncClient(
|
|
transport=ASGITransport(app=main.app, client=("127.0.0.1", 54321)),
|
|
base_url="http://test",
|
|
) as ac:
|
|
response = await ac.post("/api/wormhole/join")
|
|
return response.status_code, response.json()
|
|
|
|
status_code, result = asyncio.run(_run())
|
|
|
|
assert status_code == 200
|
|
assert result["ok"] is True
|
|
assert result["identity"] == {"node_id": "!sb_test_join"}
|
|
assert bootstrap_calls == ["identity", "persona"]
|
|
assert node_setting_calls == [{"enabled": True}]
|
|
assert refresh_calls == [{}]
|
|
|
|
|
|
def test_runtime_smoke_gate_open_and_send_encrypted(tmp_path, monkeypatch):
|
|
import auth
|
|
import main
|
|
from routers import mesh_public
|
|
|
|
gate_mls_mod, persona_mod = _fresh_gate_state(tmp_path, monkeypatch)
|
|
gate_id = "smoke-gate"
|
|
|
|
persona_mod.bootstrap_wormhole_persona_state(force=True)
|
|
persona_mod.create_gate_persona(gate_id, label="scribe")
|
|
composed = gate_mls_mod.compose_encrypted_gate_message(gate_id, "smoke gate payload")
|
|
|
|
monkeypatch.setattr(main, "_verify_gate_access", lambda *_args, **_kwargs: "member")
|
|
monkeypatch.setattr(mesh_public, "_verify_gate_access", lambda *_args, **_kwargs: "member")
|
|
|
|
async def _run():
|
|
async with AsyncClient(transport=ASGITransport(app=main.app), base_url="http://test") as ac:
|
|
proof_response = await ac.post(
|
|
"/api/wormhole/gate/proof",
|
|
json={"gate_id": gate_id},
|
|
headers={"X-Admin-Key": auth._current_admin_key()},
|
|
)
|
|
post_response = await ac.post(
|
|
"/api/wormhole/gate/message/post-encrypted",
|
|
json={
|
|
"gate_id": gate_id,
|
|
"sender_id": composed["sender_id"],
|
|
"public_key": composed["public_key"],
|
|
"public_key_algo": composed["public_key_algo"],
|
|
"signature": composed["signature"],
|
|
"sequence": composed["sequence"],
|
|
"protocol_version": composed["protocol_version"],
|
|
"epoch": composed["epoch"],
|
|
"ciphertext": composed["ciphertext"],
|
|
"nonce": composed["nonce"],
|
|
"sender_ref": composed["sender_ref"],
|
|
"format": composed["format"],
|
|
"gate_envelope": composed.get("gate_envelope", ""),
|
|
"envelope_hash": composed.get("envelope_hash", ""),
|
|
"compat_reply_to": False,
|
|
},
|
|
headers={"X-Admin-Key": auth._current_admin_key()},
|
|
)
|
|
wait_response = await ac.get(
|
|
f"/api/mesh/infonet/messages/wait?gate={gate_id}&after=0&limit=10&timeout_ms=1000",
|
|
)
|
|
return proof_response.json(), post_response.json(), wait_response.status_code, wait_response.json()
|
|
|
|
try:
|
|
proof_result, post_result, wait_status, wait_result = asyncio.run(_run())
|
|
finally:
|
|
gate_mls_mod.reset_gate_mls_state()
|
|
|
|
assert proof_result["ok"] is True
|
|
assert proof_result["gate_id"] == gate_id
|
|
assert post_result["ok"] is True
|
|
assert wait_status == 200
|
|
assert wait_result["gate"] == gate_id
|
|
assert wait_result["changed"] is True
|
|
assert wait_result["count"] == 1
|
|
assert wait_result["messages"][0]["event_id"] == post_result["event_id"]
|
|
|
|
|
|
def test_runtime_smoke_dm_send_route(tmp_path, monkeypatch):
|
|
import main
|
|
|
|
relay = _fresh_dm_route_env(tmp_path, monkeypatch)
|
|
|
|
async def _run():
|
|
async with AsyncClient(transport=ASGITransport(app=main.app), base_url="http://test") as ac:
|
|
response = await ac.post(
|
|
"/api/mesh/dm/send",
|
|
json=(lambda body: body | {
|
|
"signed_context": build_signed_context(
|
|
event_type="dm_message",
|
|
kind="dm_send",
|
|
endpoint="/api/mesh/dm/send",
|
|
lane_floor="private_strong",
|
|
sequence_domain="dm_send",
|
|
node_id="alice",
|
|
sequence=body["sequence"],
|
|
payload={
|
|
"recipient_id": body["recipient_id"],
|
|
"delivery_class": body["delivery_class"],
|
|
"recipient_token": body["recipient_token"],
|
|
"ciphertext": body["ciphertext"],
|
|
"format": "mls1",
|
|
"msg_id": body["msg_id"],
|
|
"timestamp": body["timestamp"],
|
|
"sender_seal": body["sender_seal"],
|
|
"transport_lock": body["transport_lock"],
|
|
},
|
|
recipient_id=body["recipient_id"],
|
|
)
|
|
})(
|
|
{
|
|
"sender_id": "",
|
|
"sender_token": "opaque-sender-token",
|
|
"recipient_id": "bob",
|
|
"delivery_class": "request",
|
|
"recipient_token": "",
|
|
"ciphertext": "x3dh1:sealed-payload",
|
|
"msg_id": "runtime-smoke-dm-1",
|
|
"timestamp": int(time.time()),
|
|
"public_key": "cHVi",
|
|
"public_key_algo": "Ed25519",
|
|
"signature": "sig",
|
|
"sequence": 1,
|
|
"protocol_version": "infonet/2",
|
|
"transport_lock": "private_strong",
|
|
"sender_seal": "v3:test-seal-data",
|
|
}
|
|
),
|
|
)
|
|
return response.status_code, response.json()
|
|
|
|
status_code, result = asyncio.run(_run())
|
|
|
|
assert status_code == 200
|
|
assert result["ok"] is True
|
|
assert result["msg_id"] == "runtime-smoke-dm-1"
|
|
assert result["queued"] is True
|
|
assert result["delivery"]["local_state"] == "sealed_local"
|
|
|
|
|
|
def test_runtime_smoke_public_meshtastic_send_route(monkeypatch):
|
|
import main
|
|
from services.mesh import mesh_router as mesh_router_mod
|
|
from services.sigint_bridge import sigint_grid
|
|
|
|
fake_meshtastic = _FakeMeshtasticTransport(can_reach=True, send_ok=True)
|
|
fake_router = _FakeMeshRouter(fake_meshtastic)
|
|
fake_bridge = SimpleNamespace(messages=deque(maxlen=10))
|
|
|
|
monkeypatch.setattr(main, "_verify_signed_write", lambda **_kwargs: (True, "ok"))
|
|
monkeypatch.setattr(main, "_check_throttle", lambda *_args: (True, "ok"))
|
|
monkeypatch.setattr(mesh_router_mod, "mesh_router", fake_router)
|
|
monkeypatch.setattr(sigint_grid, "mesh", fake_bridge)
|
|
|
|
async def _run():
|
|
async with AsyncClient(transport=ASGITransport(app=main.app), base_url="http://test") as ac:
|
|
response = await ac.post("/api/mesh/send", json=_meshtastic_send_body())
|
|
return response.status_code, response.json()
|
|
|
|
status_code, result = asyncio.run(_run())
|
|
|
|
assert status_code == 200
|
|
assert result["ok"] is True
|
|
assert result["routed_via"] == "meshtastic"
|
|
assert fake_router.route_called is False
|
|
assert len(fake_meshtastic.sent) == 1
|