bcgov / traction

Traction is designed with an API-first architecture layered on top of Hyperledger Aries Cloud Agent Python (ACA-Py) and streamlines the process of sending and receiving digital credentials for governments and organizations.
https://digital.gov.bc.ca/digital-trust/tools/traction/
Apache License 2.0
53 stars 51 forks source link

Updating Traction to 1.0.0 can cause issues with older Innkeeper setups on single database mode #1423

Closed loneil closed 1 week ago

loneil commented 3 weeks ago

Earlier Traction deployments on OCP (pre 0.12.0 of ACA-Py it seems) have been running in single wallet db mode (so multitenant sub wallets go in one DB) but it seems that due to Innkeeper plugin running through a different multitenancy provider path (plugin config, order of loading plugins) that the Innkeeper tenant was still creating in it's own database. And that was still working in that bifurcated mode. Tenants to a single DB, Innkeeper to a standalone.

See example DB setup:

image

After fixing up some multitenancy and innkeeper plugin things this setup stopped working once upgrading Traction to 1.0.0 using the newer ACA-Py releases and plugin changes.

If manifests in the following way:

2024-11-12 17:58:13,266 TENANT: None ERROR /home/aries/.venv/lib/python3.12/site-packages/aiohttp/web_protocol.py:448 Error handling request
Traceback (most recent call last):
File "/home/aries/.venv/lib/python3.12/site-packages/acapy_agent/askar/profile.py", line 244, in _setup
self._handle = await asyncio.wait_for(self._opener, 10)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/asyncio/tasks.py", line 520, in wait_for
return await fut
^^^^^^^^^
File "/home/aries/.venv/lib/python3.12/site-packages/aries_askar/store.py", line 733, in _open
await bindings.session_start(self._store, self._profile, self._is_txn),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/aries/.venv/lib/python3.12/site-packages/aries_askar/bindings/__init__.py", line 262, in session_start
handle = await invoke_async(
^^^^^^^^^^^^^^^^^^^
File "/home/aries/.venv/lib/python3.12/site-packages/aries_askar/bindings/lib.py", line 362, in invoke_async
return await self.loaded.invoke_async(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/asyncio/futures.py", line 291, in __await__
yield self # This tells Task to wait for completion.
^^^^^^^^^^
File "/usr/local/lib/python3.12/asyncio/tasks.py", line 385, in __wakeup
future.result()
File "/usr/local/lib/python3.12/asyncio/futures.py", line 203, in result
raise self._exception.with_traceback(self._exception_tb)
aries_askar.error.AskarError: Profile not found
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/aries/.venv/lib/python3.12/site-packages/aiohttp/web_protocol.py", line 477, in _handle_request
resp = await request_handler(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/aries/.venv/lib/python3.12/site-packages/aiohttp/web_app.py", line 559, in _handle
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/home/aries/.venv/lib/python3.12/site-packages/aiohttp/web_middlewares.py", line 117, in impl
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/home/aries/.venv/lib/python3.12/site-packages/acapy_agent/admin/server.py", line 141, in ready_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/home/aries/.venv/lib/python3.12/site-packages/acapy_agent/admin/server.py", line 212, in debug_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/home/aries/.venv/lib/python3.12/site-packages/acapy_agent/admin/server.py", line 357, in setup_context
return await task
^^^^^^^^^^
File "/usr/local/lib/python3.12/asyncio/futures.py", line 291, in __await__
yield self # This tells Task to wait for completion.
^^^^^^^^^^
File "/usr/local/lib/python3.12/asyncio/tasks.py", line 385, in __wakeup
future.result()
File "/usr/local/lib/python3.12/asyncio/futures.py", line 203, in result
raise self._exception.with_traceback(self._exception_tb)
File "/usr/local/lib/python3.12/asyncio/tasks.py", line 316, in __step_run_and_handle_result
result = coro.throw(exc)
^^^^^^^^^^^^^^^
File "/home/aries/.venv/lib/python3.12/site-packages/acapy_agent/admin/server.py", line 183, in upgrade_middleware
async with context.profile.session() as session:
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/aries/.venv/lib/python3.12/site-packages/acapy_agent/core/profile.py", line 197, in __aenter__
await self._setup()
File "/home/aries/.venv/lib/python3.12/site-packages/acapy_agent/askar/profile.py", line 246, in _setup
raise ProfileError("Error opening store session") from err
acapy_agent.core.error.ProfileError: Error opening store session

Note this is a pretty generic error that can happen in other cases where storage can't find the profile (DB inaccessible, etc). So this error isn't specific to the Innkeeper case here.

Other existing tenants work just fine, can access them, use webhooks, use API Keys, etc. It's just the Innkeeper tenant that breaks this way. This means you can't look at other tenants, delete them, manage API keys at the Innkeeper level, or create new tenants.

Easiest fix for this is to just create a new Innkeeper, there's no historical data kept in the old Innkeeper or anything. The Innkeeper is just another Tenant, it just has specific permissions to call specific routes in the Innkeeper plugin is all.

To do that can leverage the fact that Traction will create an innkeeper on startup if one is not found. So can do the following steps.

loneil commented 1 week ago

Closing this issue as it's done on dev/test/prod for us. The above can be kept around here for if anyone else searches for any of these details