source: trunk/integration/test_tor.py

Last change on this file was e458fe7, checked in by Florian Sesser <florian@…>, at 2025-05-16T19:08:57Z

Updated chutney runs on Python 3.12 just fine

  • Property mode set to 100644
File size: 5.8 KB
Line 
1"""
2Ported to Python 3.
3"""
4
5import sys
6from os.path import join
7from os import environ
8
9import pytest
10import pytest_twisted
11
12from . import util
13
14from twisted.python.filepath import (
15    FilePath,
16)
17
18from allmydata.test.common import (
19    write_introducer,
20)
21from allmydata.client import read_config
22from allmydata.util.deferredutil import async_to_deferred
23
24# see "conftest.py" for the fixtures (e.g. "tor_network")
25
26# XXX: Integration tests that involve Tor do not run reliably on
27# Windows.  They are skipped for now, in order to reduce CI noise.
28#
29# https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3347
30if sys.platform.startswith('win'):
31    pytest.skip('Skipping Tor tests on Windows', allow_module_level=True)
32
33@pytest_twisted.inlineCallbacks
34def test_onion_service_storage(reactor, request, temp_dir, flog_gatherer, tor_network, tor_introducer_furl):
35    """
36    Two nodes and an introducer all configured to use Tahoe.
37
38    The two nodes can talk to the introducer and each other: we upload to one
39    node, read from the other.
40    """
41    carol = yield _create_anonymous_node(reactor, 'carol', 8100, request, temp_dir, flog_gatherer, tor_network, tor_introducer_furl, 2)
42    dave = yield _create_anonymous_node(reactor, 'dave', 8101, request, temp_dir, flog_gatherer, tor_network, tor_introducer_furl, 2)
43    yield util.await_client_ready(carol, minimum_number_of_servers=2, timeout=600)
44    yield util.await_client_ready(dave, minimum_number_of_servers=2, timeout=600)
45    yield upload_to_one_download_from_the_other(reactor, temp_dir, carol, dave)
46
47
48@async_to_deferred
49async def upload_to_one_download_from_the_other(reactor, temp_dir, upload_to: util.TahoeProcess, download_from: util.TahoeProcess):
50    """
51    Ensure both nodes are connected to "a grid" by uploading something via one
52    node, and retrieve it using the other.
53    """
54
55    gold_path = join(temp_dir, "gold")
56    with open(gold_path, "w") as f:
57        f.write(
58            "The object-capability model is a computer security model. A "
59            "capability describes a transferable right to perform one (or "
60            "more) operations on a given object."
61        )
62    # XXX could use treq or similar to POST these to their respective
63    # WUIs instead ...
64
65    proto = util._CollectOutputProtocol()
66    reactor.spawnProcess(
67        proto,
68        sys.executable,
69        (
70            sys.executable, '-b', '-m', 'allmydata.scripts.runner',
71            '-d', upload_to.node_dir,
72            'put', gold_path,
73        ),
74        env=environ,
75    )
76    await proto.done
77    cap = proto.output.getvalue().strip().split()[-1]
78    print("capability: {}".format(cap))
79
80    proto = util._CollectOutputProtocol(capture_stderr=False)
81    reactor.spawnProcess(
82        proto,
83        sys.executable,
84        (
85            sys.executable, '-b', '-m', 'allmydata.scripts.runner',
86            '-d', download_from.node_dir,
87            'get', cap,
88        ),
89        env=environ,
90    )
91    await proto.done
92    download_got = proto.output.getvalue().strip()
93    assert download_got == open(gold_path, 'rb').read().strip()
94
95
96@pytest_twisted.inlineCallbacks
97def _create_anonymous_node(reactor, name, web_port, request, temp_dir, flog_gatherer, tor_network, introducer_furl, shares_total: int) -> util.TahoeProcess:
98    node_dir = FilePath(temp_dir).child(name)
99    if node_dir.exists():
100        raise RuntimeError(
101            "A node already exists in '{}'".format(node_dir)
102        )
103    print(f"creating {node_dir.path} with introducer {introducer_furl}")
104    node_dir.makedirs()
105    proto = util._DumpOutputProtocol(None)
106    reactor.spawnProcess(
107        proto,
108        sys.executable,
109        (
110            sys.executable, '-b', '-m', 'allmydata.scripts.runner',
111            'create-node',
112            '--nickname', name,
113            '--webport', str(web_port),
114            '--introducer', introducer_furl,
115            '--hide-ip',
116            '--tor-control-port', tor_network.client_control_endpoint,
117            '--listen', 'tor',
118            '--shares-needed', '1',
119            '--shares-happy', '1',
120            '--shares-total', str(shares_total),
121            node_dir.path,
122        ),
123        env=environ,
124        )
125    yield proto.done
126
127
128    # Which services should this client connect to?
129    write_introducer(node_dir, "default", introducer_furl)
130    util.basic_node_configuration(request, flog_gatherer.furl, node_dir.path)
131
132    config = read_config(node_dir.path, "tub.port")
133    config.set_config("tor", "onion", "true")
134    config.set_config("tor", "onion.external_port", "3457")
135    config.set_config("tor", "control.port", tor_network.client_control_endpoint)
136    config.set_config("tor", "onion.private_key_file", "private/tor_onion.privkey")
137
138    print("running")
139    result = yield util._run_node(reactor, node_dir.path, request, None)
140    print("okay, launched")
141    return result
142
143@pytest.mark.skipif(sys.platform.startswith('darwin'), reason='This test has issues on macOS')
144@pytest_twisted.inlineCallbacks
145def test_anonymous_client(reactor, request, temp_dir, flog_gatherer, tor_network, introducer_furl):
146    """
147    A normal node (normie) and a normal introducer are configured, and one node
148    (anonymoose) which is configured to be anonymous by talking via Tor.
149
150    Anonymoose should be able to communicate with normie.
151
152    TODO how to ensure that anonymoose is actually using Tor?
153    """
154    normie = yield util._create_node(
155        reactor, request, temp_dir, introducer_furl, flog_gatherer, "normie",
156        web_port="tcp:9989:interface=localhost",
157        storage=True, needed=1, happy=1, total=1,
158    )
159    yield util.await_client_ready(normie)
160
161    anonymoose = yield _create_anonymous_node(reactor, 'anonymoose', 8102, request, temp_dir, flog_gatherer, tor_network, introducer_furl, 1)
162    yield util.await_client_ready(anonymoose, minimum_number_of_servers=1, timeout=1200)
163
164    yield upload_to_one_download_from_the_other(reactor, temp_dir, normie, anonymoose)
Note: See TracBrowser for help on using the repository browser.