forked from hyperledger/aries-cloudagent-python
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request hyperledger#2230 from usingtechnology/feature/play…
…ground-demo stand up multiple agents (single and multi) for local development and testing
- Loading branch information
Showing
14 changed files
with
1,212 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
NGROK_AUTHTOKEN= | ||
|
||
ACAPY_GENESIS_URL=http://test.bcovrin.vonx.io/genesis | ||
|
||
# | ||
# database | ||
# | ||
POSTGRESQL_HOST=wallet-db | ||
POSTGRESQL_PORT=5432 | ||
POSTGRESQL_USER=postgres | ||
POSTGRESQL_PASSWORD=development | ||
POSTGRESQL_ADMIN_USER=postgres | ||
POSTGRESQL_ADMIN_PASSWORD=development | ||
|
||
# | ||
# wallet storage configuration | ||
# | ||
ACAPY_WALLET_STORAGE_CONFIG={"url":"${POSTGRESQL_HOST}:${POSTGRESQL_PORT}","wallet_scheme":"DatabasePerWallet"} | ||
ACAPY_WALLET_STORAGE_CREDS={"account":"${POSTGRESQL_USER}","password":"${POSTGRESQL_PASSWORD}","admin_account":"${POSTGRESQL_ADMIN_USER}","admin_password":"${POSTGRESQL_ADMIN_PASSWORD}"} | ||
|
||
# | ||
# logging | ||
# | ||
ACAPY_LOG_LEVEL=INFO | ||
RUST_LOG=ERROR | ||
|
||
# | ||
# tracing - uncomment in each service if needed | ||
# | ||
ACAPY_TRACE=0 | ||
ACAPY_TRACE_TARGET=http://logstash:9700/ | ||
ACAPY_TRACE_TAG=acapy.events | ||
ACAPY_TRACE_LABEL=agent.trace | ||
|
||
# | ||
# NGROK Tunnels/Hosts : ensure services and tunnel config match if you change service ports | ||
# tunnels: | ||
# <XXX_TUNNEL_NAME>: | ||
# proto: http | ||
# addr: <XXX_HOST>:<XXX_AGENT_HTTP_IN_PORT> | ||
# | ||
NGROK_FABER_ALICE_HOST=ngrok-faber-alice | ||
NGROK_ACME_MULTI_HOST=ngrok-acme-multi | ||
|
||
# | ||
# Faber : faber-agent 9001/9011 | ||
# | ||
FABER_TUNNEL_HOST=${NGROK_FABER_ALICE_HOST} | ||
FABER_TUNNEL_NAME=faber | ||
FABER_HOST=faber-agent | ||
FABER_AGENT_LABEL=faber | ||
FABER_AGENT_HTTP_IN_PORT=9001 | ||
FABER_AGENT_HTTP_ADMIN_PORT=9011 | ||
FABER_AGENT_ARG_FILE=./configs/singletenant-auto-accept.yml | ||
FABER_ACAPY_ENDPOINT=http://${FABER_HOST}:${FABER_AGENT_HTTP_IN_PORT} | ||
FABER_ACAPY_WALLET_STORAGE_CONFIG=${ACAPY_WALLET_STORAGE_CONFIG} | ||
FABER_ACAPY_WALLET_STORAGE_CREDS=${ACAPY_WALLET_STORAGE_CREDS} | ||
FABER_ACAPY_WALLET_NAME=faber_wallet | ||
FABER_ACAPY_WALLET_KEY=changeme | ||
FABER_ACAPY_GENESIS_URL=${ACAPY_GENESIS_URL} | ||
FABER_ACAPY_LOG_LEVEL=${ACAPY_LOG_LEVEL} | ||
FABER_RUST_LOG=${RUST_LOG} | ||
FABER_POSTGRESQL_HOST=${POSTGRESQL_HOST} | ||
FABER_POSTGRESQL_PORT=${POSTGRESQL_PORT} | ||
# tracing... | ||
FABER_ACAPY_TRACE=${ACAPY_TRACE} | ||
FABER_ACAPY_TRACE_TARGET=${ACAPY_TRACE_TARGET} | ||
FABER_ACAPY_TRACE_TAG=${ACAPY_TRACE_TAG} | ||
FABER_ACAPY_TRACE_LABEL=faber.agent.trace | ||
|
||
# | ||
# Alice : alice-agent - 9002/9012 | ||
# | ||
ALICE_TUNNEL_HOST=${NGROK_FABER_ALICE_HOST} | ||
ALICE_TUNNEL_NAME=alice | ||
ALICE_HOST=alice-agent | ||
ALICE_AGENT_LABEL=alice | ||
ALICE_AGENT_HTTP_IN_PORT=9002 | ||
ALICE_AGENT_HTTP_ADMIN_PORT=9012 | ||
ALICE_AGENT_ARG_FILE=./configs/singletenant-auto-accept.yml | ||
ALICE_ACAPY_ENDPOINT=http://${ALICE_HOST}:${ALICE_AGENT_HTTP_IN_PORT} | ||
ALICE_ACAPY_WALLET_STORAGE_CONFIG=${ACAPY_WALLET_STORAGE_CONFIG} | ||
ALICE_ACAPY_WALLET_STORAGE_CREDS=${ACAPY_WALLET_STORAGE_CREDS} | ||
ALICE_ACAPY_WALLET_NAME=alice_wallet | ||
ALICE_ACAPY_WALLET_KEY=changeme | ||
ALICE_ACAPY_GENESIS_URL=${ACAPY_GENESIS_URL} | ||
ALICE_ACAPY_LOG_LEVEL=${ACAPY_LOG_LEVEL} | ||
ALICE_RUST_LOG=${RUST_LOG} | ||
ALICE_POSTGRESQL_HOST=${POSTGRESQL_HOST} | ||
ALICE_POSTGRESQL_PORT=${POSTGRESQL_PORT} | ||
# tracing... | ||
ALICE_ACAPY_TRACE=${ACAPY_TRACE} | ||
ALICE_ACAPY_TRACE_TARGET=${ACAPY_TRACE_TARGET} | ||
ALICE_ACAPY_TRACE_TAG=${ACAPY_TRACE_TAG} | ||
ALICE_ACAPY_TRACE_LABEL=alice.agent.trace | ||
|
||
# | ||
# Acme : acme-agent - 9003/9013 | ||
# | ||
ACME_TUNNEL_HOST=${NGROK_ACME_MULTI_HOST} | ||
ACME_TUNNEL_NAME=acme | ||
ACME_HOST=acme-agent | ||
ACME_AGENT_LABEL=acme | ||
ACME_AGENT_HTTP_IN_PORT=9003 | ||
ACME_AGENT_HTTP_ADMIN_PORT=9013 | ||
ACME_AGENT_ARG_FILE=./configs/singletenant-auto-accept.yml | ||
ACME_ACAPY_ENDPOINT=http://${ACME_HOST}:${ACME_AGENT_HTTP_IN_PORT} | ||
ACME_ACAPY_WALLET_STORAGE_CONFIG=${ACAPY_WALLET_STORAGE_CONFIG} | ||
ACME_ACAPY_WALLET_STORAGE_CREDS=${ACAPY_WALLET_STORAGE_CREDS} | ||
ACME_ACAPY_WALLET_NAME=acme_wallet | ||
ACME_ACAPY_WALLET_KEY=changeme | ||
ACME_ACAPY_GENESIS_URL=${ACAPY_GENESIS_URL} | ||
ACME_ACAPY_LOG_LEVEL=${ACAPY_LOG_LEVEL} | ||
ACME_RUST_LOG=${RUST_LOG} | ||
ACME_POSTGRESQL_HOST=${POSTGRESQL_HOST} | ||
ACME_POSTGRESQL_PORT=${POSTGRESQL_PORT} | ||
# tracing... | ||
ACME_ACAPY_TRACE=${ACAPY_TRACE} | ||
ACME_ACAPY_TRACE_TARGET=${ACAPY_TRACE_TARGET} | ||
ACME_ACAPY_TRACE_TAG=${ACAPY_TRACE_TAG} | ||
ACME_ACAPY_TRACE_LABEL=acme.agent.trace | ||
|
||
# | ||
# Multi : multi-agent - 9004/9014 | ||
# | ||
MULTI_TUNNEL_HOST=${NGROK_ACME_MULTI_HOST} | ||
MULTI_TUNNEL_NAME=multi | ||
MULTI_HOST=multi-agent | ||
MULTI_AGENT_LABEL=multi | ||
MULTI_AGENT_HTTP_IN_PORT=9004 | ||
MULTI_AGENT_HTTP_ADMIN_PORT=9014 | ||
MULTI_AGENT_ARG_FILE=./configs/multitenant-auto-accept.yml | ||
MULTI_ACAPY_ENDPOINT=http://${MULTI_HOST}:${MULTI_AGENT_HTTP_IN_PORT} | ||
MULTI_ACAPY_WALLET_STORAGE_CONFIG=${ACAPY_WALLET_STORAGE_CONFIG} | ||
MULTI_ACAPY_WALLET_STORAGE_CREDS=${ACAPY_WALLET_STORAGE_CREDS} | ||
MULTI_ACAPY_WALLET_NAME=multi_wallet | ||
MULTI_ACAPY_WALLET_KEY=changeme | ||
MULTI_ACAPY_GENESIS_URL=${ACAPY_GENESIS_URL} | ||
MULTI_ACAPY_LOG_LEVEL=${ACAPY_LOG_LEVEL} | ||
MULTI_RUST_LOG=${RUST_LOG} | ||
MULTI_POSTGRESQL_HOST=${POSTGRESQL_HOST} | ||
MULTI_POSTGRESQL_PORT=${POSTGRESQL_PORT} | ||
# tracing... | ||
MULTI_ACAPY_TRACE=${ACAPY_TRACE} | ||
MULTI_ACAPY_TRACE_TARGET=${ACAPY_TRACE_TARGET} | ||
MULTI_ACAPY_TRACE_TAG=${ACAPY_TRACE_TAG} | ||
MULTI_ACAPY_TRACE_LABEL=multi.agent.trace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
FROM ghcr.io/hyperledger/aries-cloudagent-python:py3.9-indy-1.16.0-0.8.1 | ||
|
||
USER root | ||
|
||
RUN mkdir -p /acapy-agent | ||
WORKDIR /acapy-agent | ||
|
||
ADD https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 /usr/bin/jq | ||
RUN chmod +x /usr/bin/jq | ||
|
||
USER $user | ||
|
||
# Copy the necessary files | ||
COPY ./start.sh start.sh | ||
COPY ./configs configs | ||
|
||
RUN chmod +x start.sh && \ | ||
aca-py --version > ./acapy-version.txt | ||
|
||
ENTRYPOINT ["bash", "./start.sh"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
# ACA-Py Playground | ||
|
||
This directory contains scripts to run several ACA-Py agents in various configurations for demonstration, development and testing scenarios. The agents are using Postgres (15) database storage (`askar`, `DatabasePerWallet`) and are running without security (`--admin-insecure-mode`). | ||
|
||
The inspiration for this playground was testing mediation and the differences between single-tenant and multi-tenant modes. These scripts allowed the developer to stand up 3 single-tenant agents and 1 multi-tenant agent and run various scenarios (see [scripts](./scripts) - for some basic examples). Running in `--admin-insecure-mode` simplifies creating tenants in multi-tenant mode and eliminates the need for adding headers for calls in single-tenant mode. | ||
|
||
- faber-agent | ||
- alice-agent | ||
- acme-agent | ||
- multi-agent (the multi-tenant agent) | ||
|
||
By default, all the agents share the same Postgres Database Service (version 15) and all use [Ngrok](https://ngrok.com) for publicly accessible URLs. | ||
|
||
## Dependencies | ||
|
||
Docker Compose version v2.17.2 | ||
|
||
## Agent Configuration | ||
|
||
There are two simple configurations provided: | ||
|
||
- [`singletenant-auto-accept.yml`](./configs/singletenant-auto-accept.yml) | ||
- [`multitenant-auto-accept.yml`](./configs/multitenant-auto-accept.yml) | ||
|
||
These configuration files are provided to the ACA-Py start command via the `AGENT_ARG_FILE` environment variable. See [`.env`](./.env.sample) and [`start.sh`](./start.sh). | ||
|
||
### Dockerfile and start.sh | ||
|
||
[`Dockerfile.acapy`](./Dockerfile.acapy) assembles the image to run. Currently based on [Aries Cloudagent Python 0.8.1](ghcr.io/hyperledger/aries-cloudagent-python:py3.9-indy-1.16.0-0.8.1), we need [jq](https://stedolan.github.io/jq/) to setup (or not) the ngrok tunnel and execute the Aca-py start command - see [`start.sh`](./start.sh). You may note that the start command is very sparse, additional configuration is done via environment variables in the [docker compose file](./docker-compose.yml). | ||
|
||
### ngrok | ||
|
||
Note that ngrok allows 2 tunnels per instance with an unpaid account. We have broken up the 4 default services into 2 ngrok services and tunnel configurations. If you need to alter port numbers for your agent services, you will have to update the ngrok tunnel files. | ||
|
||
- [ngrok-faber-alice](./ngrok-faber-alice.yml) | ||
- [ngrok-acme-multi](./ngrok-acme-multi.yml) | ||
|
||
If you have a paid account, you can set the `NGROK_AUTHTOKEN` environment variable. See below. | ||
|
||
### .env | ||
|
||
Additional configuration (ie. port numbers for the services, `NGROK_AUTHTOKEN`, ...) are done in the [`.env`](./.env.sample) file. Change as needed and ensure ngrok configuration matches. | ||
|
||
```shell | ||
cp .env.sample .env | ||
``` | ||
|
||
## Running the Playground | ||
|
||
To run the agents in this repo, open a command shell in this directory and run: | ||
|
||
- to build the containers: | ||
|
||
```bash | ||
docker compose build | ||
``` | ||
|
||
- to run the agents: | ||
|
||
```bash | ||
docker compose up | ||
``` | ||
|
||
- to shut down: | ||
|
||
```bash | ||
docker compose stop | ||
docker compose rm -f | ||
``` | ||
|
||
This will leave the agents wallet data, so if you restart the agent it will maintain any created data. | ||
|
||
- to remove the wallet data: | ||
|
||
```bash | ||
docker compose down -v --remove-orphans | ||
``` | ||
|
||
- individual services can be started by specifying the service name(s): | ||
|
||
```bash | ||
docker compose up multi-agent | ||
docker compose up faber-agent alice-agent | ||
``` | ||
|
||
You can now access the agent Admin APIs via Swagger at: | ||
|
||
- faber: [http://localhost:9011/api/doc#](http://localhost:9011/api/doc#) | ||
- alice: [http://localhost:9012/api/doc#](http://localhost:9012/api/doc#) | ||
- acme: [http://localhost:9013/api/doc#](http://localhost:9013/api/doc#) | ||
- multi: [http://localhost:9014/api/doc#](http://localhost:9014/api/doc#) | ||
|
||
## Scripts | ||
|
||
While having the Swagger Admin API is excellent, you may need to do something more complex than a single API call. You may need to see how agents with varying capabilities interact or validate that single-tenant and multi-tenant work the same. Jumping around from multiple browser tabs and cutting and pasting ids and JSON blocks can quickly grow tiresome. | ||
|
||
A few Python (3.9) [scripts](./scripts) are provided as examples of what you may do once your agents are up and running. | ||
|
||
```shell | ||
cd scripts | ||
pip install -r requirements.txt | ||
python ping_agents.py | ||
``` | ||
|
||
The [`ping_agents`](./scripts/ping_agents.py) script is a trivial example using the ACA-Py API to create tenants in the multi-agent instance and interact between the agents. We create and receive invitations and ping each other. | ||
|
||
The [`mediator_ping_agents`](./scripts/mediator_ping_agents) script requires that you have a mediator service running and have the mediator's invitation URL. See [Aries Mediator Service](https://github.com/hyperledger/aries-mediator-service) for standing up a local instance and how to find the invitation URL. In this script, each agent requests mediation and we can see the mediator forwarding messages between the agents. | ||
|
||
## Run without NGrok | ||
|
||
[Ngrok](https://ngrok.com) provides a tunneling service and a way to provide a public IP to your locally running instance of ACA-Py. There are restrictions with Ngrok most notably regarding inbound connections. | ||
|
||
```shell | ||
Too many connections! The tunnel session SESSION has violated the rate-limit policy of THRESHOLD connections per minute by initiating COUNT connections in the last SECONDS seconds. Please decrease your inbound connection volume or upgrade to a paid plan for additional capacity. | ||
|
||
ngrok limits the number of inbound connections to your tunnels. Limits are imposed on connections, not requests. If your HTTP clients use persistent connections aka HTTP keep-alive (most modern ones do), you'll likely never hit this limit. ngrok will return a 429 response to HTTP connections that exceed the rate limit. Connections to TCP and TLS tunnels violating the rate limit will be closed without a response. | ||
``` | ||
If you do not require external access to your instance, consider turning NGrok off. NGrok tunnelling can be disabled by changing an environment variable for each service. Set `TUNNEL_NAME` to null/empty, and no tunnel will be created. See [`.env`](.env.sample), [`docker-compose.yml`](./docker-compose.yml) and [`start.sh`](./start.sh), | ||
### update .env | ||
```shell | ||
FABER_TUNNEL_NAME= | ||
``` | ||
### docker-compose.yml | ||
```shell | ||
environment: | ||
- TUNNEL_HOST=${FABER_TUNNEL_HOST} | ||
``` | ||
### start.sh | ||
```shell | ||
# if $TUNNEL_NAME is not empty, grab the service's ngrok route and set our ACAPY_ENDPOINT | ||
if [[ ! -z "$TUNNEL_NAME" ]]; then . . . | ||
``` | ||
Set service value to empty in `.env` that will set the `TUNNEL_NAME` environment variable to empty which will circumvent the use of the tunnel for the service (`ACAPY_ENDPOINT`). | ||
## ELK Stack / Tracing logging | ||
Please see [ELK Stack Readme](../elk-stack/README.md). | ||
You may notice a series of environment variables for each agent service in [.env](./.env.sample) and commented-out network and agent configuration in the [docker compose file](./docker-compose.yml). Check the environment variables and uncomment as needed if wanting to send trace events to ELK. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Connections | ||
debug-connections: true | ||
auto-accept-invites: true | ||
auto-accept-requests: true | ||
auto-ping-connection: true | ||
|
||
# multitenant | ||
multitenant: true | ||
multitenant-admin: true | ||
jwt-secret: changeme |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Connections | ||
debug-connections: true | ||
auto-accept-invites: true | ||
auto-accept-requests: true | ||
auto-ping-connection: true |
Oops, something went wrong.