These scripts allow a developer (or similiarly interested party), to build and spin up a local environment of Traction (multitenant acapy + plugins + tenant ui).
Traction is a multi-tenanted Aca-Py that is intended to aid tenants with a self-service model. To support this, there are two "roles": innkeeper and tenant.
Innkeeper is used by the administrator of the multi-tenanted Aca-Py instance and is used to onboard tenants. There will be additional administrative functions added but currently their role is basically approval (or denial) of requests to become tenants.
Tenants are analogous to wallets when Aca-Py is in multitenant mode. Traction plugins add enhanced functionality to the current Aca-Py API. Note that the "innkeeper" is also a tenant (one with some administrative abilities and responsibilites).
Tenants onboard to the system by making a reservation. The innkeeper will approve (or deny) the reservation. Tenants that have been given approval will then check-in and be given their keys (wallet_id
, wallet_key
, ability to get tokens...).
The Tenant UI is for the innkeeper AND tenants. (Prospective) Tenants can make a reservation, check the status of their reservation, check-in when approved and then login and perform necessary start up tasks for their wallet/agent (public did, connect with endorser, create schemas and credential defintions, etc). The Innkeeper can review reservations and approve/deny, and then manage tenants.
New functionality is being added daily, so stay tuned as the Tenant UI grows. Keep in mind, the Tenant UI is NOT intended to support all possible functions allowed by Aca-Py, nor is it intended to act as your line of business application. The vision is to support the most necessary start up procedures and functions that are not done regularly (i.e. create a schema).
For tenants to perform all their Aca-Py calls, access is done through an NGINX proxy. This allows tenants to call most all endpoints found in Aca-Py Admin plus enhancements added through the Traction Plugins. This is the API your controllers and line of business apps will call. See NGINX Template
A very simple server/controller to demonstrate integrating your Line of Business application with Traction/Aca-Py via webhooks. See services/tenant-lob.
Currently this setup has dependencies on BCovrin Test Ledger and a registered endorser DID. These constraints will be removed, they are just short term requirements that the BC Gov developers needed to communicate with phone/wallets and other DIDs on the same ledger for demonstration purposes. This is not a vision for Traction, as it should be up to the administrator/installer/devops team (and their business contraints) for endorsement. Feel free to alter the default configuration for your purposes, but understand their may be some unintended consequences and it may not work correctly.
Also, there are longer term goals for moving the plugins to separate repositories and allowing teams to pull them in and configure their own Aca-Py images as needed. Currently, we are pulling the plugins in as source and building a custom image. For local development, the build of this image is included in the docker compose build
command. Once the Aca-py + plugin image is built (tagged: traction:plugins-acapy
), that image is pulled into another that we use to run an ngrok script for external access to our agent (see services/aca-py. This is not what we are doing in production, but we are doing it here (for now).
This image is based on ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.9.0-rc0 and this is where we pull in the traction plugins and build out the image see Dockerfile
The plugins are built using the base plugins pyproject.toml which pulls in each plugin as source. Simply adding new plugin directories to the file system and adding to the dockerfile will not be enough, they must be dependencies in the plugins/pyproject.toml
.
Stay tuned for updates to make this process simpler and more generic. It is currently in place to support some immediate needs by the BC Gov developers.
The default configuration will stand up the following environment:
- NGROK Traction Agent. An ngrok public endpoint for acapy agent... see
ACAPY_HTTP_PORT
environment variable (8030). - Traction Agent. Multitenanted Aca-Py with Traction Plugins
- Tenant Proxy. NGINX proxy for tenant API... see
TENANT_PROXY_PORT
environment variable (8032). - Traction DB. Postgresql database for Traction Agent Aca-Py
- Tenant UI. Vue 3 application for innkeeper (tenant onboarding) and tenants... see
TENANT_UI_PORT
environment variable (5101). - Endorser API. Controller for endorser running locally.
- Endorser Agent. Aca-Py configured for endorser role.
- Endorser DB. Postgresql database for Endorser Agent Aca-Py
- innkeeper / change-me
- BCovrin Test ledger... see
ACAPY_GENESIS_URL
environment variable (http://test.bcovrin.vonx.io/genesis). - previously registered Endorser DID... see
ACAPY_ENDORSER_PUBLIC_DID
environment variable.
- docker
- docker compose (V1 or V2)
There are two commands that may act differently depending on your configuration: docker compose
and docker-compose
.
In the following example, you can see that the two commands use two different docker compose versions. (This is a Mac with Docker Docker Desktop 4.16.2 with V2 disabled in the settings).
CountryMac:scripts jason$ docker compose version
> Docker Compose version v2.15.1
CountryMac:scripts jason$ docker-compose version
> docker-compose version 1.29.2, build 5becea4c
Now, the same machine with V2 enabled in the Docker Desktop settings.
CountryMac:scripts jason$ docker compose version
> Docker Compose version v2.15.1
CountryMac:scripts jason$ docker-compose version
> Docker Compose version v2.15.1
- copy
.env-example
to.env
and adjust as necessary for your environment - bring up traction
cp .env-example .env
docker compose build
docker compose up
Note: to use your ngrok
auth token and prevent the tunnels from expiring, add the value in the .env
file after uncommenting the line defining NGROK_AUTHTOKEN
and then start the project with docker compose up
.
Docker Compose (and docker) configurations vary greatly for every developer, we cannot assure that the docker compose files will work with every nuance and tweak a developer makes to their configuration (using buildkit or not, logged in or not, etc.). These scripts have been tested against Docker / Docker Compose V1 and V2. Using docker compose
to build series of images seems to vary the most between V1 and V2 and various developer machines. If you have issues building try clearing out your docker and build images directly. See above for checking your versions.
Try the following to purge your docker containers, images and build cache:
docker rm -vf $(docker ps -aq)
docker rmi -f $(docker images -aq)
docker system prune -a --volumes
Assume starting in /scripts
...
cd ../plugins/docker
docker build -f ./Dockerfile --tag traction:plugins-acapy ..
cd ../../services/aca-py
docker build -f ./Dockerfile.acapy --tag traction:traction-agent .
cd ../../scripts
docker compose up
If there are still errors, try turning buildkit off. In the terminal where you are running your builds:
export DOCKER_BUILDKIT=0
Then try building again.
This will leave the volume (data) intact and available on restart.
docker compose down
IMPORTANT when envionments are torn down and then brought up, a new ngrok endpoint is created. This could cause issues reusing tenants/wallets as they will be registered with defunct ngrok endpoints.
This will remove the volume, so next start/up will re-recreate a new environment.
docker compose down -v --remove-orphans
The following guide, we will perform a simple onboarding process where you will play both the innkeeper and a tenant.
This assumes a clean environment built and started as documented above.
You may find it easier to just leave tabs open instead of copying and saving the IDs, passwords and keys.
- (Tenant) Make a reservation
- open a new tab to act as a prospective tenant and make a reservation
- navigate to http://localhost:5101
- Click on Create Request
- Fill in request, remember the email address and set Tenant name to something unique.
- Submit Request - copy the email address and Reservation ID.
- (Innkeeper) Approve the Reservation
- open a new tab in a browser to perform innkeeper duties.
- navigate to http://localhost:5101/innkeeper
- Sign-in with:
- Admin Name =
innkeeper
- Admin Key =
change-me
- Admin Name =
- Go to the Reservations tab and refresh if needed.
- Approve the Reservation by clicking the checkmark under Actions column
- Copy the Reservation Password (NOTE: this is not happening in production, the reservation password will be delivered to the tenant by email or some other means)
- (Tenant) Check reservation status
- open a new tab to act as a prospective tenant and check the reservation
- navigate to http://localhost:5101
- Click on Check Status
- enter the email address from above and the saved Reservation ID
- Click Check Status and it should be approved.
- Enter in the Reservation password.
- This should be validated and you are presented with your Wallet ID and Wallet Key.
- Copy these down!
- (Tenant) Sign in
- open new tab for the tenant
- navigate to http://localhost:5101
- Enter the saved Wallet ID and Wallet Key
You can use the wallet id and key to retrieve a token and use the Tenant API.
- Open new tab and navigate to http://localhost:8032/api/doc
- Scroll down to POST multitenancy/wallet/{wallet_id}/token
- Expand and click Try it out.
- Populate the body with your Wallet Key
- Enter your Wallet ID in the
wallet_id
field. - Click Execute and check the response.
- Copy the value for
token
from the response. - Scroll to the top (or click on a lock icon).
- In the bottom
AuthorizationHeader (apiKey)
section, for the Value field, enterBearer <your token value>
and Authorize. - You are now logged in as your tenant/wallet/agent.
- Scroll to GET /tenant, expand, Try it out and Execute.
- These are your tenant's details. Only you are authorized to fetch your tenant data.
For Tenant Line of Business Integration, see more steps in the tenant-lob demo readme.