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

Allow specifying key derivation method on sub-wallet create #1719

Merged
merged 14 commits into from
Apr 15, 2022
Merged
7 changes: 6 additions & 1 deletion aries_cloudagent/config/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -1634,7 +1634,7 @@ def add_arguments(self, parser: ArgumentParser):
help=(
'Specify multitenancy configuration ("wallet_type" and "wallet_name"). '
'For example: "{"wallet_type":"askar-profile","wallet_name":'
'"askar-profile-name"}"'
'"askar-profile-name", "key_derivation_method":"RAW"}"'
'"wallet_name" is only used when "wallet_type" is "askar-profile"'
),
)
Expand Down Expand Up @@ -1668,6 +1668,11 @@ def get_settings(self, args: Namespace):
"wallet_name"
)

if multitenancyConfig.get("key_derivation_method"):
settings[
"multitenant.key_derivation_method"
] = multitenancyConfig.get("key_derivation_method")

return settings


Expand Down
26 changes: 17 additions & 9 deletions aries_cloudagent/multitenant/admin/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,23 @@
from aiohttp import web
from aiohttp_apispec import (
docs,
request_schema,
match_info_schema,
response_schema,
querystring_schema,
request_schema,
response_schema,
)
from marshmallow import fields, validate, validates_schema, ValidationError
from marshmallow import ValidationError, fields, validate, validates_schema

from ...admin.request_context import AdminRequestContext
from ...messaging.valid import JSONWebToken, UUIDFour
from ...core.error import BaseError
from ...core.profile import ProfileManagerProvider
from ...messaging.models.base import BaseModelError
from ...messaging.models.openapi import OpenAPISchema
from ...messaging.valid import JSONWebToken, UUIDFour
from ...multitenant.base import BaseMultitenantManager
from ...storage.error import StorageError, StorageNotFoundError
from ...wallet.models.wallet_record import WalletRecord, WalletRecordSchema
from ...wallet.error import WalletSettingsError

from ...core.error import BaseError
from ...core.profile import ProfileManagerProvider

from ...wallet.models.wallet_record import WalletRecord, WalletRecordSchema
from ..error import WalletKeyMissingError


Expand Down Expand Up @@ -58,6 +56,13 @@ class CreateWalletRequestSchema(OpenAPISchema):
description="Master key used for key derivation.", example="MySecretKey123"
)

wallet_key_derivation = fields.Str(
description="Key derivation",
required=False,
example="RAW",
validate=validate.OneOf(["ARGON2I_MOD", "ARGON2I_INT", "RAW"]),
)

wallet_type = fields.Str(
description="Type of the wallet to create",
example="indy",
Expand Down Expand Up @@ -303,10 +308,13 @@ async def wallet_create(request: web.BaseRequest):

label = body.get("label")
image_url = body.get("image_url")
key_derivation = body.get("wallet_key_derivation")
if label:
settings["default_label"] = label
if image_url:
settings["image_url"] = image_url
if key_derivation: # allow lower levels to handle default
settings["wallet.key_derivation_method"] = key_derivation

try:
multitenant_mgr = context.profile.inject(BaseMultitenantManager)
Expand Down
28 changes: 28 additions & 0 deletions aries_cloudagent/multitenant/admin/tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ async def test_wallets_list_query(self):
async def test_wallet_create(self):
body = {
"wallet_name": "test",
"default_label": "test_label",
"wallet_type": "indy",
"wallet_key": "test",
"key_management_mode": "managed",
Expand Down Expand Up @@ -206,6 +207,7 @@ async def test_wallet_create_optional_default_fields(self):
body = {
"wallet_name": "test",
"wallet_key": "test",
"wallet_key_derivation": "ARGON2I_MOD",
"wallet_webhook_urls": [],
"wallet_dispatch_type": "base",
"label": "my_test_label",
Expand All @@ -227,6 +229,32 @@ async def test_wallet_create_optional_default_fields(self):
"image_url": body["image_url"],
"wallet.webhook_urls": body["wallet_webhook_urls"],
"wallet.dispatch_type": body["wallet_dispatch_type"],
"wallet.key_derivation_method": body["wallet_key_derivation"],
},
WalletRecord.MODE_MANAGED,
)

async def test_wallet_create_raw_key_derivation(self):
body = {
"wallet_name": "test",
"wallet_key": "test",
"wallet_key_derivation": "RAW",
}
self.request.json = async_mock.CoroutineMock(return_value=body)

with async_mock.patch.object(test_module.web, "json_response") as mock_response:
self.mock_multitenant_mgr.create_wallet = async_mock.CoroutineMock()
self.mock_multitenant_mgr.create_auth_token = async_mock.CoroutineMock()

await test_module.wallet_create(self.request)
self.mock_multitenant_mgr.create_wallet.assert_called_once_with(
{
"wallet.type": "in_memory",
"wallet.name": body["wallet_name"],
"wallet.key": body["wallet_key"],
"wallet.key_derivation_method": body["wallet_key_derivation"],
"wallet.webhook_urls": [],
"wallet.dispatch_type": "base",
},
WalletRecord.MODE_MANAGED,
)
Expand Down
39 changes: 21 additions & 18 deletions aries_cloudagent/multitenant/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,26 +184,29 @@ async def create_wallet(
)

await wallet_record.save(session)
try:
# provision wallet
profile = await self.get_wallet_profile(
self._profile.context,
wallet_record,
{
"wallet.key": wallet_key,
},
provision=True,
)

# provision wallet
profile = await self.get_wallet_profile(
self._profile.context,
wallet_record,
{
"wallet.key": wallet_key,
},
provision=True,
)

# subwallet context
async with profile.session() as session:
wallet = session.inject(BaseWallet)
public_did_info = await wallet.get_public_did()
# subwallet context
async with profile.session() as session:
wallet = session.inject(BaseWallet)
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
)
if public_did_info:
await self.add_key(
wallet_record.wallet_id, public_did_info.verkey, skip_if_exists=True
)
except Exception:
await wallet_record.delete_record(session)
raise

return wallet_record

Expand Down
5 changes: 5 additions & 0 deletions aries_cloudagent/wallet/models/wallet_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ def wallet_key(self) -> Optional[str]:
"""Accessor for the key of the wallet."""
return self.settings.get("wallet.key")

@property
def wallet_key_derivation_method(self):
"""Accessor for the key derivation method of the wallet."""
return self.settings.get("wallet.key_derivation_method")

@property
def record_value(self) -> dict:
"""Accessor for the JSON record value generated for this record."""
Expand Down