Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable manually triggering keylist updates during connection #1851

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
88dda1e
feat: add update keylist for connection method and route
dbluhm May 25, 2022
8a34920
refactor: move mediation record retrieval util
dbluhm Jun 8, 2022
36e3837
feat: add route managers
dbluhm Jun 9, 2022
3d56a0e
feat: integrate route manager in base classes
dbluhm Jun 9, 2022
efa8b1f
refactor: connection manager uses routing manager
dbluhm Jun 9, 2022
2d3dfbc
refactor: route_connection, utils on route manager
dbluhm Jun 9, 2022
2ca17d1
fix: retrieve previously used mediator when possible
dbluhm Jun 9, 2022
b116c4a
fix: broken imports
dbluhm Jun 9, 2022
f2bd49e
fix: status code on response
dbluhm Jun 9, 2022
b6b6784
fix: mediation id from metadata
dbluhm Jun 9, 2022
82893f6
feat: register update-keylist route
dbluhm Jun 9, 2022
fcb70c6
fix: state mismatches, overwriting updates
dbluhm Jun 9, 2022
998cb49
feat: out of band manager use route manager
dbluhm Jun 9, 2022
4a3313e
feat: didexchange manager use route manager
dbluhm Jun 9, 2022
5554062
Merge branch 'main' into feature/manual-keylist-update
dbluhm Jun 22, 2022
aad9505
test: out of band manager with route manager
dbluhm Jul 1, 2022
16d987a
style: flake8 fixes for route manager
dbluhm Jul 1, 2022
f19e160
refactor: remove add_key from base multitenant mgr
dbluhm Jul 1, 2022
a99a952
test: conn rec handler mediation id
dbluhm Jul 1, 2022
835e9ea
test: connection manager with route manager
dbluhm Jul 1, 2022
5d4a3ed
test: didex request handler with route mgr
dbluhm Jul 1, 2022
23a2981
test: didexchange manager with route manager
dbluhm Jul 1, 2022
58faf20
style: flake8 fixes for route manager
dbluhm Jul 1, 2022
0e3e030
test: route manager and mediation route manager
dbluhm Jul 1, 2022
805c43d
test: multitenant route manager
dbluhm Jul 1, 2022
eb22619
fix: remove unused imports
dbluhm Jul 1, 2022
6ca49ee
Merge branch 'main' into feature/manual-keylist-update
dbluhm Jul 1, 2022
d582a16
fix: public did routing in wallet routes
dbluhm Jul 1, 2022
2dcaf68
fix: allow mediation record to be none
dbluhm Jul 6, 2022
960b1b8
fix: pytest attempting to collect mock class
dbluhm Jul 6, 2022
0a352a7
test: update keylist for connection endpoint
dbluhm Jul 6, 2022
d576262
test: error conditions on update keylist endpoint
dbluhm Jul 6, 2022
add2f24
fix: relative imports
dbluhm Jul 6, 2022
af41244
fix: more relative imports
dbluhm Jul 6, 2022
f8120a6
fix: more relative imports
dbluhm Jul 6, 2022
ad17f68
feat: inject weak ref to profile
dbluhm Jul 6, 2022
b3dabdc
feat: inject route manager
dbluhm Jul 6, 2022
44ef00c
fix: tests use injected route manager
dbluhm Jul 6, 2022
822fdfb
refactor: don't inject profile into context
dbluhm Jul 6, 2022
096a8f6
Merge branch 'main' into feature/manual-keylist-update
dbluhm Jul 19, 2022
4409ec9
Merge branch 'main' into feature/manual-keylist-update
dbluhm Jul 20, 2022
da8f509
Merge branch 'main' into feature/manual-keylist-update
dbluhm Jul 20, 2022
9b870be
Merge branch 'main' into feature/manual-keylist-update
dbluhm Jul 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions aries_cloudagent/config/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@
from ..core.profile import Profile, ProfileManager, ProfileSession
from ..storage.base import BaseStorage
from ..storage.error import StorageNotFoundError
from ..version import __version__, RECORD_TYPE_ACAPY_VERSION
from ..version import RECORD_TYPE_ACAPY_VERSION, __version__
from ..wallet.base import BaseWallet
from ..wallet.did_info import DIDInfo
from ..wallet.crypto import seed_to_did
from ..wallet.key_type import KeyType
from ..wallet.did_info import DIDInfo
from ..wallet.did_method import DIDMethod

