Example #1
0
def test_federated_nodes_connect_via_tls_and_verify(
        ursula_federated_test_config):
    node = make_federated_ursulas(ursula_config=ursula_federated_test_config,
                                  quantity=1).pop()
    node_deployer = node.get_deployer()

    node_deployer.addServices()
    node_deployer.catalogServers(node_deployer.hendrix)
    node_deployer.start()

    cert = node_deployer.cert.to_cryptography()
    cert_bytes = cert.public_bytes(serialization.Encoding.PEM)

    def check_node_with_cert(node, cert_file):
        response = requests.get("https://{}/public_information".format(
            node.rest_url()),
                                verify=cert_file)
        ursula = Ursula.from_bytes(response.content, federated_only=True)
        assert ursula == node

    try:
        with open("test-cert", "wb") as f:
            # f.write(cert.tbs_certificate_bytes.hex())
            f.write(cert_bytes)
        yield threads.deferToThread(check_node_with_cert, node, "test-cert")
    finally:
        os.remove("test-cert")
def test_one_node_stores_a_bunch_of_others(federated_ursulas,
                                           ursula_federated_test_config):
    the_chosen_seednode = list(federated_ursulas)[2]
    seed_node = the_chosen_seednode.seed_node_metadata()
    newcomer = make_federated_ursulas(
        ursula_config=ursula_federated_test_config,
        quantity=1,
        know_each_other=False,
        save_metadata=True,
        seed_nodes=[seed_node]).pop()

    assert not newcomer.known_nodes

    def start_lonely_learning_loop():
        newcomer.start_learning_loop()
        start = maya.now()
        # Loop until the_chosen_seednode is in storage.
        while not the_chosen_seednode in newcomer.node_storage.all(
                federated_only=True):
            passed = maya.now() - start
            if passed.seconds > 2:
                pytest.fail("Didn't find the seed node.")

    yield deferToThread(start_lonely_learning_loop)

    # The known_nodes are all saved in storage (and no others have been saved)
    assert list(newcomer.known_nodes.values()) == list(
        newcomer.node_storage.all(True))
Example #3
0
def fleet_of_highperf_mocked_ursulas(ursula_federated_test_config, request):
    try:
        quantity = request.param
    except AttributeError:
        quantity = 5000  # Bigass fleet by default; that's kinda the point.
    with GlobalLoggerSettings.pause_all_logging_while():
        with mock_secret_source():
            with mock_cert_storage, mock_cert_loading, mock_rest_app_creation, mock_cert_generation, mock_remember_node, mock_message_verification:
                _ursulas = make_federated_ursulas(ursula_config=ursula_federated_test_config,
                                                  quantity=quantity, know_each_other=False)
                all_ursulas = {u.checksum_address: u for u in _ursulas}
                for ursula in _ursulas:
                    ursula.known_nodes._nodes = all_ursulas
                    ursula.known_nodes.checksum = b"This is a fleet state checksum..".hex()
    return _ursulas
Example #4
0
def test_new_federated_ursula_announces_herself(ursula_federated_test_config):
    ursula_in_a_house, ursula_with_a_mouse = make_federated_ursulas(ursula_config=ursula_federated_test_config,
                                                                    quantity=2,
                                                                    know_each_other=False,
                                                                    network_middleware=MockRestMiddleware())

    # Neither Ursula knows about the other.
    assert ursula_in_a_house.known_nodes == ursula_with_a_mouse.known_nodes == {}

    ursula_in_a_house.remember_node(ursula_with_a_mouse)

    # OK, now, ursula_in_a_house knows about ursula_with_a_mouse, but not vice-versa.
    assert ursula_with_a_mouse in ursula_in_a_house.known_nodes.values()
    assert not ursula_in_a_house in ursula_with_a_mouse.known_nodes.values()

    # But as ursula_in_a_house learns, she'll announce herself to ursula_with_a_mouse.
    ursula_in_a_house.learn_from_teacher_node()

    assert ursula_with_a_mouse in ursula_in_a_house.known_nodes.values()
    assert ursula_in_a_house in ursula_with_a_mouse.known_nodes.values()
Example #5
0
def federated_ursulas(ursula_federated_test_config):
    _ursulas = make_federated_ursulas(
        ursula_config=ursula_federated_test_config,
        quantity=NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK)
    yield _ursulas
def test_emit_warning_upon_new_version(ursula_federated_test_config, caplog):
    nodes = make_federated_ursulas(ursula_config=ursula_federated_test_config,
                                   quantity=3,
                                   know_each_other=False)
    teacher, learner, new_node = nodes

    learner.remember_node(teacher)
    teacher.remember_node(learner)
    teacher.remember_node(new_node)

    new_node.TEACHER_VERSION = learner.LEARNER_VERSION + 1

    warnings = []

    def warning_trapper(event):
        if event['log_level'] == LogLevel.warn:
            warnings.append(event)

    globalLogPublisher.addObserver(warning_trapper)
    learner.learn_from_teacher_node()

    assert len(warnings) == 1
    assert warnings[0]['log_format'] == learner.unknown_version_message.format(
        new_node, new_node.TEACHER_VERSION, learner.LEARNER_VERSION)

    # Now let's go a little further: make the version totally unrecognizable.

    # First, there's enough garbage to at least scrape a potential checksum address
    fleet_snapshot = os.urandom(32 + 4)
    random_bytes = os.urandom(50)  # lots of garbage in here
    future_version = learner.LEARNER_VERSION + 42
    version_bytes = future_version.to_bytes(2, byteorder="big")
    crazy_bytes = fleet_snapshot + VariableLengthBytestring(version_bytes +
                                                            random_bytes)
    signed_crazy_bytes = bytes(teacher.stamp(crazy_bytes))

    Response = namedtuple("MockResponse", ("content", "status_code"))
    response = Response(content=signed_crazy_bytes + crazy_bytes,
                        status_code=200)

    learner._current_teacher_node = teacher
    learner.network_middleware.get_nodes_via_rest = lambda *args, **kwargs: response
    learner.learn_from_teacher_node()

    # If you really try, you can read a node representation from the garbage
    accidental_checksum = to_checksum_address(random_bytes[:20])
    accidental_nickname = nickname_from_seed(accidental_checksum)[0]
    accidental_node_repr = Character._display_name_template.format(
        "Ursula", accidental_nickname, accidental_checksum)

    assert len(warnings) == 2
    assert warnings[1]['log_format'] == learner.unknown_version_message.format(
        accidental_node_repr, future_version, learner.LEARNER_VERSION)

    # This time, however, there's not enough garbage to assume there's a checksum address...
    random_bytes = os.urandom(2)
    crazy_bytes = fleet_snapshot + VariableLengthBytestring(version_bytes +
                                                            random_bytes)
    signed_crazy_bytes = bytes(teacher.stamp(crazy_bytes))

    response = Response(content=signed_crazy_bytes + crazy_bytes,
                        status_code=200)

    learner._current_teacher_node = teacher
    learner.learn_from_teacher_node()

    assert len(warnings) == 3
    # ...so this time we get a "really unknown version message"
    assert warnings[2][
        'log_format'] == learner.really_unknown_version_message.format(
            future_version, learner.LEARNER_VERSION)

    globalLogPublisher.removeObserver(warning_trapper)