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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] main from hyperledger:main #170

Merged
merged 30 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6715a0b
feat: add did:peer:1 resolution support
dbluhm Nov 17, 2023
a2c6b4f
fix: match legacy behavior better
dbluhm Dec 6, 2023
f689686
test: remove now invalid regression test
dbluhm Dec 6, 2023
0358e1f
fix: connection manager tests
dbluhm Dec 6, 2023
783895b
fix: didexchange manager tests
dbluhm Dec 6, 2023
e498c26
fix: unused import
dbluhm Dec 6, 2023
c5e573b
Slight improvement to credx proof validation error message
ianco Dec 7, 2023
28465b1
Merge branch 'main' into credx_err_msg_fix
ianco Dec 7, 2023
2857a2a
Merge pull request #2611 from dbluhm/feature/did-peer-1-resolve
swcurran Dec 7, 2023
9860157
Merge branch 'main' into credx_err_msg_fix
ianco Dec 7, 2023
5288875
Merge pull request #2655 from ianco/credx_err_msg_fix
ianco Dec 7, 2023
bfecbb7
Update snyk workflow to execute on Pull Request
usingtechnology Dec 7, 2023
67e82b4
Merge pull request #2658 from usingtechnology/issue_2526_snyk
usingtechnology Dec 7, 2023
67374e6
feat: add vc ldp manager
dbluhm Sep 18, 2023
78c75fd
fix: wallet key pair takes profile now
dbluhm Oct 4, 2023
aa69b6d
feat: add vc ldp routes and implement verify
dbluhm Oct 5, 2023
f7d27fe
feat: mark jsonld sign and verify as deprecated
dbluhm Oct 5, 2023
b083e51
feat: integrate vc ldp manager in ICv2, PPv2
dbluhm Oct 5, 2023
7eca31f
fix: ld_proof handler tests
dbluhm Oct 25, 2023
9de833d
test: vc ldp manager
dbluhm Oct 25, 2023
ee9ef3c
fix: dif format handler tests
dbluhm Oct 25, 2023
fe98313
fix: missing decorators on vc ldp manager tests
dbluhm Oct 25, 2023
ccb2454
style: formatting fixes after rebase
dbluhm Nov 17, 2023
952f3cf
fix: tests for vc ldp manager
dbluhm Nov 18, 2023
3e0ebeb
refactor: signature_type as class var
dbluhm Dec 6, 2023
48f2014
fix: bbs signature proof type back in
dbluhm Dec 6, 2023
e9dd05d
fix: created ts according to xml schema datetime spec
dbluhm Dec 7, 2023
773f806
Revert "fix: created ts according to xml schema datetime spec"
dbluhm Dec 7, 2023
d489877
fix: no milliseconds in proof created (take 2)
dbluhm Dec 7, 2023
eb13083
Merge pull request #2533 from dbluhm/refactor/json-ld-sign-consistency
dbluhm Dec 7, 2023
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
8 changes: 7 additions & 1 deletion .github/workflows/snyk.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
name: Snyk Container
on: push
on:
pull_request:
branches: [main]
paths:
- aries_cloudagent
- docker

jobs:
snyk:
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions aries_cloudagent/config/default_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ async def load_plugins(self, context: InjectionContext):
plugin_registry.register_plugin("aries_cloudagent.messaging.jsonld")
plugin_registry.register_plugin("aries_cloudagent.resolver")
plugin_registry.register_plugin("aries_cloudagent.settings")
plugin_registry.register_plugin("aries_cloudagent.vc")
plugin_registry.register_plugin("aries_cloudagent.wallet")
if wallet_type == "askar-anoncreds":
plugin_registry.register_plugin("aries_cloudagent.anoncreds")
Expand Down
51 changes: 29 additions & 22 deletions aries_cloudagent/connections/base_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
For Connection, DIDExchange and OutOfBand Manager.
"""

import json
import logging
from typing import List, Optional, Sequence, Text, Tuple, Union

Expand Down Expand Up @@ -132,35 +133,40 @@ async def create_did_document(

return did_doc

async def store_did_document(self, did_doc: DIDDoc):
async def store_did_document(self, value: Union[DIDDoc, dict]):
"""Store a DID document.

