Exemple #1
0
def test_alice_can_grant_even_when_the_first_nodes_she_tries_are_down(
        federated_alice, federated_bob, federated_ursulas):
    m, n = 2, 3
    policy_end_datetime = maya.now() + datetime.timedelta(days=5)
    label = b"this_is_the_path_to_which_access_is_being_granted"
    federated_alice.known_nodes.current_state._nodes = {}

    federated_alice.network_middleware = NodeIsDownMiddleware()

    # OK, her first and only node is down.
    down_node = list(federated_ursulas)[0]
    federated_alice.remember_node(down_node)
    federated_alice.network_middleware.node_is_down(down_node)

    # Here's the command we want to run.
    alice_grant_action = partial(federated_alice.grant,
                                 federated_bob,
                                 label,
                                 m=m,
                                 n=n,
                                 expiration=policy_end_datetime,
                                 timeout=.1)

    # Go!
    federated_alice.start_learning_loop()

    # Now we'll have a situation where Alice knows about all 10,
    # though only one is up.

    # She'll try to learn about more, but there aren't any.
    # Because she has successfully completed learning, but the nodes about which she learned are down,
    # she'll get a different error.

    more_nodes = list(federated_ursulas)[1:10]
    for node in more_nodes:
        federated_alice.network_middleware.node_is_down(node)

    for node in more_nodes:
        federated_alice.remember_node(node)
    with pytest.raises(Policy.NotEnoughUrsulas):
        alice_grant_action()

    # Now let's let a few of them come up.
    for node in more_nodes[0:4]:
        federated_alice.network_middleware.node_is_up(node)

    # Now the same exact action works.
    # TODO: This action only succeeds here because we are forcing
    #       grant to accept the ursulas that just came back online (handpicked_ursulas).
    #       Since there are now enough Ursulas online, this action *can* succeed without forcing sample.
    policy = alice_grant_action(handpicked_ursulas=more_nodes[:3])

    # TODO: This is how it's actually done. How can we measure such random results?
    #       The below line will fail with ? probability, if more then 2 of the nodes selected
    #       are among those still down.
    # policy = alice_grant_action()

    # The number of actually enacted arrangements is exactly equal to n.
    assert len(policy.treasure_map.destinations) == n
Exemple #2
0
def test_node_has_changed_cert(federated_alice, federated_ursulas):
    federated_alice.known_nodes.current_state._nodes = {}
    federated_alice.network_middleware = NodeIsDownMiddleware()
    federated_alice.network_middleware.client.certs_are_broken = True

    firstula = list(federated_ursulas)[0]
    federated_alice.remember_node(firstula)
    federated_alice.start_learning_loop(now=True)
    federated_alice.learn_from_teacher_node()
Exemple #3
0
def test_federated_bob_cannot_resume_retrieval_without_caching(federated_bob,
                                                               federated_alice,
                                                               capsule_side_channel,
                                                               enacted_federated_policy,
                                                               federated_ursulas
                                                               ):
    capsule_side_channel.reset()
    the_message_kit = capsule_side_channel()

    alices_verifying_key = federated_alice.stamp.as_umbral_pubkey()

    # Out of 10 Ursulas, eight are down.
    ursula1 = list(federated_ursulas)[0]
    ursula2 = list(federated_ursulas)[1]
    ursula3 = list(federated_ursulas)[2]
    ursula4 = list(federated_ursulas)[3]
    ursula5 = list(federated_ursulas)[4]
    ursula6 = list(federated_ursulas)[5]
    ursula7 = list(federated_ursulas)[6]
    ursula8 = list(federated_ursulas)[7]

    federated_bob.remember_node(ursula1)

    federated_bob.network_middleware = NodeIsDownMiddleware()
    federated_bob.network_middleware.node_is_down(ursula1)
    federated_bob.network_middleware.node_is_down(ursula2)
    federated_bob.network_middleware.node_is_down(ursula3)
    federated_bob.network_middleware.node_is_down(ursula4)
    federated_bob.network_middleware.node_is_down(ursula5)
    federated_bob.network_middleware.node_is_down(ursula6)
    federated_bob.network_middleware.node_is_down(ursula7)
    federated_bob.network_middleware.node_is_down(ursula8)

    # Since 8 Ursulas are down, Bob can only get 2 CFrags; not enough to complete retrieval.
    with pytest.raises(ursula1.NotEnoughUrsulas):
        federated_bob.retrieve(the_message_kit,
                               enrico=capsule_side_channel.enrico,
                               alice_verifying_key=alices_verifying_key,
                               label=enacted_federated_policy.label)

    # Since we weren't caching, there are no attached Cfrags.
    assert len(the_message_kit.capsule) == 0

    # Now the remaining two Ursulas go down.
    ursula9 = list(federated_ursulas)[8]
    ursula10 = list(federated_ursulas)[9]
    federated_bob.network_middleware.node_is_down(ursula9)
    federated_bob.network_middleware.node_is_down(ursula10)

    # ...but one other comes up.
    federated_bob.network_middleware.node_is_up(ursula4)

    with pytest.raises(ursula1.NotEnoughUrsulas):
        federated_bob.retrieve(the_message_kit,
                               enrico=capsule_side_channel.enrico,
                               alice_verifying_key=alices_verifying_key,
                               label=enacted_federated_policy.label)
