Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 1 addition & 7 deletions .github/workflows/sonar-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,6 @@ jobs:
echo base branch = ${{ fromJson(steps.get_pr_data.outputs.data).base.ref }}

git checkout -B temp-branch-for-scanning upstream/${{ fromJson(steps.get_pr_data.outputs.data).head.ref }}
- name: Move Coverage Report And Adjust Source
run: |
mkdir test-reports
mv coverage.xml test-reports
# Need to change source in coverage report because it was generated from another context
sed -i 's/\/home\/runner\/work\/acapy\/acapy\//\/github\/workspace\//g' test-reports/coverage.xml
- name: SonarCloud Scan
uses: SonarSource/sonarqube-scan-action@master
env:
Expand All @@ -70,5 +64,5 @@ jobs:
-Dsonar.pullrequest.base=${{ fromJson(steps.get_pr_data.outputs.data).base.ref }}
-Dsonar.coverage.exclusions=**/tests/**,**/demo/**,**/docs/**,**/docker/**,**/scripts/**,**/scenarios/**
-Dsonar.cpd.exclusions=**/tests/**,**/demo/**,**/docs/**,**/docker/**,**/scripts/**,**/scenarios/**
-Dsonar.python.coverage.reportPaths=test-reports/coverage.xml
-Dsonar.python.coverage.reportPaths=coverage.xml
-Dsonar.sources=./
2 changes: 1 addition & 1 deletion acapy_agent/askar/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def bind_providers(self):
VCHolder,
ClassProvider(
"acapy_agent.storage.vc_holder.askar.AskarVCHolder",
ref(self),
ClassProvider.Inject(Profile),
),
)
if (
Expand Down
2 changes: 1 addition & 1 deletion acapy_agent/connections/base_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ async def resolve_didcomm_services(
try:
doc_dict: dict = await resolver.resolve(self._profile, did, service_accept)
doc: ResolvedDocument = pydid.deserialize_document(doc_dict, strict=True)
except ResolverError as error:
except (ResolverError, ValueError) as error:
raise BaseConnectionManagerError("Failed to resolve DID services") from error

if not doc.service:
Expand Down
2 changes: 1 addition & 1 deletion acapy_agent/ledger/indy_vdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ async def credential_definition_id2schema_id(self, credential_definition_id):
seq_no = tokens[3]
return (await self.get_schema(seq_no))["id"]

async def get_key_for_did(self, did: str) -> str:
async def get_key_for_did(self, did: str) -> Optional[str]:
"""Fetch the verkey for a ledger DID.

Args:
Expand Down
19 changes: 13 additions & 6 deletions acapy_agent/messaging/valid.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,16 +363,20 @@ def __init__(self):


class AnoncredsDID(Regexp):
"""Validate value against indy DID."""
"""Validate value against anoncreds DID."""

METHOD = r"([a-zA-Z0-9_]+)"
NETWORK = r"(:[a-zA-Z0-9_.%-]+)?" # Optional network
METHOD_ID = r"([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)"

EXAMPLE = "did:(method):WgWxqztrNooG92RXvxSTWv"
PATTERN = re.compile("^(did:[a-z]:.+$)?$")
PATTERN = re.compile(rf"^did:{METHOD}{NETWORK}:{METHOD_ID}")

def __init__(self):
"""Initialize the instance."""

super().__init__(
IndyDID.PATTERN,
DIDValidation.PATTERN,
error="Value {input} is not an decentralized identifier (DID)",
)

Expand All @@ -381,14 +385,17 @@ class DIDValidation(Regexp):
"""Validate value against any valid DID spec."""

METHOD = r"([a-zA-Z0-9_]+)"
NETWORK = r"(:[a-zA-Z0-9_.%-]+)?" # Optional network
METHOD_ID = r"([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)"
PARAMS = r"((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)"
PATH = r"(\/[^#?]*)?"
QUERY = r"([?][^#]*)?"
FRAGMENT = r"(\#.*)?$"

EXAMPLE = "did:peer:WgWxqztrNooG92RXvxSTWv"
PATTERN = re.compile(rf"^did:{METHOD}:{METHOD_ID}{PARAMS}{PATH}{QUERY}{FRAGMENT}$")
PATTERN = re.compile(
rf"^did:{METHOD}{NETWORK}:{METHOD_ID}{PARAMS}{PATH}{QUERY}{FRAGMENT}$"
)

def __init__(self):
"""Initialize the instance."""
Expand Down Expand Up @@ -485,7 +492,7 @@ def __init__(self):
"""Initialize the instance."""

super().__init__(
IndyCredDefId.PATTERN,
AnoncredsCredDefId.PATTERN,
error="Value {input} is not an anoncreds credential definition identifier",
)

Expand Down Expand Up @@ -530,7 +537,7 @@ def __init__(self):
"""Initialize the instance."""

super().__init__(
IndySchemaId.PATTERN,
AnoncredsSchemaId.PATTERN,
error="Value {input} is not an anoncreds schema identifier",
)

Expand Down
4 changes: 2 additions & 2 deletions acapy_agent/protocols/did_rotate/v1_0/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ async def receive_rotate(self, conn: ConnRecord, rotate: Rotate) -> RotateRecord
)

try:
await self._ensure_supported_did(rotate.to_did)
await self.ensure_supported_did(rotate.to_did)
except ReportableDIDRotateError as err:
responder = self.profile.inject(BaseResponder)
err.message.assign_thread_from(rotate)
Expand Down Expand Up @@ -234,7 +234,7 @@ async def receive_hangup(self, conn: ConnRecord):
async with self.profile.session() as session:
await conn.delete_record(session)

async def _ensure_supported_did(self, did: str):
async def ensure_supported_did(self, did: str):
"""Check if the DID is supported."""
resolver = self.profile.inject(DIDResolver)
conn_mgr = BaseConnectionManager(self.profile)
Expand Down
4 changes: 2 additions & 2 deletions acapy_agent/protocols/did_rotate/v1_0/message_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
MESSAGE_TYPES = DIDCommPrefix.qualify_all(
{
ROTATE: f"{PROTOCOL_PACKAGE}.messages.rotate.Rotate",
ACK: f"{PROTOCOL_PACKAGE}.messages.ack.Ack",
ACK: f"{PROTOCOL_PACKAGE}.messages.ack.RotateAck",
HANGUP: f"{PROTOCOL_PACKAGE}.messages.hangup.Hangup",
PROBLEM_REPORT: f"{PROTOCOL_PACKAGE}.messages.problem_report.ProblemReport",
PROBLEM_REPORT: f"{PROTOCOL_PACKAGE}.messages.problem_report.RotateProblemReport",
}
)
17 changes: 16 additions & 1 deletion acapy_agent/protocols/did_rotate/v1_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@
from ....messaging.models.openapi import OpenAPISchema
from ....messaging.valid import DID_WEB_EXAMPLE, UUID4_EXAMPLE
from ....storage.error import StorageNotFoundError
from .manager import DIDRotateManager
from .manager import (
DIDRotateManager,
UnresolvableDIDCommServicesError,
UnresolvableDIDError,
UnsupportedDIDMethodError,
)
from .message_types import SPEC_URI
from .messages.hangup import HangupSchema as HangupMessageSchema
from .messages.rotate import RotateSchema as RotateMessageSchema
Expand Down Expand Up @@ -63,6 +68,16 @@ async def rotate(request: web.BaseRequest):
body = await request.json()
to_did = body["to_did"]

# Validate DID before proceeding
try:
await did_rotate_mgr.ensure_supported_did(to_did)
except (
UnsupportedDIDMethodError,
UnresolvableDIDError,
UnresolvableDIDCommServicesError,
) as err:
raise web.HTTPBadRequest(reason=str(err)) from err

async with context.session() as session:
try:
conn = await ConnRecord.retrieve_by_id(session, connection_id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ async def test_receive_rotate_x(self):

with (
mock.patch.object(
self.manager, "_ensure_supported_did", side_effect=test_problem_report
self.manager, "ensure_supported_did", side_effect=test_problem_report
),
mock.patch.object(self.responder, "send", mock.CoroutineMock()) as mock_send,
):
Expand Down
35 changes: 33 additions & 2 deletions acapy_agent/protocols/did_rotate/v1_0/tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ async def asyncSetUp(self):
"DIDRotateManager",
autospec=True,
return_value=mock.MagicMock(
rotate_my_did=mock.CoroutineMock(return_value=generate_mock_rotate_message())
rotate_my_did=mock.CoroutineMock(return_value=generate_mock_rotate_message()),
ensure_supported_did=mock.CoroutineMock(),
),
)
async def test_rotate(self, *_):
Expand Down Expand Up @@ -102,7 +103,15 @@ async def test_hangup(self, *_):
}
)

async def test_rotate_conn_not_found(self):
@mock.patch.object(
test_module,
"DIDRotateManager",
autospec=True,
return_value=mock.MagicMock(
ensure_supported_did=mock.CoroutineMock(),
),
)
async def test_rotate_conn_not_found(self, *_):
self.request.match_info = {"conn_id": test_conn_id}
self.request.json = mock.CoroutineMock(return_value=test_valid_rotate_request)

Expand All @@ -114,6 +123,28 @@ async def test_rotate_conn_not_found(self):
with self.assertRaises(test_module.web.HTTPNotFound):
await test_module.rotate(self.request)

async def test_rotate_did_validation_errors(self):
self.request.match_info = {"conn_id": test_conn_id}
self.request.json = mock.CoroutineMock(return_value=test_valid_rotate_request)

for error_class in [
test_module.UnsupportedDIDMethodError,
test_module.UnresolvableDIDError,
test_module.UnresolvableDIDCommServicesError,
]:
with mock.patch.object(
test_module,
"DIDRotateManager",
autospec=True,
return_value=mock.MagicMock(
ensure_supported_did=mock.CoroutineMock(
side_effect=error_class("test error")
),
),
):
with self.assertRaises(test_module.web.HTTPBadRequest):
await test_module.rotate(self.request)


if __name__ == "__main__":
unittest.main()
42 changes: 21 additions & 21 deletions acapy_agent/revocation_anoncreds/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@
from ..ledger.multiple_ledger.base_manager import BaseMultipleLedgerManager
from ..messaging.models.openapi import OpenAPISchema
from ..messaging.valid import (
INDY_CRED_DEF_ID_EXAMPLE,
INDY_CRED_DEF_ID_VALIDATE,
ANONCREDS_CRED_DEF_ID_EXAMPLE,
ANONCREDS_CRED_DEF_ID_VALIDATE,
INDY_CRED_REV_ID_EXAMPLE,
INDY_CRED_REV_ID_VALIDATE,
INDY_REV_REG_ID_EXAMPLE,
INDY_REV_REG_ID_VALIDATE,
ANONCREDS_REV_REG_ID_EXAMPLE,
ANONCREDS_REV_REG_ID_VALIDATE,
UUID4_EXAMPLE,
UUID4_VALIDATE,
WHOLE_NUM_EXAMPLE,
Expand Down Expand Up @@ -99,10 +99,10 @@ def validate_fields(self, data, **kwargs):

rev_reg_id = fields.Str(
required=False,
validate=INDY_REV_REG_ID_VALIDATE,
validate=ANONCREDS_REV_REG_ID_VALIDATE,
metadata={
"description": "Revocation registry identifier",
"example": INDY_REV_REG_ID_EXAMPLE,
"example": ANONCREDS_REV_REG_ID_EXAMPLE,
},
)
cred_rev_id = fields.Str(
Expand Down Expand Up @@ -138,18 +138,18 @@ def validate_fields(self, data, **kwargs):

rev_reg_id = fields.Str(
required=False,
validate=INDY_REV_REG_ID_VALIDATE,
validate=ANONCREDS_REV_REG_ID_VALIDATE,
metadata={
"description": "Revocation registry identifier",
"example": INDY_REV_REG_ID_EXAMPLE,
"example": ANONCREDS_REV_REG_ID_EXAMPLE,
},
)
cred_def_id = fields.Str(
required=False,
validate=INDY_CRED_DEF_ID_VALIDATE,
validate=ANONCREDS_CRED_DEF_ID_VALIDATE,
metadata={
"description": "Credential definition identifier",
"example": INDY_CRED_DEF_ID_EXAMPLE,
"example": ANONCREDS_CRED_DEF_ID_EXAMPLE,
},
)

Expand Down Expand Up @@ -215,10 +215,10 @@ class RevRegsCreatedSchemaAnoncreds(OpenAPISchema):

rev_reg_ids = fields.List(
fields.Str(
validate=INDY_REV_REG_ID_VALIDATE,
validate=ANONCREDS_REV_REG_ID_VALIDATE,
metadata={
"description": "Revocation registry identifiers",
"example": INDY_REV_REG_ID_EXAMPLE,
"example": ANONCREDS_REV_REG_ID_EXAMPLE,
},
)
)
Expand All @@ -233,7 +233,7 @@ class RevRegUpdateTailsFileUriSchema(OpenAPISchema):
"description": "Public URI to the tails file",
"example": (
"http://192.168.56.133:6543/revocation/registry/"
f"{INDY_REV_REG_ID_EXAMPLE}/tails-file"
f"{ANONCREDS_REV_REG_ID_EXAMPLE}/tails-file"
),
},
)
Expand All @@ -244,10 +244,10 @@ class RevRegsCreatedQueryStringSchema(OpenAPISchema):

cred_def_id = fields.Str(
required=False,
validate=INDY_CRED_DEF_ID_VALIDATE,
validate=ANONCREDS_CRED_DEF_ID_VALIDATE,
metadata={
"description": "Credential definition identifier",
"example": INDY_CRED_DEF_ID_EXAMPLE,
"example": ANONCREDS_CRED_DEF_ID_EXAMPLE,
},
)
state = fields.Str(
Expand Down Expand Up @@ -284,10 +284,10 @@ class RevRegIdMatchInfoSchema(OpenAPISchema):

rev_reg_id = fields.Str(
required=True,
validate=INDY_REV_REG_ID_VALIDATE,
validate=ANONCREDS_REV_REG_ID_VALIDATE,
metadata={
"description": "Revocation Registry identifier",
"example": INDY_REV_REG_ID_EXAMPLE,
"example": ANONCREDS_REV_REG_ID_EXAMPLE,
},
)

Expand All @@ -297,10 +297,10 @@ class RevocationCredDefIdMatchInfoSchema(OpenAPISchema):

cred_def_id = fields.Str(
required=True,
validate=INDY_CRED_DEF_ID_VALIDATE,
validate=ANONCREDS_CRED_DEF_ID_VALIDATE,
metadata={
"description": "Credential definition identifier",
"example": INDY_CRED_DEF_ID_EXAMPLE,
"example": ANONCREDS_CRED_DEF_ID_EXAMPLE,
},
)

Expand Down Expand Up @@ -348,7 +348,7 @@ class PublishRevocationsSchemaAnoncreds(OpenAPISchema):

rrid2crid = fields.Dict(
required=False,
keys=fields.Str(metadata={"example": INDY_REV_REG_ID_EXAMPLE}),
keys=fields.Str(metadata={"example": ANONCREDS_REV_REG_ID_EXAMPLE}),
values=fields.List(
fields.Str(
validate=INDY_CRED_REV_ID_VALIDATE,
Expand All @@ -368,7 +368,7 @@ class PublishRevocationsResultSchemaAnoncreds(OpenAPISchema):

rrid2crid = fields.Dict(
required=False,
keys=fields.Str(metadata={"example": INDY_REV_REG_ID_EXAMPLE}),
keys=fields.Str(metadata={"example": ANONCREDS_REV_REG_ID_EXAMPLE}),
values=fields.List(
fields.Str(
validate=INDY_CRED_REV_ID_VALIDATE,
Expand Down
Loading
Loading