from ..wallet.key_type import KeyType
from .base import ConfigError
from .injection_context import InjectionContext

Expand Down
4 changes: 4 additions & 0 deletions aries_cloudagent/connections/base_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
from ..protocols.coordinate_mediation.v1_0.models.mediation_record import (
MediationRecord,
)
from ..protocols.coordinate_mediation.v1_0.route_manager import (
RouteManager,
)
from ..resolver.base import ResolverError
from ..resolver.did_resolver import DIDResolver
from ..storage.base import BaseStorage
Expand Down Expand Up @@ -56,6 +59,7 @@ def __init__(self, profile: Profile):
"""
self._logger = logging.getLogger(__name__)
self._profile = profile
self._route_manager = profile.inject(RouteManager)

async def create_did_document(
self,
Expand Down
36 changes: 0 additions & 36 deletions aries_cloudagent/connections/util.py

This file was deleted.

23 changes: 16 additions & 7 deletions aries_cloudagent/core/conductor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,20 @@
import hashlib
import json
import logging

from qrcode import QRCode

from ..admin.base_server import BaseAdminServer
from ..admin.server import AdminResponder, AdminServer
from ..config.default_context import ContextBuilder
from ..config.injection_context import InjectionContext
from ..config.provider import ClassProvider
from ..config.ledger import (
get_genesis_transactions,
ledger_config,
load_multiple_genesis_transactions_from_config,
)
from ..config.logging import LoggingConfigurator
from ..config.provider import ClassProvider
from ..config.wallet import wallet_config
from ..core.profile import Profile
from ..indy.verifier import IndyVerifier
Expand All @@ -33,8 +34,8 @@
BaseMultipleLedgerManager,
MultipleLedgerManagerError,
)
from ..ledger.multiple_ledger.manager_provider import MultiIndyLedgerManagerProvider
from ..ledger.multiple_ledger.ledger_requests_executor import IndyLedgerRequestsExecutor
from ..ledger.multiple_ledger.manager_provider import MultiIndyLedgerManagerProvider
from ..messaging.responder import BaseResponder
from ..multitenant.base import BaseMultitenantManager
from ..multitenant.manager_provider import MultitenantManagerProvider
Expand All @@ -45,8 +46,12 @@
from ..protocols.connections.v1_0.messages.connection_invitation import (
ConnectionInvitation,
)
from ..protocols.coordinate_mediation.v1_0.manager import MediationManager
from ..protocols.coordinate_mediation.mediation_invite_store import MediationInviteStore
from ..protocols.coordinate_mediation.v1_0.manager import MediationManager
from ..protocols.coordinate_mediation.v1_0.route_manager import RouteManager
from ..protocols.coordinate_mediation.v1_0.route_manager_provider import (
RouteManagerProvider,
)
from ..protocols.out_of_band.v1_0.manager import OutOfBandManager
from ..protocols.out_of_band.v1_0.messages.invitation import HSProto, InvitationMessage
from ..storage.base import BaseStorage
Expand All @@ -61,12 +66,11 @@
from ..utils.stats import Collector
from ..utils.task_queue import CompletedTask, TaskQueue
from ..vc.ld_proofs.document_loader import DocumentLoader
from ..version import __version__, RECORD_TYPE_ACAPY_VERSION
from ..version import RECORD_TYPE_ACAPY_VERSION, __version__
from ..wallet.did_info import DIDInfo
from .oob_processor import OobMessageProcessor

from .dispatcher import Dispatcher
from .util import STARTUP_EVENT_TOPIC, SHUTDOWN_EVENT_TOPIC
from .oob_processor import OobMessageProcessor
from .util import SHUTDOWN_EVENT_TOPIC, STARTUP_EVENT_TOPIC

LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -204,6 +208,11 @@ async def setup(self):
BaseMultitenantManager, MultitenantManagerProvider(self.root_profile)
)

# Bind route manager provider
context.injector.bind_provider(
RouteManager, RouteManagerProvider(self.root_profile)
)

# Bind oob message processor to be able to receive and process un-encrypted
# messages
context.injector.bind_instance(
Expand Down
2 changes: 2 additions & 0 deletions aries_cloudagent/core/tests/test_dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
V20CredProblemReport,
)
from ...protocols.problem_report.v1_0.message import ProblemReport
from ...protocols.coordinate_mediation.v1_0.route_manager import RouteManager
from ...transport.inbound.message import InboundMessage
from ...transport.inbound.receipt import MessageReceipt
from ...transport.outbound.message import OutboundMessage
Expand All @@ -31,6 +32,7 @@ def make_profile() -> Profile:
profile.context.injector.bind_instance(ProtocolRegistry, ProtocolRegistry())
profile.context.injector.bind_instance(Collector, Collector())
profile.context.injector.bind_instance(EventBus, EventBus())
profile.context.injector.bind_instance(RouteManager, async_mock.MagicMock())
return profile


Expand Down
72 changes: 12 additions & 60 deletions aries_cloudagent/multitenant/base.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
"""Manager for multitenancy."""

from abc import ABC, abstractmethod
from datetime import datetime
import logging
from abc import abstractmethod, ABC
from typing import Iterable, List, Optional, cast

import jwt
from typing import Iterable, List, Optional, cast

from ..core.profile import (
Profile,
ProfileSession,
)
from ..messaging.responder import BaseResponder
from ..config.injection_context import InjectionContext
from ..wallet.models.wallet_record import WalletRecord
from ..wallet.base import BaseWallet
from ..core.error import BaseError
from ..protocols.routing.v1_0.manager import RouteNotFoundError, RoutingManager
from ..protocols.routing.v1_0.models.route_record import RouteRecord
from ..transport.wire_format import BaseWireFormat
from ..storage.base import BaseStorage
from ..storage.error import StorageNotFoundError
from ..core.profile import Profile, ProfileSession
from ..protocols.coordinate_mediation.v1_0.manager import (
MediationManager,
MediationRecord,
)

from ..protocols.coordinate_mediation.v1_0.route_manager import RouteManager
from ..protocols.routing.v1_0.manager import RouteNotFoundError, RoutingManager
from ..protocols.routing.v1_0.models.route_record import RouteRecord
from ..storage.base import BaseStorage
from ..transport.wire_format import BaseWireFormat
from ..wallet.base import BaseWallet
from ..wallet.models.wallet_record import WalletRecord
from .error import WalletKeyMissingError

LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -204,8 +199,8 @@ async def create_wallet(
public_did_info = await wallet.get_public_did()

if public_did_info:
await self.add_key(
wallet_record.wallet_id, public_did_info.verkey, skip_if_exists=True
await profile.inject(RouteManager).route_public_did(
profile, public_did_info.verkey
)
except Exception:
await wallet_record.delete_record(session)
Expand Down Expand Up @@ -285,49 +280,6 @@ async def remove_wallet_profile(self, profile: Profile):

"""

