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

feat: remove keys on mediator when deleting connections #1143

Merged
merged 13 commits into from
Dec 12, 2022

Conversation

genaris
Copy link
Contributor

@genaris genaris commented Dec 7, 2022

This PR addresses the case where a mobile agent (or any agent that uses mediator) deletes a connection or OOB record, meaning that the corresponding recipient keys should be removed from its mediator (as per Aries RFC 0211). Otherwise, mediator will still be forwarding messages to the agent that can't (and more importantly don't want to) be handled.

This will mean that, when using mediator, in order to delete a connection or out-of-band record, the agent must be online. This is aligned to the opposite case: connection and OOB invitation creation, which also need the agent to be online to be in sync with its mediator.

@genaris genaris requested a review from a team as a code owner December 7, 2022 03:11
@codecov-commenter
Copy link

codecov-commenter commented Dec 7, 2022

Codecov Report

Merging #1143 (4d22ce3) into main (979c695) will increase coverage by 0.14%.
The diff coverage is 64.10%.

@@            Coverage Diff             @@
##             main    #1143      +/-   ##
==========================================
+ Coverage   88.34%   88.48%   +0.14%     
==========================================
  Files         706      706              
  Lines       16436    16468      +32     
  Branches     2662     2670       +8     
==========================================
+ Hits        14520    14572      +52     
+ Misses       1909     1889      -20     
  Partials        7        7              
Impacted Files Coverage Δ
packages/core/src/modules/oob/OutOfBandApi.ts 83.33% <16.66%> (-1.39%) ⬇️
packages/core/src/modules/routing/RecipientApi.ts 70.86% <27.27%> (+9.33%) ⬆️
...ules/routing/services/MediationRecipientService.ts 85.86% <92.85%> (+1.33%) ⬆️
...ges/core/src/modules/connections/ConnectionsApi.ts 68.88% <100.00%> (+1.19%) ⬆️
...c/modules/routing/messages/KeylistUpdateMessage.ts 100.00% <100.00%> (ø)
...ore/src/modules/routing/services/RoutingService.ts 100.00% <100.00%> (ø)
packages/core/src/modules/dids/DidsApi.ts 78.57% <0.00%> (+7.14%) ⬆️
.../core/src/modules/routing/RecipientModuleConfig.ts 100.00% <0.00%> (+26.66%) ⬆️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@genaris genaris requested a review from TimoGlastra December 7, 2022 15:21
Comment on lines +327 to +338
const connection = await this.connectionService.getById(this.agentContext, connectionId)

if (connection.mediatorId && connection.did) {
const did = await this.didResolverService.resolve(this.agentContext, connection.did)

if (did.didDocument) {
await this.routingService.removeRouting(this.agentContext, {
recipientKeys: did.didDocument.recipientKeys,
mediatorId: connection.mediatorId,
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just thinking forward a bit here. If we start supporting public dids I could have multiple connections using the same did, thus removing all the keys at the mediator could lead to issues for other connections. That's not the case at the moment, but just thinking here whether that could lead to issues in the future.

Also we have the didRecord that contains the recipientKeys of the did document, which means we wouldn't have to fetch it from the ledger. Not sure though if that's a better approach?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point here. So the goal is to simply remove the recipientKeys needed for this particular connection, provided they won't affect other connections also related to the same public DID.

If i'm not wrong, even if we are using public DIDs for invitations, we will be always doing some sort of key rotation, because otherwise we wouldn't know, when receiving a message, which connection is that message for. What would be the most direct approach to get the actual recipient keys I need to delete?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would be the most direct approach to get the actual recipient keys I need to delete?

Note sure. That can be really difficult. We would need to check whether any connection of our of band invitation exist with a did that uses a specific key.... I think for now this is fine. We will probably keep the behaviour as you described until at least didcomm v2 and then we only work with dids rather than keys, so it will be easier to discover I guess.

We also don't delete keys for connectionless exchanges after they're done (can be hard to determine what done means in a generic way). We should probably also add that

@@ -565,6 +564,20 @@ export class OutOfBandApi {
* @param outOfBandId the out of band record id
*/
public async deleteById(outOfBandId: string) {
const outOfBandRecord = await this.getById(outOfBandId)

const relatedConnections = await this.connectionsApi.findAllByOutOfBandId(outOfBandId)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can become quite an expensive query if you have a lot of connections created. Another reason to support pagination...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes... Hopefully, delete operations will not be so common, so the performance impact would not be so big.

const relatedConnections = await this.connectionsApi.findAllByOutOfBandId(outOfBandId)

// If it uses mediation and there are no related connections, proceed to delete keys from mediator
if (outOfBandRecord.mediatorId && (relatedConnections.length === 0 || outOfBandRecord.reusable)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we delete the recipientKeys if the oob record is reusable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If an Out of Band record is reusable, every time a new connection is created based on it, a new recipient key will be created and shared with the mediator. My reasoning is that if we delete the out of band record we will not be affecting any connection created from it, and therefore we are safe to delete that key on mediator. Maybe I'm missing something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that makes sense, hadn't thought about it. Maybe add it as a comment to the code :)

@@ -370,8 +373,22 @@ export class RecipientApi {
return mediationRecord
}

public async notifyKeylistUpdate(connection: ConnectionRecord, verkey: string) {
const message = this.mediationRecipientService.createKeylistUpdateMessage(verkey)
public async notifyKeylistUpdate(connection: ConnectionRecord, verkey: string, action?: KeylistUpdateAction) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really related to this PR, but maybe we can update this method to something like:

Suggested change
public async notifyKeylistUpdate(connection: ConnectionRecord, verkey: string, action?: KeylistUpdateAction) {
public async notifyKeylistUpdate({
connectionId: string
publicKeyBase58: string // or even publicKeyFingerprint
action: KeylistUpdateAction // make action required
}) {
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. I just didn't want to introduce breaking changes at the API level on this PR. But for sure this method must be updated. I would like to do something similar to Discover Features module, where we have the option of doing sync or async queries, in order to have a more harmonized Recipient API

endpoints: mediationRecord.endpoint ? [mediationRecord.endpoint] : routing.endpoints,
routingKeys: mediationRecord.routingKeys.map((key) => Key.fromPublicKeyBase58(key, KeyType.Ed25519)),
}
}

public async removeMediationRouting(
agentContext: AgentContext,
{ recipientKeys, mediatorId }: RemoveRoutingOptions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the service level we usually use records over ids, not sure if using a record is better here though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. It was just to have a similar API to addMediationRouting, which also takes mediatorId. Overall I think the API used in this module is quite different from other parts of the framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants