Skip to content

Commit 56f9ec0

Browse files
authored
Merge pull request openwallet-foundation#3623 from davidchaiken/dc_demo_local_ngrok
AliceGetsAPhone demo works in local docker environment
2 parents 38c1474 + 08eda00 commit 56f9ec0

File tree

5 files changed

+109
-17
lines changed

5 files changed

+109
-17
lines changed

demo/ngrok-wait.sh

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@ if ! [ -z "$TAILS_NGROK_NAME" ]; then
2121
else
2222
echo " not found"
2323
fi
24-
export PUBLIC_TAILS_URL=$NGROK_ENDPOINT
25-
echo "Fetched ngrok tails server endpoint [$PUBLIC_TAILS_URL]"
24+
if [ -z "$NGROK_ENDPOINT" ] || [ "$NGROK_ENDPOINT" = "null" ]; then
25+
# setting PUBLIC_TAILS_URL to null confuses the agent because "null" is a truthy value in Python
26+
echo "PUBLIC_TAILS_URL not set and ngrok not available"
27+
else
28+
export PUBLIC_TAILS_URL=$NGROK_ENDPOINT
29+
echo "Fetched ngrok tails server endpoint [$PUBLIC_TAILS_URL]"
30+
fi
2631
fi
2732

2833
export AGENT_NAME=$1

demo/run_demo

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -221,17 +221,47 @@ else
221221
export RUNMODE="pwd"
222222
fi
223223

224-
# check if ngrok is running on our $AGENT_PORT (don't override if AGENT_ENDPOINT is already set)
225-
if [ -z "$AGENT_ENDPOINT" ] && [ "$RUNMODE" == "docker" ]; then
226-
echo "Trying to detect ngrok service endpoint"
224+
if [ "$RUNMODE" == "docker" ]; then
225+
echo "Checking ngrok service endpoints"
227226
JQ=${JQ:-`which jq`}
228227
if [ -x "$JQ" ]; then
229-
NGROK_ENDPOINT=$(curl --silent localhost:4040/api/tunnels | $JQ -r '.tunnels[0].public_url')
230-
if [ -z "$NGROK_ENDPOINT" ] || [ "$NGROK_ENDPOINT" = "null" ]; then
231-
echo "ngrok not detected for agent endpoint"
232-
else
233-
export AGENT_ENDPOINT=$NGROK_ENDPOINT
234-
echo "Detected ngrok agent endpoint [$AGENT_ENDPOINT]"
228+
NGROK_CURL="curl --silent localhost:4040/api/tunnels"
229+
# check if ngrok is running on our $AGENT_PORT (don't override if AGENT_ENDPOINT is already set)
230+
if [ -z "$AGENT_ENDPOINT" ]; then
231+
# default behavior is to use the first tunnel as the agent endpoint
232+
NGROK_ENDPOINT=$($NGROK_CURL | $JQ -r '.tunnels[0].public_url')
233+
# ngrok does not guarantee the order that the API returns the tunnels,
234+
# so use the named endpoint if it exists.
235+
NAMED_ENDPOINT=$($NGROK_CURL | $JQ -r '.tunnels[] | select(.name=="acapy-agent") | .public_url')
236+
if ! [ -z "$NAMED_ENDPOINT" ]; then
237+
NGROK_ENDPOINT=$NAMED_ENDPOINT # use the endpoint specified by name
238+
fi
239+
if [ -z "$NGROK_ENDPOINT" ] || [ "$NGROK_ENDPOINT" = "null" ]; then
240+
echo "ngrok not detected for agent endpoint"
241+
else
242+
export AGENT_ENDPOINT=$NGROK_ENDPOINT
243+
echo "Detected ngrok agent endpoint [$AGENT_ENDPOINT]"
244+
fi
245+
fi
246+
# check if ngrok is running for webhooks (don't override if WEBHOOK_TARGET is already set)
247+
if [ -z "$WEBHOOK_TARGET"]; then # webhook target not specified, see if ngrok lists it by name
248+
NAMED_ENDPOINT=$($NGROK_CURL | $JQ -r '.tunnels[] | select(.name=="acapy-webhooks") | .public_url')
249+
if [ -z "$NAMED_ENDPOINT" ]; then
250+
echo "ngrok not detected for webhooks endpoint"
251+
else
252+
export WEBHOOK_TARGET=${NAMED_ENDPOINT}/webhooks
253+
echo "Detected ngrok webhooks endpoint [$WEBHOOK_TARGET]"
254+
fi
255+
fi
256+
# check if ngrok is running for tails-server (don't override if TAILS_NETWORK or PUBLIC_TAILS_URL is already set)
257+
if [ -z "$TAILS_NETWORK" ] && [ -z "$PUBLIC_TAILS_URL" ]; then # tails-server not specified, see if ngrok lists it by name
258+
NAMED_ENDPOINT=$($NGROK_CURL | $JQ -r '.tunnels[] | select(.name=="tails-server") | .public_url')
259+
if [ -z "$NAMED_ENDPOINT" ]; then
260+
echo "ngrok not detected for tails-server endpoint"
261+
else
262+
export PUBLIC_TAILS_URL=${NAMED_ENDPOINT}
263+
echo "Detected ngrok tails-server endpoint [$PUBLIC_TAILS_URL]"
264+
fi
235265
fi
236266
else
237267
echo "jq not found"