async def add_key(
self, wallet_id: str, recipient_key: str, *, skip_if_exists: bool = False
):
"""
Add a wallet key to map incoming messages to specific subwallets.

Args:
wallet_id: The wallet id the key corresponds to
recipient_key: The recipient key belonging to the wallet
skip_if_exists: Whether to skip the action if the key is already registered
for relaying / mediation
"""

LOGGER.info(
f"Add route record for recipient {recipient_key} to wallet {wallet_id}"
)
routing_mgr = RoutingManager(self._profile)
mediation_mgr = MediationManager(self._profile)
mediation_record = await mediation_mgr.get_default_mediator()

if skip_if_exists:
try:
async with self._profile.session() as session:
await RouteRecord.retrieve_by_recipient_key(session, recipient_key)

# If no error is thrown, it means there is already a record
return
except (StorageNotFoundError):
pass

await routing_mgr.create_route_record(
recipient_key=recipient_key, internal_wallet_id=wallet_id
)

# External mediation
if mediation_record:
keylist_updates = await mediation_mgr.add_key(recipient_key)

responder = self._profile.inject(BaseResponder)
await responder.send(
keylist_updates, connection_id=mediation_record.connection_id
)

async def create_auth_token(
self, wallet_record: WalletRecord, wallet_key: str = None
) -> str:
Expand Down
105 changes: 105 additions & 0 deletions aries_cloudagent/multitenant/route_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"""Multitenancy route manager."""