Args:
did_doc: The `DIDDoc` instance to persist
value: The `DIDDoc` instance to persist
"""
assert did_doc.did
if isinstance(value, DIDDoc):
did = value.did
doc = value.to_json()
else:
did = value["id"]
doc = json.dumps(value)

# Special case: we used to store did:sov dids as unqualified.
# For backwards compatibility, we'll strip off the prefix.
if did.startswith("did:sov:"):
did = did[8:]

self._logger.debug("Storing DID document for %s: %s", did, doc)

try:
stored_doc, record = await self.fetch_did_document(did_doc.did)
stored_doc, record = await self.fetch_did_document(did)
except StorageNotFoundError:
record = StorageRecord(
self.RECORD_TYPE_DID_DOC,
did_doc.to_json(),
{"did": did_doc.did},
)
record = StorageRecord(self.RECORD_TYPE_DID_DOC, doc, {"did": did})
async with self._profile.session() as session:
storage: BaseStorage = session.inject(BaseStorage)
await storage.add_record(record)
else:
async with self._profile.session() as session:
storage: BaseStorage = session.inject(BaseStorage)
await storage.update_record(
record, did_doc.to_json(), {"did": did_doc.did}
)
await self.remove_keys_for_did(did_doc.did)
for key in did_doc.pubkey.values():
if key.controller == did_doc.did:
await self.add_key_for_did(did_doc.did, key.value)
await storage.update_record(record, doc, {"did": did})

await self.remove_keys_for_did(did)
await self.record_did(did)

async def add_key_for_did(self, did: str, key: str):
"""Store a verkey for lookup against a DID.
Expand Down Expand Up @@ -219,12 +225,12 @@ async def resolve_didcomm_services(
doc: ResolvedDocument = pydid.deserialize_document(doc_dict, strict=True)
except ResolverError as error:
raise BaseConnectionManagerError(
"Failed to resolve public DID in invitation"
"Failed to resolve DID services"
) from error

if not doc.service:
raise BaseConnectionManagerError(
"Cannot connect via public DID that has no associated services"
"Cannot connect via DID that has no associated services"
)

didcomm_services = sorted(
Expand Down Expand Up @@ -580,7 +586,7 @@ async def get_connection_targets(

def diddoc_connection_targets(
self,
doc: DIDDoc,
doc: Optional[Union[DIDDoc, dict]],
sender_verkey: str,
their_label: Optional[str] = None,
) -> Sequence[ConnectionTarget]:
Expand All @@ -591,6 +597,8 @@ def diddoc_connection_targets(
sender_verkey: The verkey we are using
their_label: The connection label they are using
"""
if isinstance(doc, dict):
doc = DIDDoc.deserialize(doc)
if not doc:
raise BaseConnectionManagerError("No DIDDoc provided for connection target")
if not doc.did:
Expand All @@ -617,17 +625,16 @@ def diddoc_connection_targets(
)
return targets

async def fetch_did_document(self, did: str) -> Tuple[DIDDoc, StorageRecord]:
async def fetch_did_document(self, did: str) -> Tuple[dict, StorageRecord]:
"""Retrieve a DID Document for a given DID.

Args:
did: The DID to search for
"""
# legacy documents for unqualified dids
async with self._profile.session() as session:
storage = session.inject(BaseStorage)
record = await storage.find_record(self.RECORD_TYPE_DID_DOC, {"did": did})
return DIDDoc.from_json(record.value), record
return json.loads(record.value), record

async def find_connection(
self,
Expand Down
15 changes: 9 additions & 6 deletions aries_cloudagent/connections/models/conn_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from ...core.profile import ProfileSession
from ...messaging.models.base_record import BaseRecord, BaseRecordSchema
from ...messaging.valid import (
INDY_DID_EXAMPLE,
INDY_DID_VALIDATE,
GENERIC_DID_EXAMPLE,
GENERIC_DID_VALIDATE,
INDY_RAW_PUBLIC_KEY_EXAMPLE,
INDY_RAW_PUBLIC_KEY_VALIDATE,
UUID4_EXAMPLE,
Expand Down Expand Up @@ -653,15 +653,18 @@ class Meta:
)
my_did = fields.Str(
required=False,
validate=INDY_DID_VALIDATE,
metadata={"description": "Our DID for connection", "example": INDY_DID_EXAMPLE},
validate=GENERIC_DID_VALIDATE,
metadata={
"description": "Our DID for connection",
"example": GENERIC_DID_EXAMPLE,
},
)
their_did = fields.Str(
required=False,
validate=INDY_DID_VALIDATE,
validate=GENERIC_DID_VALIDATE,
metadata={
"description": "Their DID for connection",
"example": INDY_DID_EXAMPLE,
"example": GENERIC_DID_EXAMPLE,
},
)
their_label = fields.Str(
Expand Down
77 changes: 11 additions & 66 deletions aries_cloudagent/connections/tests/test_base_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@
from ...resolver.default.key import KeyDIDResolver
from ...resolver.default.legacy_peer import LegacyPeerDIDResolver
from ...resolver.did_resolver import DIDResolver
from ...storage.base import BaseStorage
from ...storage.error import StorageNotFoundError
from ...storage.record import StorageRecord
from ...transport.inbound.receipt import MessageReceipt
from ...utils.multiformats import multibase, multicodec
from ...wallet.base import DIDInfo
Expand Down Expand Up @@ -243,70 +241,6 @@ async def test_did_key_storage(self):
assert did == self.test_target_did
await self.manager.remove_keys_for_did(self.test_target_did)

async def test_store_did_document_with_routing_keys(self):
"""Regression test for ensuring agents with the same mediator can connect."""

# Replicate old behavior where routing keys could be stored multiple times
routing_key = "cK7fwfjpakMuv8QKVv2y6qouZddVw4TxZNQPUs2fFTd"
async with self.profile.session() as session:
for _ in range(3):
record = StorageRecord(
self.manager.RECORD_TYPE_DID_KEY,
routing_key,
{"did": "bogus", "key": routing_key},
)
storage = session.inject(BaseStorage)
await storage.add_record(record)

# The DIDDoc class will turn the routing key into a publicKey entry.
# This is NOT the correct behavior for normalizing DID Documents.
# Unforunately, it's been doing it for a long time; to accomodate
# stored records, we need to make sure we can handle duplicate records
# where they shouldn't actually be.
# These records were never used or else we would have seen errors raised
# by find_did_for_key compaining of duplicate records.
doc_with_routing_keys = DIDDoc.deserialize(
{
"@context": "https://w3id.org/did/v1",
"publicKey": [
{
"id": "YQwDgq9vdAbB3fk1tkeXmg#1",
"controller": "YQwDgq9vdAbB3fk1tkeXmg",
"type": "Ed25519VerificationKey2018",
"publicKeyBase58": "J81x9zdJa8CGSbTYpoYQaNrV6yv13M1Lgz4tmkNPKwZn",
},
{
"id": "YQwDgq9vdAbB3fk1tkeXmg#1",
"controller": "YQwDgq9vdAbB3fk1tkeXmg",
"type": "Ed25519VerificationKey2018",
"publicKeyBase58": routing_key,
},
],
"service": [
{
"id": "YQwDgq9vdAbB3fk1tkeXmg#IndyAgentService",
"serviceEndpoint": "https://aries-mediator-agent.vonx.io",
"type": "IndyAgent",
"priority": 0,
"recipientKeys": [
"J81x9zdJa8CGSbTYpoYQaNrV6yv13M1Lgz4tmkNPKwZn"
],
"routingKeys": [routing_key],
}
],
"authentication": [
{
"publicKey": "YQwDgq9vdAbB3fk1tkeXmg#1",
"type": "Ed25519SignatureAuthentication2018",
}
],
"id": "YQwDgq9vdAbB3fk1tkeXmg",
}
)
with self.assertLogs(level="WARNING") as context:
await self.manager.store_did_document(doc_with_routing_keys)
assert context.output and "Key already associated with DID" in context.output[0]

async def test_fetch_connection_targets_no_my_did(self):
mock_conn = mock.MagicMock()
mock_conn.my_did = None
Expand Down Expand Up @@ -1793,3 +1727,14 @@ async def test_get_endpoints(self):
"localhost:8020",
"10.20.30.40:5060",
)

async def test_diddoc_connection_targets_diddoc(self):
did_doc = self.make_did_doc(
self.test_target_did,
self.test_target_verkey,
)
targets = self.manager.diddoc_connection_targets(
did_doc,
self.test_verkey,
)
assert isinstance(targets[0], ConnectionTarget)
3 changes: 2 additions & 1 deletion aries_cloudagent/indy/credx/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ async def verify_presentation(
msgs.append(f"{PresVerifyMsg.PRES_VALUE_ERROR.value}::{s}")
LOGGER.error(
f"Presentation on nonce={pres_req['nonce']} "
f"cannot be validated: {str(err)}"
f"cannot be validated (presentation will be marked as Invalid)"
f": {str(err)}"
)
return (False, msgs)

Expand Down
12 changes: 10 additions & 2 deletions aries_cloudagent/messaging/jsonld/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ class SignResponseSchema(OpenAPISchema):
error = fields.Str(required=False, metadata={"description": "Error text"})


@docs(tags=["jsonld"], summary="Sign a JSON-LD structure and return it")
@docs(
tags=["jsonld"],
summary="Sign a JSON-LD structure and return it",
deprecated=True,
)
@request_schema(SignRequestSchema())
@response_schema(SignResponseSchema(), 200, description="")
async def sign(request: web.BaseRequest):
Expand Down Expand Up @@ -119,7 +123,11 @@ class VerifyResponseSchema(OpenAPISchema):
error = fields.Str(required=False, metadata={"description": "Error text"})


@docs(tags=["jsonld"], summary="Verify a JSON-LD structure.")
@docs(
tags=["jsonld"],
summary="Verify a JSON-LD structure.",
deprecated=True,
)
@request_schema(VerifyRequestSchema())
@response_schema(VerifyResponseSchema(), 200, description="")
async def verify(request: web.BaseRequest):
Expand Down
Loading
Loading