Exemple #4
0
def test_use_external_cache(enacted_federated_policy, federated_bob,
                            federated_ursulas):

    federated_bob.start_learning_loop()
    messages, message_kits = _make_message_kits(
        enacted_federated_policy.public_key)

    ursulas = list(federated_ursulas)

    # All Ursulas are down except for two
    federated_bob.network_middleware = NodeIsDownMiddleware()
    for ursula in ursulas[2:]:
        federated_bob.network_middleware.node_is_down(ursula)

    # Fetch what we can without decrypting
    loaded_message_kits = federated_bob.retrieve(
        message_kits=message_kits,
        **_policy_info_kwargs(enacted_federated_policy),
    )

    # Not enough cfrags yet
    assert not any(mk.is_decryptable_by_receiver()
                   for mk in loaded_message_kits)

    # Now the remaining two Ursulas go down.
    for ursula in ursulas[:2]:
        federated_bob.network_middleware.node_is_down(ursula)

    # ...but one other comes up.
    federated_bob.network_middleware.node_is_up(ursulas[2])

    # Try again, building on top of the existing cache
    loaded_message_kits = federated_bob.retrieve(
        message_kits=loaded_message_kits,
        **_policy_info_kwargs(enacted_federated_policy),
    )

    assert all(mk.is_decryptable_by_receiver() for mk in loaded_message_kits)

    # Should be enough cfrags now. Disconnect all Ursulas
    # to be sure Bob doesn't cheat and contact them again.
    for ursula in ursulas:
        federated_bob.network_middleware.node_is_down(ursula)

    cleartexts = federated_bob.retrieve_and_decrypt(
        message_kits=loaded_message_kits,
        **_policy_info_kwargs(enacted_federated_policy),
    )

    assert cleartexts == messages
def test_blockchain_ursulas_reencrypt(blockchain_ursulas, blockchain_alice,
                                      blockchain_bob, policy_value):
    label = b'bbo'

    # TODO: Make sample selection buffer configurable - #1061
    m = n = 10
    expiration = maya.now() + datetime.timedelta(days=5)

    _policy = blockchain_alice.grant(bob=blockchain_bob,
                                     label=label,
                                     m=m,
                                     n=n,
                                     expiration=expiration,
                                     value=policy_value)

    enrico = Enrico.from_alice(blockchain_alice, label)

    message = b"Oh, this isn't even BO. This is beyond BO. It's BBO."

    message_kit, signature = enrico.encrypt_message(message)

    blockchain_bob.start_learning_loop(now=True)
    blockchain_bob.join_policy(label, bytes(blockchain_alice.stamp))

    plaintext = blockchain_bob.retrieve(
        message_kit,
        alice_verifying_key=blockchain_alice.stamp,
        label=label,
        enrico=enrico)
    assert plaintext[0] == message

    # Let's consider also that a node may be down when granting
    blockchain_alice.network_middleware = NodeIsDownMiddleware()
    blockchain_alice.network_middleware.node_is_down(blockchain_ursulas[0])

    with pytest.raises(BlockchainPolicy.NotEnoughBlockchainUrsulas):
        _policy = blockchain_alice.grant(bob=blockchain_bob,
                                         label=b'another-label',
                                         m=m,
                                         n=n,
                                         expiration=expiration,
                                         value=policy_value)
Exemple #6
0
def test_blockchain_ursulas_reencrypt(blockchain_ursulas, blockchain_alice,
                                      blockchain_bob, policy_value):
    label = b'bbo'

    # TODO: Make sample selection buffer configurable - #1061
    threshold = shares = 10
    expiration = maya.now() + datetime.timedelta(days=35)

    _policy = blockchain_alice.grant(bob=blockchain_bob,
                                     label=label,
                                     threshold=threshold,
                                     shares=shares,
                                     expiration=expiration,
                                     value=policy_value)

    enrico = Enrico.from_alice(blockchain_alice, label)

    message = b"Oh, this isn't even BO. This is beyond BO. It's BBO."

    message_kit = enrico.encrypt_message(message)

    blockchain_bob.start_learning_loop(now=True)

    plaintexts = blockchain_bob.retrieve_and_decrypt(
        [message_kit],
        encrypted_treasure_map=_policy.treasure_map,
        alice_verifying_key=blockchain_alice.stamp.as_umbral_pubkey())
    assert plaintexts == [message]

    # Let's consider also that a node may be down when granting
    blockchain_alice.network_middleware = NodeIsDownMiddleware()
    blockchain_alice.network_middleware.node_is_down(blockchain_ursulas[0])

    with pytest.raises(BlockchainPolicy.NotEnoughUrsulas):
        _policy = blockchain_alice.grant(bob=blockchain_bob,
                                         label=b'another-label',
                                         threshold=threshold,
                                         shares=shares,
                                         expiration=expiration,
                                         value=policy_value)