import logging
from typing import List, Optional, Tuple

from ..core.profile import Profile
from ..messaging.responder import BaseResponder
from ..protocols.coordinate_mediation.v1_0.manager import MediationManager
from ..protocols.coordinate_mediation.v1_0.models.mediation_record import (
MediationRecord,
)
from ..protocols.coordinate_mediation.v1_0.route_manager import RouteManager
from ..protocols.routing.v1_0.manager import RoutingManager
from ..protocols.routing.v1_0.models.route_record import RouteRecord
from ..storage.error import StorageNotFoundError


LOGGER = logging.getLogger(__name__)


class MultitenantRouteManager(RouteManager):
"""Multitenancy route manager."""

def __init__(
self,
root_profile: Profile,
):
"""Initialize multitenant route manager."""
self.root_profile = root_profile

async def get_base_wallet_mediator(self) -> Optional[MediationRecord]:
"""Get base wallet's default mediator."""
return await MediationManager(self.root_profile).get_default_mediator()

async def _route_for_key(
self,
profile: Profile,
recipient_key: str,
mediation_record: Optional[MediationRecord] = None,
*,
skip_if_exists: bool = False,
replace_key: Optional[str] = None,
):
wallet_id = profile.settings["wallet.id"]
LOGGER.info(
f"Add route record for recipient {recipient_key} to wallet {wallet_id}"
)
routing_mgr = RoutingManager(self.root_profile)
mediation_mgr = MediationManager(self.root_profile)
# If base wallet had mediator, only notify that mediator.
# Else, if subwallet has mediator, notify that mediator.
base_mediation_record = await self.get_base_wallet_mediator()
mediation_record = base_mediation_record or mediation_record

if skip_if_exists:
try:
async with self.root_profile.session() as session:
await RouteRecord.retrieve_by_recipient_key(session, recipient_key)

# If no error is thrown, it means there is already a record
return None
except (StorageNotFoundError):
pass

await routing_mgr.create_route_record(
recipient_key=recipient_key, internal_wallet_id=wallet_id
)

# External mediation
keylist_updates = None
if mediation_record:
dbluhm marked this conversation as resolved.
Show resolved Hide resolved
keylist_updates = await mediation_mgr.add_key(recipient_key)
if replace_key:
keylist_updates = await mediation_mgr.remove_key(
replace_key, keylist_updates
)

responder = self.root_profile.inject(BaseResponder)
await responder.send(
keylist_updates, connection_id=mediation_record.connection_id
)

return keylist_updates

async def routing_info(
self,
profile: Profile,
my_endpoint: str,
mediation_record: Optional[MediationRecord] = None,
) -> Tuple[List[str], str]:
"""Return routing info."""
routing_keys = []

base_mediation_record = await self.get_base_wallet_mediator()

if base_mediation_record:
routing_keys = base_mediation_record.routing_keys
my_endpoint = base_mediation_record.endpoint

if mediation_record:
routing_keys = [*routing_keys, *mediation_record.routing_keys]
my_endpoint = mediation_record.endpoint

return routing_keys, my_endpoint
Loading