demo/runners/faber.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -679,12 +679,14 @@ async def main(args):
679679
"/present-proof-2.0/create-request", proof_request_web_request
680680
)
681681
pres_req_id = proof_request["pres_ex_id"]
682-
url = (
683-
"http://"
684-
+ os.getenv("DOCKERHOST").replace(
685-
"{PORT}", str(faber_agent.agent.admin_port + 1)
686-
)
687-
+ "/webhooks/pres_req/"
682+
url = ((os.getenv("WEBHOOK_TARGET") or (
683+
"http://"
684+
+ os.getenv("DOCKERHOST").replace(
685+
"{PORT}", str(faber_agent.agent.admin_port + 1)
686+
)
687+
+ "/webhooks"
688+
))
689+
+ "/pres_req/"
688690
+ pres_req_id
689691
+ "/"
690692
)

docker/Dockerfile.demo

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ ENV ENABLE_PTVSD 0
55
ENV ENABLE_PYDEVD_PYCHARM 0
66
ENV PYDEVD_PYCHARM_HOST "host.docker.internal"
77

8+
# jq is required for the ngrok-wait.sh script
89
RUN mkdir -p bin && curl -L -o bin/jq \
910
https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 && \
1011
chmod ug+x bin/jq
12+
# some versions of docker put .local/bin in the PATH instead of bin
13+
RUN mkdir -p .local/bin && ln -s ../../bin/jq .local/bin/jq
1114

1215
# Copy and install Aries Agent code
1316
RUN pip install --no-cache-dir poetry==2.1.1

docs/demo/AliceGetsAPhone.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ git clone https://github.com/bcgov/indy-tails-server.git
115115
cd indy-tails-server/docker
116116
./manage build
117117
./manage start
118+
./manage logs
118119
```
119120

120121
This will run the required components for the tails server to function and make a tails server available on port 6543.
@@ -128,12 +129,35 @@ ngrok-tails-server_1 | t=2020-05-13T22:51:14+0000 lvl=info msg="started tunnel"
128129

129130
Note the server name in the `url=https://c5789aa0.ngrok.io` parameter (`https://c5789aa0.ngrok.io`) - this is the external url for your tails server. Make sure you use the `https` url!
130131

132+
If you see an "authentication failed" error in the logs like this:
133+
```bash
134+
ngrok-tails-server-1 | ERROR: authentication failed: Usage of ngrok requires a verified account and authtoken.
135+
ngrok-tails-server-1 | ERROR:
136+
ngrok-tails-server-1 | ERROR: Sign up for an account: https://dashboard.ngrok.com/signup
137+
ngrok-tails-server-1 | ERROR: Install your authtoken: https://dashboard.ngrok.com/get-started/your-authtoken
138+
```
139+
then you'll need to follow the links to set up a ngrok account and get an authentication token.
140+
When you have the authtoken, hit CTRL-C to exit from the logs and run the following commands,
141+
replacing `<YOUR AUTHTOKEN>` with the authtoken from ngrok.
142+
```bash
143+
./manage logs # run above
144+
^C
145+
./manage stop
146+
cat >>ngrok.yml
147+
authtoken: <YOUR AUTHTOKEN>
148+
^D
149+
./manage start
150+
./manage logs
151+
```
152+
131153
#### Running in Play with Docker?
132154

133155
Run the same steps on _PWD_ as you would run locally (see above). Open a new shell (click on "ADD NEW INSTANCE") to run the tails server.
134156

135157
Note that with _Play with Docker_ it can be challenging to capture the information you need from the log file as it scrolls by, you can try leaving off the `--events` option when you run the Faber agent to reduce the quantity of information logged to the screen.
136158

159+
Also note that _PWD_ enviroments are insecure. If you enter a ngrok authtoken into a _PWD_ session, you should invalidate (reset) the authtoken as soon as you are done using the environment.
160+
137161
### Run `faber` With Extra Parameters
138162

139163
#### Running locally in a bash shell?
@@ -218,6 +242,12 @@ http://ip10-0-121-4-bquqo816b480a4bfn3kg-8020.direct.play-with-docker.com?c_i=ey
218242

219243
Note that this will use the ngrok endpoint if you are running locally, or your PWD endpoint if you are running on PWD.
220244

245+
When running locally, use the `AGENT_ENDPOINT` environment variable to run the demo so that it puts the public hostname in the QR code:
246+
```bash
247+
AGENT_ENDPOINT=https://abc123.ngrok.io LEDGER_URL=http://test.bcovrin.vonx.io ./run_demo faber
248+
```
249+
See the Connectionless Proof Request section below for a more complete ngrok configuration that also supports the revocation option.
250+
221251
## Issue a Credential
222252

223253
We will use the Faber console to issue a credential. This could be done using the Swagger API as we have done in the connection process. We'll leave that as an exercise to the user.
@@ -321,6 +351,28 @@ Then in the faber demo, select option `2a` - Faber will display a QR code which
321351

322352
Behind the scenes, the Faber controller delivers the proof request information (linked from the url encoded in the QR code) directly to your mobile agent, without establishing and agent-to-agent connection first. If you are interested in the underlying mechanics, you can review the `faber.py` code in the repository.
323353

354+
If you want to use a connectionless proof request with docker running locally, you need to set up ngrok to forward both the agent port (8020) and the webhooks port (8022). If you have a free ngrok account, you need to run a single ngrok agent that forwards all of the necessary ports. Here is an ngrok configuration file that works for this purpose:
355+
```yaml
356+
version: "3"
357+
agent:
358+
authtoken: <YOUR AUTHTOKEN>
359+
tunnels:
360+
acapy-agent:
361+
proto: http
362+
addr: 8020
363+
acapy-webhooks:
364+
proto: http
365+
addr: 8022
366+
tails-server:
367+
addr: 6543
368+
inspect: false
369+
proto: http
370+
```
371+
When using this approach, leave your ngrok authtoken out of the tails-server ngrok.yml file to prevent the tails-server from starting its own ngrok agent. This trick avoids the following error from ngrok:
372+
```bash
373+
ERROR: authentication failed: Your account is limited to 1 simultaneous ngrok agent sessions.
374+
```
375+
324376
## Conclusion
325377
326378
That’s the Faber-Mobile Alice demo. Feel free to play with the Swagger API and experiment further and figure out what an instance of a controller has to do to make things work.

0 commit comments

Comments
 (0)