Exemple #7
0
def test_bob_does_not_let_a_connection_error_stop_him(enacted_federated_policy,
                                                      federated_ursulas,
                                                      federated_bob,
                                                      federated_alice):
    assert len(federated_bob.known_nodes) == 0
    ursula1 = list(federated_ursulas)[0]
    ursula2 = list(federated_ursulas)[1]

    federated_bob.remember_node(ursula1)

    federated_bob.network_middleware = NodeIsDownMiddleware()
    federated_bob.network_middleware.node_is_down(ursula1)

    with pytest.raises(TreasureMap.NowhereToBeFound):
        federated_bob.get_treasure_map(federated_alice.stamp,
                                       enacted_federated_policy.label)

    federated_bob.remember_node(ursula2)

    map = federated_bob.get_treasure_map(federated_alice.stamp,
                                         enacted_federated_policy.label)

    assert sorted(list(map.destinations.keys())) == sorted(
        list(u.checksum_address for u in list(federated_ursulas)))
Exemple #8
0
def test_federated_retrieves_partially_then_finishes(federated_bob,
                                                     federated_alice,
                                                     capsule_side_channel,
                                                     enacted_federated_policy,
                                                     federated_ursulas):
    # Same setup as last time.
    capsule_side_channel.reset()
    the_message_kit = capsule_side_channel()

    alices_verifying_key = federated_alice.stamp.as_umbral_pubkey()
    ursula1 = list(federated_ursulas)[0]
    ursula2 = list(federated_ursulas)[1]
    ursula3 = list(federated_ursulas)[2]
    ursula4 = list(federated_ursulas)[3]
    ursula5 = list(federated_ursulas)[4]
    ursula6 = list(federated_ursulas)[5]
    ursula7 = list(federated_ursulas)[6]
    ursula8 = list(federated_ursulas)[7]

    federated_bob.remember_node(ursula1)

    federated_bob.network_middleware = NodeIsDownMiddleware()
    federated_bob.network_middleware.node_is_down(ursula1)
    federated_bob.network_middleware.node_is_down(ursula2)
    federated_bob.network_middleware.node_is_down(ursula3)
    federated_bob.network_middleware.node_is_down(ursula4)
    federated_bob.network_middleware.node_is_down(ursula5)
    federated_bob.network_middleware.node_is_down(ursula6)
    federated_bob.network_middleware.node_is_down(ursula7)
    federated_bob.network_middleware.node_is_down(ursula8)

    # Bob can't retrieve; there aren't enough Ursulas up.
    with pytest.raises(ursula1.NotEnoughUrsulas):
        federated_bob.retrieve(the_message_kit,
                               enrico=capsule_side_channel.enrico,
                               alice_verifying_key=alices_verifying_key,
                               label=enacted_federated_policy.label,
                               retain_cfrags=True)

    # Since we were caching, there are now 2 attached cfrags.
    assert len(the_message_kit.capsule) == 2

    # Now the remaining two Ursulas go down.
    ursula9 = list(federated_ursulas)[8]
    ursula10 = list(federated_ursulas)[9]
    federated_bob.network_middleware.node_is_down(ursula9)
    federated_bob.network_middleware.node_is_down(ursula10)

    # ...but one other comes up.
    federated_bob.network_middleware.node_is_up(ursula4)

    # We're not allowed to try again with a Capsule with cached CFrags if we set cache to False.
    with pytest.raises(TypeError):
        federated_bob.retrieve(the_message_kit,
                               enrico=capsule_side_channel.enrico,
                               alice_verifying_key=alices_verifying_key,
                               label=enacted_federated_policy.label,
                               retain_cfrags=False)

    # But now, with just one Ursula up, we can use the cached CFrags to get the message.
    delivered_cleartexts = federated_bob.retrieve(
        the_message_kit,
        enrico=capsule_side_channel.enrico,
        alice_verifying_key=alices_verifying_key,
        label=enacted_federated_policy.label,
        retain_cfrags=True,
        use_attached_cfrags=True,
    )

    assert b"Welcome to flippering number 1." == delivered_cleartexts[0]

    # In fact, if Bob is totally offline, he can get the message:
    for ursula in federated_ursulas:
        federated_bob.network_middleware.node_is_down(ursula)

    delivered_cleartexts = federated_bob.retrieve(
        the_message_kit,
        enrico=capsule_side_channel.enrico,
        alice_verifying_key=alices_verifying_key,
        label=enacted_federated_policy.label,
        retain_cfrags=True,
        use_attached_cfrags=True)

    assert b"Welcome to flippering number 1." == delivered_cleartexts[0]

    # Heck, even if we delete the attached CFrags, as might happen if we were loading the Capsule again from disk...
    the_message_kit.capsule.clear_cfrags()

    # ...we can still get the message with the network being down because Bob has the properly completed WorkOrders cached in state.
    delivered_cleartexts = federated_bob.retrieve(
        the_message_kit,
        enrico=capsule_side_channel.enrico,
        alice_verifying_key=alices_verifying_key,
        label=enacted_federated_policy.label,
        use_precedent_work_orders=True)

    assert b"Welcome to flippering number 1." == delivered_cleartexts[0]
    federated_bob.network_middleware.all_nodes_up()