Merge pull request #250 from ralexstokes/add-secio-groundwork

Add secio groundwork
This commit is contained in:
Alex Stokes 2019-08-15 19:32:17 -07:00 committed by GitHub
commit dbdbcf7440
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 270 additions and 224 deletions

View File

@ -1,6 +1,7 @@
import asyncio
from typing import Mapping, Sequence
from libp2p.crypto.keys import KeyPair
from libp2p.crypto.rsa import create_new_key_pair
from libp2p.host.basic_host import BasicHost
from libp2p.kademlia.network import KademliaServer
@ -12,7 +13,7 @@ from libp2p.peer.peerstore import PeerStore
from libp2p.peer.peerstore_interface import IPeerStore
from libp2p.routing.interfaces import IPeerRouting
from libp2p.routing.kademlia.kademlia_peer_router import KadmeliaPeerRouter
from libp2p.security.insecure_security import InsecureTransport
from libp2p.security.insecure.transport import InsecureTransport
from libp2p.security.secure_transport_interface import ISecureTransport
from libp2p.transport.tcp.tcp import TCP
from libp2p.transport.upgrader import TransportUpgrader
@ -33,11 +34,15 @@ async def cleanup_done_tasks() -> None:
await asyncio.sleep(3)
def generate_peer_id_from_rsa_identity() -> ID:
new_key_pair = create_new_key_pair()
new_public_key = new_key_pair.public_key
new_id = ID.from_pubkey(new_public_key)
return new_id
def generate_new_rsa_identity() -> KeyPair:
return create_new_key_pair()
def generate_peer_id_from_rsa_identity(key_pair: KeyPair = None) -> ID:
if not key_pair:
key_pair = generate_new_rsa_identity()
public_key = key_pair.public_key
return ID.from_pubkey(public_key)
def initialize_default_kademlia_router(
@ -64,6 +69,7 @@ def initialize_default_kademlia_router(
def initialize_default_swarm(
key_pair: KeyPair,
id_opt: ID = None,
transport_opt: Sequence[str] = None,
muxer_opt: Sequence[str] = None,
@ -83,7 +89,7 @@ def initialize_default_swarm(
"""
if not id_opt:
id_opt = generate_peer_id_from_rsa_identity()
id_opt = generate_peer_id_from_rsa_identity(key_pair)
# TODO parse transport_opt to determine transport
transport_opt = transport_opt or ["/ip4/127.0.0.1/tcp/8001"]
@ -92,8 +98,10 @@ def initialize_default_swarm(
# TODO TransportUpgrader is not doing anything really
# TODO parse muxer and sec to pass into TransportUpgrader
muxer = muxer_opt or ["mplex/6.7.0"]
sec = sec_opt or {TProtocol("insecure/1.0.0"): InsecureTransport("insecure")}
upgrader = TransportUpgrader(sec, muxer)
security_transports_by_protocol = sec_opt or {
TProtocol("insecure/1.0.0"): InsecureTransport(key_pair)
}
upgrader = TransportUpgrader(security_transports_by_protocol, muxer)
peerstore = peerstore_opt or PeerStore()
# TODO: Initialize discovery if not presented
@ -103,6 +111,7 @@ def initialize_default_swarm(
async def new_node(
key_pair: KeyPair = None,
swarm_opt: INetwork = None,
id_opt: ID = None,
transport_opt: Sequence[str] = None,
@ -113,6 +122,7 @@ async def new_node(
) -> BasicHost:
"""
create new libp2p node
:param key_pair: key pair for deriving an identity
:param swarm_opt: optional swarm
:param id_opt: optional id for host
:param transport_opt: optional choice of transport upgrade
@ -123,11 +133,15 @@ async def new_node(
:return: return a host instance
"""
if not key_pair:
key_pair = generate_new_rsa_identity()
if not id_opt:
id_opt = generate_peer_id_from_rsa_identity()
id_opt = generate_peer_id_from_rsa_identity(key_pair)
if not swarm_opt:
swarm_opt = initialize_default_swarm(
key_pair=key_pair,
id_opt=id_opt,
transport_opt=transport_opt,
muxer_opt=muxer_opt,

View File

@ -46,11 +46,9 @@ class PublicKey(Key):
...
def serialize_to_protobuf(self) -> protobuf.PublicKey:
_type = self.get_type()
key_type = self.get_type().value
data = self.to_bytes()
protobuf_key = protobuf.PublicKey()
protobuf_key.key_type = _type.value
protobuf_key.data = data
protobuf_key = protobuf.PublicKey(key_type=key_type, data=data)
return protobuf_key
@ -68,11 +66,9 @@ class PrivateKey(Key):
...
def serialize_to_protobuf(self) -> protobuf.PrivateKey:
_type = self.get_type()
key_type = self.get_type().value
data = self.to_bytes()
protobuf_key = protobuf.PrivateKey()
protobuf_key.key_type = _type.value
protobuf_key.data = data
protobuf_key = protobuf.PrivateKey(key_type=key_type, data=data)
return protobuf_key

View File

@ -34,11 +34,7 @@ class RawConnection(IRawConnection):
async def read(self) -> bytes:
line = await self.reader.readline()
adjusted_line = line.decode().rstrip("\n")
# TODO: figure out a way to remove \n without going back and forth with
# encoding and decoding
return adjusted_line.encode()
return line.rstrip(b"\n")
def close(self) -> None:
self.writer.close()

View File

@ -15,7 +15,6 @@ def _serialize_public_key(key: PublicKey) -> bytes:
class ID:
_bytes: bytes
_xor_id: int = None
_b58_str: str = None

View File

@ -0,0 +1,52 @@
from typing import Optional
from libp2p.crypto.keys import PrivateKey, PublicKey
from libp2p.network.connection.raw_connection_interface import IRawConnection
from libp2p.peer.id import ID
from libp2p.security.base_transport import BaseSecureTransport
from libp2p.security.secure_conn_interface import ISecureConn
class BaseSession(ISecureConn, IRawConnection):
"""
``BaseSession`` is not fully instantiated from its abstract classes as it
is only meant to be used in clases that derive from it.
"""
def __init__(
self, transport: BaseSecureTransport, conn: IRawConnection, peer_id: ID
) -> None:
self.local_peer = transport.local_peer
self.local_private_key = transport.local_private_key
self.conn = conn
self.remote_peer_id = peer_id
self.remote_permanent_pubkey = None
self.initiator = self.conn.initiator
self.writer = self.conn.writer
self.reader = self.conn.reader
# TODO clean up how this is passed around?
def next_stream_id(self) -> int:
return self.conn.next_stream_id()
async def write(self, data: bytes) -> None:
await self.conn.write(data)
async def read(self) -> bytes:
return await self.conn.read()
def close(self) -> None:
self.conn.close()
def get_local_peer(self) -> ID:
return self.local_peer
def get_local_private_key(self) -> PrivateKey:
return self.local_private_key
def get_remote_peer(self) -> ID:
return self.remote_peer_id
def get_remote_public_key(self) -> Optional[PublicKey]:
return self.remote_permanent_pubkey

View File

@ -0,0 +1,14 @@
from libp2p.crypto.keys import KeyPair
from libp2p.peer.id import ID
from libp2p.security.secure_transport_interface import ISecureTransport
class BaseSecureTransport(ISecureTransport):
"""
``BaseSecureTransport`` is not fully instantiated from its abstract classes as it
is only meant to be used in clases that derive from it.
"""
def __init__(self, local_key_pair: KeyPair) -> None:
self.local_private_key = local_key_pair.private_key
self.local_peer = ID.from_pubkey(local_key_pair.public_key)

View File

@ -0,0 +1,32 @@
from libp2p.network.connection.raw_connection_interface import IRawConnection
from libp2p.peer.id import ID
from libp2p.security.base_session import BaseSession
from libp2p.security.base_transport import BaseSecureTransport
from libp2p.security.secure_conn_interface import ISecureConn
class InsecureSession(BaseSession):
pass
class InsecureTransport(BaseSecureTransport):
"""
``InsecureTransport`` provides the "identity" upgrader for a ``IRawConnection``,
i.e. the upgraded transport does not add any additional security.
"""
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
"""
Secure the connection, either locally or by communicating with opposing node via conn,
for an inbound connection (i.e. we are not the initiator)
:return: secure connection object (that implements secure_conn_interface)
"""
return InsecureSession(self, conn, ID(b""))
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
"""
Secure the connection, either locally or by communicating with opposing node via conn,
for an inbound connection (i.e. we are the initiator)
:return: secure connection object (that implements secure_conn_interface)
"""
return InsecureSession(self, conn, peer_id)

View File

@ -1,60 +0,0 @@
from typing import cast
from libp2p.network.connection.raw_connection_interface import IRawConnection
from libp2p.peer.id import ID
from libp2p.security.secure_conn_interface import ISecureConn
from libp2p.security.secure_transport_interface import ISecureTransport
from .typing import TSecurityDetails
class InsecureTransport(ISecureTransport):
"""
``InsecureTransport`` provides the "identity" upgrader for a ``IRawConnection``,
i.e. the upgraded transport does not add any additional security.
"""
transport_id: str
def __init__(self, transport_id: str) -> None:
self.transport_id = transport_id
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
"""
Secure the connection, either locally or by communicating with opposing node via conn,
for an inbound connection (i.e. we are not the initiator)
:return: secure connection object (that implements secure_conn_interface)
"""
insecure_conn = InsecureConn(conn, self.transport_id)
return insecure_conn
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
"""
Secure the connection, either locally or by communicating with opposing node via conn,
for an inbound connection (i.e. we are the initiator)
:return: secure connection object (that implements secure_conn_interface)
"""
insecure_conn = InsecureConn(conn, self.transport_id)
return insecure_conn
class InsecureConn(ISecureConn):
conn: IRawConnection
details: TSecurityDetails
def __init__(self, conn: IRawConnection, conn_id: str) -> None:
self.conn = conn
self.details = cast(TSecurityDetails, {})
self.details["id"] = conn_id
def get_conn(self) -> IRawConnection:
"""
:return: connection object that has been made secure
"""
return self.conn
def get_security_details(self) -> TSecurityDetails:
"""
:return: map containing details about the connections security
"""
return self.details

View File

View File

@ -1,8 +1,8 @@
from abc import ABC, abstractmethod
from libp2p.crypto.keys import PrivateKey, PublicKey
from libp2p.network.connection.raw_connection_interface import IRawConnection
from .typing import TSecurityDetails
from libp2p.peer.id import ID
"""
@ -13,15 +13,23 @@ Relevant go repo: https://github.com/libp2p/go-conn-security/blob/master/interfa
"""
class ISecureConn(ABC):
class AbstractSecureConn(ABC):
@abstractmethod
def get_conn(self) -> IRawConnection:
"""
:return: the underlying raw connection
"""
def get_local_peer(self) -> ID:
pass
@abstractmethod
def get_security_details(self) -> TSecurityDetails:
"""
:return: map containing details about the connections security
"""
def get_local_private_key(self) -> PrivateKey:
pass
@abstractmethod
def get_remote_peer(self) -> ID:
pass
@abstractmethod
def get_remote_public_key(self) -> PublicKey:
pass
class ISecureConn(AbstractSecureConn, IRawConnection):
pass

View File

@ -2,8 +2,7 @@ from abc import ABC, abstractmethod
from libp2p.network.connection.raw_connection_interface import IRawConnection
from libp2p.peer.id import ID
from .secure_conn_interface import ISecureConn
from libp2p.security.secure_conn_interface import ISecureConn
"""

View File

@ -1,15 +1,14 @@
from abc import ABC
from typing import Dict
from typing import Dict, Mapping
from libp2p.network.connection.raw_connection_interface import IRawConnection
from libp2p.peer.id import ID
from libp2p.protocol_muxer.multiselect import Multiselect
from libp2p.protocol_muxer.multiselect_client import MultiselectClient
from libp2p.security.secure_conn_interface import ISecureConn
from libp2p.security.secure_transport_interface import ISecureTransport
from libp2p.typing import TProtocol
from .secure_conn_interface import ISecureConn
from .secure_transport_interface import ISecureTransport
"""
Represents a secured connection object, which includes a connection and details about the security
@ -24,21 +23,19 @@ class SecurityMultistream(ABC):
multiselect: Multiselect
multiselect_client: MultiselectClient
def __init__(self) -> None:
# Map protocol to secure transport
def __init__(
self, secure_transports_by_protocol: Mapping[TProtocol, ISecureTransport]
) -> None:
self.transports = {}
# Create multiselect
self.multiselect = Multiselect()
# Create multiselect client
self.multiselect_client = MultiselectClient()
for protocol, transport in secure_transports_by_protocol.items():
self.add_transport(protocol, transport)
def add_transport(self, protocol: TProtocol, transport: ISecureTransport) -> None:
# Associate protocol with transport
self.transports[protocol] = transport
# Add protocol and handler to multiselect
# Note: None is added as the handler for the given protocol since
# we only care about selecting the protocol, not any handler function
self.multiselect.add_handler(protocol, None)
@ -49,13 +46,8 @@ class SecurityMultistream(ABC):
for an inbound connection (i.e. we are not the initiator)
:return: secure connection object (that implements secure_conn_interface)
"""
# Select a secure transport
transport = await self.select_transport(conn, False)
# Create secured connection
secure_conn = await transport.secure_inbound(conn)
return secure_conn
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
@ -64,13 +56,8 @@ class SecurityMultistream(ABC):
for an inbound connection (i.e. we are the initiator)
:return: secure connection object (that implements secure_conn_interface)
"""
# Select a secure transport
transport = await self.select_transport(conn, True)
# Create secured connection
secure_conn = await transport.secure_outbound(conn, peer_id)
return secure_conn
async def select_transport(

View File

@ -1,18 +1,18 @@
import asyncio
from typing import cast
from libp2p.crypto.keys import KeyPair
from libp2p.network.connection.raw_connection_interface import IRawConnection
from libp2p.peer.id import ID
from libp2p.security.base_transport import BaseSecureTransport
from libp2p.security.insecure.transport import InsecureSession
from libp2p.security.secure_conn_interface import ISecureConn
from libp2p.security.secure_transport_interface import ISecureTransport
from .typing import TSecurityDetails
class SimpleSecurityTransport(ISecureTransport):
class SimpleSecurityTransport(BaseSecureTransport):
key_phrase: str
def __init__(self, key_phrase: str) -> None:
def __init__(self, local_key_pair: KeyPair, key_phrase: str) -> None:
super().__init__(local_key_pair)
self.key_phrase = key_phrase
async def secure_inbound(self, conn: IRawConnection) -> ISecureConn:
@ -29,8 +29,12 @@ class SimpleSecurityTransport(ISecureTransport):
"Key phrase differed between nodes. Expected " + self.key_phrase
)
secure_conn = SimpleSecureConn(conn, self.key_phrase)
return secure_conn
session = InsecureSession(self, conn, ID(b""))
# NOTE: this is abusing the abstraction we have here
# but this code may be deprecated soon and this exists
# mainly to satisfy a test that will go along w/ it
session.key_phrase = self.key_phrase
return session
async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn:
"""
@ -50,28 +54,9 @@ class SimpleSecurityTransport(ISecureTransport):
"Key phrase differed between nodes. Expected " + self.key_phrase
)
secure_conn = SimpleSecureConn(conn, self.key_phrase)
return secure_conn
class SimpleSecureConn(ISecureConn):
conn: IRawConnection
key_phrase: str
details: TSecurityDetails
def __init__(self, conn: IRawConnection, key_phrase: str) -> None:
self.conn = conn
self.details = cast(TSecurityDetails, {})
self.details["key_phrase"] = key_phrase
def get_conn(self) -> IRawConnection:
"""
:return: connection object that has been made secure
"""
return self.conn
def get_security_details(self) -> TSecurityDetails:
"""
:return: map containing details about the connections security
"""
return self.details
session = InsecureSession(self, conn, peer_id)
# NOTE: this is abusing the abstraction we have here
# but this code may be deprecated soon and this exists
# mainly to satisfy a test that will go along w/ it
session.key_phrase = self.key_phrase
return session

View File

@ -39,11 +39,8 @@ class Mplex(IMuxedConn):
for new muxed streams
:param peer_id: peer_id of peer the connection is to
"""
super().__init__(secured_conn, generic_protocol_handler, peer_id)
self.secured_conn = secured_conn
self.raw_conn = secured_conn.get_conn()
self.initiator = self.raw_conn.initiator
self.conn = secured_conn
self.initiator = secured_conn.initiator
# Store generic protocol handler
self.generic_protocol_handler = generic_protocol_handler
@ -63,7 +60,7 @@ class Mplex(IMuxedConn):
"""
close the stream muxer and underlying raw connection
"""
self.raw_conn.close()
self.conn.close()
def is_closed(self) -> bool:
"""
@ -99,7 +96,7 @@ class Mplex(IMuxedConn):
:param multi_addr: multi_addr that stream connects to
:return: a new stream
"""
stream_id = self.raw_conn.next_stream_id()
stream_id = self.conn.next_stream_id()
stream = MplexStream(stream_id, multi_addr, self)
self.buffers[stream_id] = asyncio.Queue()
await self.send_message(HeaderTags.NewStream, None, stream_id)
@ -139,8 +136,8 @@ class Mplex(IMuxedConn):
:param _bytes: byte array to write
:return: length written
"""
self.raw_conn.writer.write(_bytes)
await self.raw_conn.writer.drain()
self.conn.writer.write(_bytes)
await self.conn.writer.drain()
return len(_bytes)
async def handle_incoming(self) -> None:
@ -177,10 +174,10 @@ class Mplex(IMuxedConn):
# loop in handle_incoming
timeout = 0.1
try:
header = await decode_uvarint_from_stream(self.raw_conn.reader, timeout)
length = await decode_uvarint_from_stream(self.raw_conn.reader, timeout)
header = await decode_uvarint_from_stream(self.conn.reader, timeout)
length = await decode_uvarint_from_stream(self.conn.reader, timeout)
message = await asyncio.wait_for(
self.raw_conn.reader.read(length), timeout=timeout
self.conn.reader.read(length), timeout=timeout
)
except asyncio.TimeoutError:
return None, None, None

View File

@ -18,14 +18,11 @@ class TransportUpgrader:
muxer: Sequence[str]
def __init__(
self, secOpt: Mapping[TProtocol, ISecureTransport], muxerOpt: Sequence[str]
) -> None:
# Store security option
self.security_multistream = SecurityMultistream()
for key in secOpt:
self.security_multistream.add_transport(key, secOpt[key])
# Store muxer option
self,
secure_transports_by_protocol: Mapping[TProtocol, ISecureTransport],
muxerOpt: Sequence[str],
):
self.security_multistream = SecurityMultistream(secure_transports_by_protocol)
self.muxer = muxerOpt
def upgrade_listener(self, transport: ITransport, listeners: IListener) -> None:
@ -54,7 +51,5 @@ class TransportUpgrader:
"""
Upgrade raw connection to muxed connection
"""
# For PoC, no security, default to mplex
# TODO do exchange to determine multiplexer
return Mplex(conn, generic_protocol_handler, peer_id)

View File

@ -13,6 +13,7 @@ import multiaddr
import pytest
from libp2p import initialize_default_swarm, new_node
from libp2p.crypto.rsa import create_new_key_pair
from libp2p.host.basic_host import BasicHost
from libp2p.network.notifee_interface import INotifee
from tests.utils import (
@ -172,14 +173,18 @@ async def test_one_notifier_on_two_nodes():
async def test_one_notifier_on_two_nodes_with_listen():
events_b = []
node_a_key_pair = create_new_key_pair()
node_a_transport_opt = ["/ip4/127.0.0.1/tcp/0"]
node_a = await new_node(transport_opt=node_a_transport_opt)
node_a = await new_node(node_a_key_pair, transport_opt=node_a_transport_opt)
await node_a.get_network().listen(multiaddr.Multiaddr(node_a_transport_opt[0]))
# Set up node_b swarm to pass into host
node_b_key_pair = create_new_key_pair()
node_b_transport_opt = ["/ip4/127.0.0.1/tcp/0"]
node_b_multiaddr = multiaddr.Multiaddr(node_b_transport_opt[0])
node_b_swarm = initialize_default_swarm(transport_opt=node_b_transport_opt)
node_b_swarm = initialize_default_swarm(
node_b_key_pair, transport_opt=node_b_transport_opt
)
node_b = BasicHost(node_b_swarm)
async def my_stream_handler(stream):

View File

@ -3,9 +3,13 @@ import asyncio
import pytest
from tests.configs import LISTEN_MADDR
from .configs import GOSSIPSUB_PARAMS
from .factories import FloodsubFactory, GossipsubFactory, HostFactory, PubsubFactory
from tests.pubsub.configs import GOSSIPSUB_PARAMS
from tests.pubsub.factories import (
FloodsubFactory,
GossipsubFactory,
HostFactory,
PubsubFactory,
)
@pytest.fixture

View File

@ -1,17 +1,22 @@
import factory
from libp2p import initialize_default_swarm
from libp2p.crypto.rsa import create_new_key_pair
from libp2p.host.basic_host import BasicHost
from libp2p.pubsub.floodsub import FloodSub
from libp2p.pubsub.gossipsub import GossipSub
from libp2p.pubsub.pubsub import Pubsub
from tests.configs import LISTEN_MADDR
from .configs import FLOODSUB_PROTOCOL_ID, GOSSIPSUB_PARAMS, GOSSIPSUB_PROTOCOL_ID
from tests.pubsub.configs import (
FLOODSUB_PROTOCOL_ID,
GOSSIPSUB_PARAMS,
GOSSIPSUB_PROTOCOL_ID,
)
def swarm_factory():
return initialize_default_swarm(transport_opt=[str(LISTEN_MADDR)])
private_key = create_new_key_pair()
return initialize_default_swarm(private_key, transport_opt=[str(LISTEN_MADDR)])
class HostFactory(factory.Factory):

View File

@ -189,6 +189,7 @@ async def test_set_then_send_from_diff_nodes_five_nodes_ring_topography():
@pytest.mark.asyncio
@pytest.mark.slow
async def test_set_then_send_from_five_diff_nodes_five_nodes_ring_topography():
num_nodes = 5
adj_map = {0: [1], 1: [2], 2: [3], 3: [4], 4: [0]}

View File

@ -87,5 +87,6 @@ async def test_lru_cache_two_nodes(pubsubs_fsub, monkeypatch):
@pytest.mark.parametrize("test_case_obj", floodsub_protocol_pytest_params)
@pytest.mark.asyncio
@pytest.mark.slow
async def test_gossipsub_run_with_floodsub_tests(test_case_obj):
await perform_test_from_obj(test_case_obj, FloodsubFactory)

View File

@ -268,6 +268,7 @@ async def test_fanout(hosts, pubsubs_gsub):
@pytest.mark.parametrize("num_hosts", (10,))
@pytest.mark.asyncio
@pytest.mark.slow
async def test_fanout_maintenance(hosts, pubsubs_gsub):
num_msgs = 5

View File

@ -17,6 +17,7 @@ async def test_gossipsub_initialize_with_floodsub_protocol():
@pytest.mark.parametrize("test_case_obj", floodsub_protocol_pytest_params)
@pytest.mark.asyncio
@pytest.mark.slow
async def test_gossipsub_run_with_floodsub_tests(test_case_obj):
await perform_test_from_obj(
test_case_obj,

View File

@ -4,10 +4,11 @@ import multiaddr
import pytest
from libp2p import new_node
from libp2p.crypto.rsa import create_new_key_pair
from libp2p.peer.peerinfo import info_from_p2p_addr
from libp2p.protocol_muxer.multiselect_client import MultiselectClientError
from libp2p.security.insecure_security import InsecureTransport
from libp2p.security.simple_security import SimpleSecurityTransport
from libp2p.security.insecure.transport import InsecureSession, InsecureTransport
from libp2p.security.simple.transport import SimpleSecurityTransport
from tests.utils import cleanup, connect
# TODO: Add tests for multiple streams being opened on different
@ -20,6 +21,11 @@ def peer_id_for_node(node):
return info.peer_id
initiator_key_pair = create_new_key_pair()
noninitiator_key_pair = create_new_key_pair()
async def perform_simple_test(
assertion_func, transports_for_initiator, transports_for_noninitiator
):
@ -50,8 +56,8 @@ async def perform_simple_test(
node2_conn = node2.get_network().connections[peer_id_for_node(node1)]
# Perform assertion
assertion_func(node1_conn.secured_conn.get_security_details())
assertion_func(node2_conn.secured_conn.get_security_details())
assertion_func(node1_conn.conn)
assertion_func(node2_conn.conn)
# Success, terminate pending tasks.
await cleanup()
@ -59,11 +65,11 @@ async def perform_simple_test(
@pytest.mark.asyncio
async def test_single_insecure_security_transport_succeeds():
transports_for_initiator = {"foo": InsecureTransport("foo")}
transports_for_noninitiator = {"foo": InsecureTransport("foo")}
transports_for_initiator = {"foo": InsecureTransport(initiator_key_pair)}
transports_for_noninitiator = {"foo": InsecureTransport(noninitiator_key_pair)}
def assertion_func(details):
assert details["id"] == "foo"
def assertion_func(conn):
assert isinstance(conn, InsecureSession)
await perform_simple_test(
assertion_func, transports_for_initiator, transports_for_noninitiator
@ -72,11 +78,15 @@ async def test_single_insecure_security_transport_succeeds():
@pytest.mark.asyncio
async def test_single_simple_test_security_transport_succeeds():
transports_for_initiator = {"tacos": SimpleSecurityTransport("tacos")}
transports_for_noninitiator = {"tacos": SimpleSecurityTransport("tacos")}
transports_for_initiator = {
"tacos": SimpleSecurityTransport(initiator_key_pair, "tacos")
}
transports_for_noninitiator = {
"tacos": SimpleSecurityTransport(noninitiator_key_pair, "tacos")
}
def assertion_func(details):
assert details["key_phrase"] == "tacos"
def assertion_func(conn):
assert conn.key_phrase == "tacos"
await perform_simple_test(
assertion_func, transports_for_initiator, transports_for_noninitiator
@ -86,13 +96,15 @@ async def test_single_simple_test_security_transport_succeeds():
@pytest.mark.asyncio
async def test_two_simple_test_security_transport_for_initiator_succeeds():
transports_for_initiator = {
"tacos": SimpleSecurityTransport("tacos"),
"shleep": SimpleSecurityTransport("shleep"),
"tacos": SimpleSecurityTransport(initiator_key_pair, "tacos"),
"shleep": SimpleSecurityTransport(initiator_key_pair, "shleep"),
}
transports_for_noninitiator = {
"shleep": SimpleSecurityTransport(noninitiator_key_pair, "shleep")
}
transports_for_noninitiator = {"shleep": SimpleSecurityTransport("shleep")}
def assertion_func(details):
assert details["key_phrase"] == "shleep"
def assertion_func(conn):
assert conn.key_phrase == "shleep"
await perform_simple_test(
assertion_func, transports_for_initiator, transports_for_noninitiator
@ -101,14 +113,16 @@ async def test_two_simple_test_security_transport_for_initiator_succeeds():
@pytest.mark.asyncio
async def test_two_simple_test_security_transport_for_noninitiator_succeeds():
transports_for_initiator = {"tacos": SimpleSecurityTransport("tacos")}
transports_for_initiator = {
"tacos": SimpleSecurityTransport(initiator_key_pair, "tacos")
}
transports_for_noninitiator = {
"shleep": SimpleSecurityTransport("shleep"),
"tacos": SimpleSecurityTransport("tacos"),
"shleep": SimpleSecurityTransport(noninitiator_key_pair, "shleep"),
"tacos": SimpleSecurityTransport(noninitiator_key_pair, "tacos"),
}
def assertion_func(details):
assert details["key_phrase"] == "tacos"
def assertion_func(conn):
assert conn.key_phrase == "tacos"
await perform_simple_test(
assertion_func, transports_for_initiator, transports_for_noninitiator
@ -118,16 +132,16 @@ async def test_two_simple_test_security_transport_for_noninitiator_succeeds():
@pytest.mark.asyncio
async def test_two_simple_test_security_transport_for_both_succeeds():
transports_for_initiator = {
"a": SimpleSecurityTransport("a"),
"b": SimpleSecurityTransport("b"),
"a": SimpleSecurityTransport(initiator_key_pair, "a"),
"b": SimpleSecurityTransport(initiator_key_pair, "b"),
}
transports_for_noninitiator = {
"c": SimpleSecurityTransport("c"),
"b": SimpleSecurityTransport("b"),
"b": SimpleSecurityTransport(noninitiator_key_pair, "b"),
"c": SimpleSecurityTransport(noninitiator_key_pair, "c"),
}
def assertion_func(details):
assert details["key_phrase"] == "b"
def assertion_func(conn):
assert conn.key_phrase == "b"
await perform_simple_test(
assertion_func, transports_for_initiator, transports_for_noninitiator
@ -137,12 +151,12 @@ async def test_two_simple_test_security_transport_for_both_succeeds():
@pytest.mark.asyncio
async def test_multiple_security_none_the_same_fails():
transports_for_initiator = {
"a": SimpleSecurityTransport("a"),
"b": SimpleSecurityTransport("b"),
"a": SimpleSecurityTransport(initiator_key_pair, "a"),
"b": SimpleSecurityTransport(initiator_key_pair, "b"),
}
transports_for_noninitiator = {
"c": SimpleSecurityTransport("c"),
"d": SimpleSecurityTransport("d"),
"d": SimpleSecurityTransport(noninitiator_key_pair, "d"),
"c": SimpleSecurityTransport(noninitiator_key_pair, "c"),
}
def assertion_func(_):
@ -161,18 +175,18 @@ async def test_default_insecure_security():
transports_for_initiator = None
transports_for_noninitiator = None
details1 = None
details2 = None
conn1 = None
conn2 = None
def assertion_func(details):
nonlocal details1
nonlocal details2
if not details1:
details1 = details
elif not details2:
details2 = details
def assertion_func(conn):
nonlocal conn1
nonlocal conn2
if not conn1:
conn1 = conn
elif not conn2:
conn2 = conn
else:
assert details1 == details2
assert conn1 == conn2
await perform_simple_test(
assertion_func, transports_for_initiator, transports_for_noninitiator