diff --git a/stack_orchestrator/data/compose/docker-compose-go-nitro-auth.yml b/stack_orchestrator/data/compose/docker-compose-go-nitro-auth.yml new file mode 100644 index 00000000..7fa6a90f --- /dev/null +++ b/stack_orchestrator/data/compose/docker-compose-go-nitro-auth.yml @@ -0,0 +1,113 @@ +version: '3.7' + +services: + go-nitro-alice: + image: cerc/go-nitro:local + hostname: go-nitro-alice + restart: on-failure + depends_on: + - go-nitro-bootnode + environment: + CERC_NITRO_CHAIN_PK: ${CERC_NITRO_CHAIN_PK_ALICE:-888814df89c4358d7ddb3fa4b0213e7331239a80e1f013eaa7b2deca2a41a218} + CERC_NITRO_CHAIN_URL: ${CERC_NITRO_CHAIN_URL:-ws://fixturenet-eth-geth-1:8546} + CERC_NA_ADDRESS: ${CERC_NA_ADDRESS} + CERC_VPA_ADDRESS: ${CERC_VPA_ADDRESS} + CERC_CA_ADDRESS: ${CERC_CA_ADDRESS} + env_file: + - ../config/go-nitro-auth/alice.env + entrypoint: ["bash", "-c", "/app/run-nitro-node.sh"] + volumes: + - nitro_deployment:/app/deployment + - go_nitro_data_alice:/app/data + - ../config/go-nitro/run-nitro-node.sh:/app/run-nitro-node.sh + healthcheck: + test: ["CMD", "nc", "-vz", "localhost", "4006"] + interval: 5s + timeout: 5s + retries: 100 + start_period: 100s + ports: + - "3006" + - "4006" + - "5006" + - "4106" + - "4206" + - "4216" + + go-nitro-bob: + image: cerc/go-nitro:local + hostname: go-nitro-bob + restart: on-failure + depends_on: + - go-nitro-bootnode + environment: + CERC_NITRO_CHAIN_PK: ${CERC_NITRO_CHAIN_PK_BOB:-570b909da9669b2f35a0b1ac70b8358516d55ae1b5b3710e95e9a94395090597} + CERC_NITRO_CHAIN_URL: ${CERC_NITRO_CHAIN_URL:-ws://fixturenet-eth-geth-1:8546} + CERC_NA_ADDRESS: ${CERC_NA_ADDRESS} + CERC_VPA_ADDRESS: ${CERC_VPA_ADDRESS} + CERC_CA_ADDRESS: ${CERC_CA_ADDRESS} + env_file: + - ../config/go-nitro-auth/bob.env + entrypoint: ["bash", "-c", "/app/run-nitro-node.sh"] + volumes: + - nitro_deployment:/app/deployment + - go_nitro_data_bob:/app/data + - ../config/go-nitro/run-nitro-node.sh:/app/run-nitro-node.sh + healthcheck: + test: ["CMD", "nc", "-vz", "localhost", "4007"] + interval: 5s + timeout: 5s + retries: 100 + start_period: 100s + ports: + - "3007" + - "4007" + - "5007" + - "4107" + - "4207" + - "4217" + + go-nitro-bootnode: + image: cerc/go-nitro:local + hostname: go-nitro-bootnode + restart: on-failure + environment: + CERC_NITRO_CHAIN_URL: ${CERC_NITRO_CHAIN_URL:-ws://fixturenet-eth-geth-1:8546} + CERC_NA_ADDRESS: ${CERC_NA_ADDRESS} + CERC_VPA_ADDRESS: ${CERC_VPA_ADDRESS} + CERC_CA_ADDRESS: ${CERC_CA_ADDRESS} + CERC_NITRO_RELAY_ON: true + env_file: + - ../config/go-nitro-auth/bootnode.env + entrypoint: [ "bash", "-c", "/app/run-nitro-node.sh" ] + volumes: + - nitro_deployment:/app/deployment + - go_nitro_data_bootnode:/app/data + - ../config/go-nitro/run-nitro-node.sh:/app/run-nitro-node.sh + healthcheck: + test: [ "CMD", "nc", "-vz", "localhost", "4008" ] + interval: 5s + timeout: 5s + retries: 100 + start_period: 100s + ports: + - "9090" + + nitro-caddy: + image: caddy:2-alpine + restart: always + environment: + CERC_ETH_RPC_ENDPOINT: ${CERC_ETH_RPC_ENDPOINT:-http://fixturenet-eth-geth-1:8545} + volumes: + - ../config/go-nitro-auth/caddy/Caddyfile:/etc/caddy/Caddyfile + ports: + - "5678" + depends_on: + - go-nitro-alice + - go-nitro-bob + +volumes: + go_nitro_data_alice: + go_nitro_data_bob: + go_nitro_data_bootnode: + nitro_deployment: \ No newline at end of file diff --git a/stack_orchestrator/data/config/go-nitro-auth/alice.env b/stack_orchestrator/data/config/go-nitro-auth/alice.env new file mode 100644 index 00000000..2de2a017 --- /dev/null +++ b/stack_orchestrator/data/config/go-nitro-auth/alice.env @@ -0,0 +1,19 @@ +# SET ME! Your on-chain private key. +#CERC_NITRO_CHAIN_PK= + +# Default is CERC_NITRO_CHAIN_PK. +#CERC_NITRO_PK= + +# SET ME! The WebSocket to connect to. +#CERC_NITRO_CHAIN_URL=wss://linea-sepolia.infura.io/ws/v3/ + +CERC_NITRO_AUTH_ON=false +CERC_NITRO_AUTH_RPC_PORT=4006 +CERC_NITRO_AUTH_UI_PORT=4206 +CERC_NITRO_BOOT_PEERS="/dns4/go-nitro-bootnode/tcp/3008/p2p/16Uiu2HAmFYz5YPf3GtkfQsAwYJfDsKSm34U9qAiTwxW7RJUVGMRK" +CERC_NITRO_DURABLE_STORE_FOLDER=/app/data/nitro-store +CERC_NITRO_MSG_PORT=3006 +CERC_NITRO_RPC_PORT=4006 +CERC_NITRO_UI_PORT=4106 +CERC_NITRO_USE_DURABLE_STORE=true +CERC_NITRO_WS_MSG_PORT=5006 \ No newline at end of file diff --git a/stack_orchestrator/data/config/go-nitro-auth/bob.env b/stack_orchestrator/data/config/go-nitro-auth/bob.env new file mode 100644 index 00000000..fc280b54 --- /dev/null +++ b/stack_orchestrator/data/config/go-nitro-auth/bob.env @@ -0,0 +1,19 @@ +# SET ME! Your on-chain private key. +#CERC_NITRO_CHAIN_PK= + +# Default is CERC_NITRO_CHAIN_PK. +#CERC_NITRO_PK= + +# SET ME! The WebSocket to connect to. +#CERC_NITRO_CHAIN_URL=wss://linea-sepolia.infura.io/ws/v3/ + +CERC_NITRO_AUTH_ON=true +CERC_NITRO_AUTH_RPC_PORT=4007 +CERC_NITRO_AUTH_UI_PORT=4207 +CERC_NITRO_BOOT_PEERS="/dns4/go-nitro-bootnode/tcp/3008/p2p/16Uiu2HAmFYz5YPf3GtkfQsAwYJfDsKSm34U9qAiTwxW7RJUVGMRK" +CERC_NITRO_DURABLE_STORE_FOLDER=/app/data/nitro-store +CERC_NITRO_MSG_PORT=3007 +CERC_NITRO_RPC_PORT=4007 +CERC_NITRO_UI_PORT=4107 +CERC_NITRO_USE_DURABLE_STORE=true +CERC_NITRO_WS_MSG_PORT=5007 diff --git a/stack_orchestrator/data/config/go-nitro-auth/bootnode.env b/stack_orchestrator/data/config/go-nitro-auth/bootnode.env new file mode 100644 index 00000000..241fbb0b --- /dev/null +++ b/stack_orchestrator/data/config/go-nitro-auth/bootnode.env @@ -0,0 +1,17 @@ +CERC_NITRO_CHAIN_PK=596db2ac27479cfdf60f708bf64ae44a1c5090e9446cca011d72bc9a59b47d3d +CERC_NITRO_PK=f41086394674cf00a66448c6688295d7330af39f6f38fed89ea023e39382d6a0 + +# The WebSocket to connect to. +#CERC_NITRO_CHAIN_URL=wss://linea-sepolia.infura.io/ws/v3/ + +CERC_NITRO_AUTH_ON=false +CERC_NITRO_AUTH_RPC_PORT=4008 +CERC_NITRO_AUTH_UI_PORT=4208 +CERC_NITRO_DURABLE_STORE_FOLDER=/app/data/nitro-store +CERC_NITRO_MSG_PORT=3008 +CERC_NITRO_RPC_PORT=4008 +CERC_NITRO_UI_PORT=4108 +CERC_NITRO_USE_DURABLE_STORE=true +CERC_NITRO_WS_MSG_PORT=5008 + +CERC_SCRIPT_DEBUG=true \ No newline at end of file diff --git a/stack_orchestrator/data/config/go-nitro-auth/caddy/Caddyfile b/stack_orchestrator/data/config/go-nitro-auth/caddy/Caddyfile new file mode 100644 index 00000000..13a11607 --- /dev/null +++ b/stack_orchestrator/data/config/go-nitro-auth/caddy/Caddyfile @@ -0,0 +1,42 @@ +:5678 { + handle /pay* { + reverse_proxy http://go-nitro-bob:8547 + } + + @eth-key-in-header { + path_regexp /eth/?$ + header X-Api-Key * + } + + handle @eth-key-in-header { + forward_auth go-nitro-bob:8547 { + uri /auth/{header.x-api-key} + } + rewrite * / + reverse_proxy {$CERC_ETH_RPC_ENDPOINT} { + header_up Host {upstream_hostport} + } + } + + @eth-key-in-path { + path_regexp apikey eth/(.+)$ + } + + handle @eth-key-in-path { + forward_auth go-nitro-bob:8547 { + uri /auth/{re.apikey.1} + } + rewrite * / + reverse_proxy {$CERC_ETH_RPC_ENDPOINT} { + header_up Host {upstream_hostport} + } + } + + handle /eth* { + respond "401 Unauthorized" 401 + } + + handle { + reverse_proxy http://go-nitro-alice:4206 + } +} \ No newline at end of file diff --git a/stack_orchestrator/data/config/go-nitro/run-nitro-node.sh b/stack_orchestrator/data/config/go-nitro/run-nitro-node.sh index 249937ef..f0febfb4 100755 --- a/stack_orchestrator/data/config/go-nitro/run-nitro-node.sh +++ b/stack_orchestrator/data/config/go-nitro/run-nitro-node.sh @@ -4,6 +4,11 @@ if [ -n "$CERC_SCRIPT_DEBUG" ]; then set -x fi +if [ -z "$CERC_NITRO_CHAIN_PK" ] || [ -z "$CERC_NITRO_CHAIN_URL" ]; then + echo "You most set both CERC_NITRO_CHAIN_PK and CERC_NITRO_CHAIN_URL." 1>&2 + exit 1 +fi + nitro_addresses_file="/app/deployment/nitro-addresses.json" # Check if CERC_NA_ADDRESS environment variable is set @@ -29,22 +34,86 @@ fi echo "Running Nitro node" -# Assuming CERC_NITRO_CHAIN_URL is of format ://host:port -ws_host=$(echo "$CERC_NITRO_CHAIN_URL" | awk -F '://' '{print $2}' | cut -d ':' -f 1) -ws_port=$(echo "$CERC_NITRO_CHAIN_URL" | awk -F '://' '{print $2}' | cut -d ':' -f 2) - -# Wait till chain endpoint is available -retry_interval=5 -while true; do - nc -z -w 1 "$ws_host" "$ws_port" - - if [ $? -eq 0 ]; then - echo "Chain endpoint is available" - break +if [[ "${CERC_GO_NITRO_WAIT_FOR_CHAIN:-true}" == "true" ]]; then + # Assuming CERC_NITRO_CHAIN_URL is of format ://host[:port][/foo] + ws_host=$(echo "$CERC_NITRO_CHAIN_URL" | awk -F '://' '{print $2}' | cut -d'/' -f 1 | cut -d ':' -f 1) + ws_port=$(echo "$CERC_NITRO_CHAIN_URL" | awk -F '://' '{print $2}' | cut -d'/' -f 1 | cut -d ':' -f 2) + if [[ "$ws_port" == "$ws_host" ]]; then + ws_port="" fi - echo "Chain endpoint not yet available, retrying in $retry_interval seconds..." - sleep $retry_interval -done + # Wait till chain endpoint is available + retry_interval=5 + while true; do + nc -z -w 1 "$ws_host" "${ws_port:-443}" -./nitro -chainurl ${CERC_NITRO_CHAIN_URL} -msgport ${CERC_NITRO_MSG_PORT} -rpcport ${CERC_NITRO_RPC_PORT} -wsmsgport ${CERC_NITRO_WS_MSG_PORT} -publicip "0.0.0.0" -pk ${CERC_NITRO_PK} -chainpk ${CERC_NITRO_CHAIN_PK} -naaddress ${NA_ADDRESS} -vpaaddress ${VPA_ADDRESS} -caaddress ${CA_ADDRESS} -usedurablestore ${CERC_NITRO_USE_DURABLE_STORE} -durablestorefolder ${CERC_NITRO_DURABLE_STORE_FOLDER} -tlscertfilepath "" -tlsKeyFilepath "" + if [ $? -eq 0 ]; then + echo "Chain endpoint is available" + break + fi + + echo "Chain endpoint not yet available, retrying in $retry_interval seconds..." + sleep $retry_interval + done +fi + +if [[ -n "$CERC_NITRO_UI_PORT" ]] && [[ -d "/app-node/packages/nitro-gui/dist" ]]; then + for f in `ls /app-node/packages/nitro-gui/dist/assets/*.js`; do + sed -i "s#\"CERC_RUNTIME_ENV_RPC_HOST\"#\"localhost:${CERC_NITRO_RPC_PORT}\"#g" "$f" + sed -i "s#\"CERC_RUNTIME_ENV_TARGET_URL\"#\"http://localhost:5678\"#g" "$f" + done + http-server -p $CERC_NITRO_UI_PORT /app-node/packages/nitro-gui/dist & +fi + +if [[ -n "$CERC_NITRO_AUTH_UI_PORT" ]] && [[ -d "/app-node/packages/nitro-auth-gui/dist" ]]; then + for f in `ls /app-node/packages/nitro-auth-gui/dist/assets/*.js`; do + sed -i "s#\"CERC_RUNTIME_ENV_RPC_URL\"#\"http://localhost:${CERC_NITRO_RPC_PORT}\"#g" "$f" + sed -i "s#\"CERC_RUNTIME_ENV_TARGET_URL\"#\"http://localhost:5678\"#g" "$f" + done + http-server -p $CERC_NITRO_AUTH_UI_PORT /app-node/packages/nitro-auth-gui/dist & +fi + +if [[ "$CERC_NITRO_AUTH_ON" == "true" ]] && [[ -d "/app-node/packages/nitro-auth/dist" ]]; then + bash -c "sleep 6 && cd /app-node/packages/nitro-auth && yarn start" & +fi + +if [[ "$CERC_NITRO_RELAY_ON" == "true" ]]; then + if [[ ! -f "/app/deployment/relay-node.json" ]]; then + node /usr/local/lib/node_modules/@cerc-io/peer/dist/cli/create-peer.js \ + -f /app/deployment/relay-node.json + fi + DEBUG='laconic:*' node /usr/local/lib/node_modules/@cerc-io/peer/dist/cli/relay.js \ + --host 0.0.0.0 \ + -f /app/deployment/relay-node.json & +fi + +if [[ -z "$CERC_CHAIN_START_BLOCK" ]]; then + if [[ ! -f "/app/deployment/chainstartblock.json" ]]; then + curl --location "$(echo $CERC_NITRO_CHAIN_URL | sed 's/^ws/http/' | sed 's#/ws/#/#')" \ + --header 'Content-Type: application/json' \ + --data '{ + "jsonrpc": "2.0", + "id": 124, + "method": "eth_blockNumber", + "params": [] + }' > /app/deployment/chainstartblock.json + fi + CERC_CHAIN_START_BLOCK=$(printf "%d" `cat /app/deployment/chainstartblock.json | jq -r '.result'`) +fi + +cd /app +./nitro \ + -chainurl ${CERC_NITRO_CHAIN_URL} \ + -msgport ${CERC_NITRO_MSG_PORT} \ + -rpcport ${CERC_NITRO_RPC_PORT} \ + -wsmsgport ${CERC_NITRO_WS_MSG_PORT} \ + -publicip "0.0.0.0" \ + -pk ${CERC_NITRO_PK:-$CERC_NITRO_CHAIN_PK} \ + -chainpk ${CERC_NITRO_CHAIN_PK} \ + -naaddress ${NA_ADDRESS} \ + -vpaaddress ${VPA_ADDRESS} \ + -caaddress ${CA_ADDRESS} \ + -usedurablestore=${CERC_NITRO_USE_DURABLE_STORE} \ + -durablestorefolder ${CERC_NITRO_DURABLE_STORE_FOLDER} \ + -bootpeers "${CERC_NITRO_BOOT_PEERS}" \ + -chainstartblock $CERC_CHAIN_START_BLOCK \ No newline at end of file diff --git a/stack_orchestrator/data/config/nitro-rpc-client/start.sh b/stack_orchestrator/data/config/nitro-rpc-client/start.sh new file mode 100755 index 00000000..c61eb04e --- /dev/null +++ b/stack_orchestrator/data/config/nitro-rpc-client/start.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +CERC_NITRO_RPC_FUND_AMOUNT=${CERC_NITRO_RPC_FUND_AMOUNT:-0} +CERC_NITRO_RPC_HOST_ALICE=${CERC_NITRO_RPC_HOST_ALICE:-go-nitro-alice} +CERC_NITRO_RPC_PORT_ALICE=${CERC_NITRO_RPC_PORT_ALICE:-4006} +CERC_NITRO_USE_TLS=${CERC_NITRO_USE_TLS:-false} +CERC_NITRO_ADDRESS_BOB=${CERC_NITRO_ADDRESS_BOB:-0xe07e314501cc73b24cf45a6577486017300e153c} + + +# Wait till chain endpoint is available +retry_interval=5 +while true; do + nc -z -w 1 "$CERC_NITRO_RPC_HOST_ALICE" "$CERC_NITRO_RPC_PORT_ALICE" + + if [ $? -eq 0 ]; then + echo "Nitro endpoint is available" + break + fi + + echo "Nitro endpoint not yet available, retrying in $retry_interval seconds..." + sleep $retry_interval +done + +if [[ "$CERC_NITRO_RPC_FUND_AMOUNT" -gt 0 ]]; then + nitro-rpc-client -h $CERC_NITRO_RPC_HOST_ALICE \ + -p $CERC_NITRO_RPC_PORT_ALICE \ + -s=$CERC_NITRO_USE_TLS \ + get-all-ledger-channels | \ + jq "[.[] | select(.Status == \"Open\") | select(.Balance.Them == \"$CERC_NITRO_ADDRESS_BOB\")] | first" > \ + /app/deployment/nitro-ledger-channel-alice-to-bob.json + + ledger_channel=$(jq -r '.ID' /app/deployment/nitro-ledger-channel-alice-to-bob.json 2>/dev/null | sed 's/^null$//') + + if [[ -z "${ledger_channel}" ]]; then + echo "Creating new ledger channel ..." + nitro-rpc-client -h $CERC_NITRO_RPC_HOST_ALICE \ + -p $CERC_NITRO_RPC_PORT_ALICE \ + -s=$CERC_NITRO_USE_TLS \ + -n \ + direct-fund --amount $CERC_NITRO_RPC_FUND_AMOUNT $CERC_NITRO_ADDRESS_BOB + + nitro-rpc-client -h $CERC_NITRO_RPC_HOST_ALICE \ + -p $CERC_NITRO_RPC_PORT_ALICE \ + -s=$CERC_NITRO_USE_TLS \ + get-all-ledger-channels | \ + jq "[.[] | select(.Status == \"Open\") | select(.Balance.Them == \"$CERC_NITRO_ADDRESS_BOB\")] | first" > \ + /app/deployment/nitro-ledger-channel-alice-to-bob.json + + ledger_channel=$(jq -r '.ID' /app/deployment/nitro-ledger-channel-alice-to-bob.json) + fi + + nitro-rpc-client -h $CERC_NITRO_RPC_HOST_ALICE \ + -p $CERC_NITRO_RPC_PORT_ALICE \ + -s=$CERC_NITRO_USE_TLS \ + get-payment-channels-by-ledger $ledger_channel > \ + /app/deployment/nitro-payment-channels-alice-to-bob.json + + first_open_channel=$(jq '[.[] | select(.Status == "Open")] | first' /app/deployment/nitro-payment-channels-alice-to-bob.json | sed 's/^null$//') + + if [[ -z "$first_open_channel" ]]; then + echo "Creating new payment channel ..." + nitro-rpc-client -h $CERC_NITRO_RPC_HOST_ALICE \ + -p $CERC_NITRO_RPC_PORT_ALICE \ + -s=$CERC_NITRO_USE_TLS \ + -n \ + virtual-fund --amount $((CERC_NITRO_RPC_FUND_AMOUNT/2)) $CERC_NITRO_ADDRESS_BOB + + nitro-rpc-client -h $CERC_NITRO_RPC_HOST_ALICE \ + -p $CERC_NITRO_RPC_PORT_ALICE \ + -s=$CERC_NITRO_USE_TLS \ + get-payment-channels-by-ledger $ledger_channel > \ + /app/deployment/nitro-payment-channels-alice-to-bob.json + + first_open_channel=$(jq '[.[] | select(.Status == "Open")] | first' /app/deployment/nitro-payment-channels-alice-to-bob.json | sed 's/^null$//') + fi + + echo "" + echo "################################################################" + echo "" + + echo "LEDGER:" + cat /app/deployment/nitro-ledger-channel-alice-to-bob.json | jq + echo "" + echo "" + + echo "PAYMENT:" + cat /app/deployment/nitro-payment-channels-alice-to-bob.json | jq + echo "" + echo "" +fi + +if [ -n "$1" ]; then + exec "$@" + exit $? +fi + +while [ 1 -eq 1 ]; do + sleep 100 +done diff --git a/stack_orchestrator/data/container-build/cerc-go-nitro/Dockerfile b/stack_orchestrator/data/container-build/cerc-go-nitro/Dockerfile index 1d0e31b4..9057d3b0 100644 --- a/stack_orchestrator/data/container-build/cerc-go-nitro/Dockerfile +++ b/stack_orchestrator/data/container-build/cerc-go-nitro/Dockerfile @@ -8,9 +8,30 @@ COPY . . RUN go build -v -o nitro . # Reduce image size -FROM debian:bullseye-slim +FROM node:18-bullseye-slim as builder-node RUN apt-get update -RUN apt-get install -y ca-certificates jq netcat +RUN apt-get install -y make +WORKDIR /app +COPY . . +RUN find . -name 'node_modules' | xargs -n1 rm -rf +RUN find . -name 'dist' | xargs -n1 rm -rf +RUN yarn +WORKDIR /app/packages/nitro-gui +RUN VITE_RPC_HOST=CERC_RUNTIME_ENV_RPC_HOST yarn build +RUN if [ -d /app/packages/nitro-auth-gui ]; then \ + cd /app/packages/nitro-auth-gui && \ + VITE_RPC_URL=CERC_RUNTIME_ENV_RPC_URL VITE_TARGET_URL=CERC_RUNTIME_ENV_TARGET_URL yarn build; \ + fi +WORKDIR /app/packages/nitro-auth +RUN if [ -d /app/packages/nitro-auth ]; then cd /app/packages/nitro-auth && yarn build; fi + +FROM node:18-bullseye-slim +RUN apt-get update +RUN apt-get install -y ca-certificates jq netcat make curl wget RUN rm -rf /var/lib/apt/lists/* +RUN npm install -g http-server +RUN npm config set @cerc-io:registry https://git.vdb.to/api/packages/cerc-io/npm/ +RUN npm install -g @cerc-io/peer WORKDIR /app COPY --from=builder /app/nitro . +COPY --from=builder-node /app /app-node \ No newline at end of file diff --git a/stack_orchestrator/data/container-build/cerc-nitro-rpc-client/Dockerfile b/stack_orchestrator/data/container-build/cerc-nitro-rpc-client/Dockerfile index 2c0d636a..2def6d70 100644 --- a/stack_orchestrator/data/container-build/cerc-nitro-rpc-client/Dockerfile +++ b/stack_orchestrator/data/container-build/cerc-nitro-rpc-client/Dockerfile @@ -4,9 +4,10 @@ RUN apk --update --no-cache add python3 alpine-sdk bash curl jq WORKDIR /app -COPY . . +COPY packages/nitro-rpc-client . RUN echo "Installing dependencies" && \ yarn -RUN cd packages/nitro-rpc-client +RUN yarn build +RUN ln -s /app/bin/nitro-rpc-client.js /bin/nitro-rpc-client diff --git a/stack_orchestrator/data/stacks/go-nitro-auth/README.md b/stack_orchestrator/data/stacks/go-nitro-auth/README.md new file mode 100644 index 00000000..edaa490e --- /dev/null +++ b/stack_orchestrator/data/stacks/go-nitro-auth/README.md @@ -0,0 +1,104 @@ +# go-nitro-auth + +Deploy a stack for demoing Nitro-based auth, using either a local fixturenet (fully self-contained) or remote testnet. + +## Local Fixturenet (Self-Contained) + +### Clone required repositories + +``` +$ laconic-so --stack fixturenet-eth setup-repositories +$ laconic-so --stack go-nitro-auth setup-repositories +``` + +### Build containers + +``` +$ laconic-so --stack fixturenet-eth build-containers +$ laconic-so --stack go-nitro-auth build-containers +``` + +### Create a deployment + +``` +$ laconic-so --stack fixturenet-eth deploy init --output nitro-net.yml +$ laconic-so --stack fixturenet-eth deploy create --spec-file nitro-net.yml --deployment-dir /srv/nitro-net + +$ laconic-so --stack go-nitro-auth deploy init --map-ports-to-host any-same --output nitro-auth.yml +$ laconic-so --stack go-nitro-auth deploy create --spec-file nitro-auth.yml --deployment-dir /srv/nitro-auth + +# Place them both in the same namespace (TODO: support setting the deployment name via --cluster). +$ cp /srv/nitro-net/deployment.yml /srv/nitro-auth/deployment.yml +``` + +### Start the containers + +``` +$ laconic-so deployment --dir /srv/nitro-net up +$ laconic-so deployment --dir /srv/nitro-auth up +``` + +### Open the webapp + +Visit http://localhost:5678 + +## Remote Testnet + +This example will use the Linea Sepolia testnet. + +### Clone required repositories + +``` +$ laconic-so --stack go-nitro-auth setup-repositories +``` + +### Build containers + +``` +$ laconic-so --stack go-nitro-auth build-containers +``` + +### Create a deployment + +``` +$ laconic-so --stack go-nitro-auth deploy init --map-ports-to-host any-same --output nitro-auth.yml +$ laconic-so --stack go-nitro-auth deploy create --spec-file nitro-auth.yml --deployment-dir /srv/nitro-auth +``` + +### Set your keys, contract addresses, etc. + +You must set the private keys for two accounts with funds on the target network, as well as the contract addresses +(if they already exist) or else an account to create them. You must also set the URL to use for WebSocket connections, +eg, `wss://linea-sepolia.infura.io/ws/v3/` + +#### Config + +``` +$ vim /srv/nitro-auth/config.env +# Addresses of existing contracts. +CERC_CA_ADDRESS="0x1Ae815c3e7556e16ceaB6B6d46306C1870EB6d24" +CERC_NA_ADDRESS="0xc453C5E3f304bb545A3Df7bBa02fe6274A056636" +CERC_VPA_ADDRESS="0xA11af80D75b1150631FA78178c94fa451c7172a8" + +# Else the private key of an account and RPC URL to use create them. +CERC_PRIVATE_KEY_DEPLOYER= +CERC_ETH_RPC_ENDPOINT=https://rpc.sepolia.linea.build + +# The WebSocket chain URL. +CERC_NITRO_CHAIN_URL=wss://linea-sepolia.infura.io/ws/v3/ + +# Private key for "Alice" account (payer) +CERC_NITRO_CHAIN_PK_ALICE= + +# Private key for "Bob" account (payee) +CERC_NITRO_CHAIN_PK_BOB= +``` + +### Start the stack +``` +$ laconic-so deployment --dir /srv/nitro-auth up +``` + +### Open the webapp + +Visit http://localhost:5678 diff --git a/stack_orchestrator/data/stacks/go-nitro-auth/stack.yml b/stack_orchestrator/data/stacks/go-nitro-auth/stack.yml new file mode 100644 index 00000000..42b10950 --- /dev/null +++ b/stack_orchestrator/data/stacks/go-nitro-auth/stack.yml @@ -0,0 +1,16 @@ +version: "1.0" +name: go-nitro-auth +description: "Stack to demonstrate payments between various services" +repos: + # for nitro-contracts + - github.com/cerc-io/ts-nitro@v0.1.15 + # for go-nitro and nitro-rpc-client + - github.com/cerc-io/go-nitro@telackey/update +containers: + # nitro + - cerc/nitro-contracts + - cerc/go-nitro + - cerc/nitro-rpc-client +pods: + - nitro-contracts + - go-nitro-auth \ No newline at end of file diff --git a/stack_orchestrator/deploy/webapp/deploy_webapp_from_registry.py b/stack_orchestrator/deploy/webapp/deploy_webapp_from_registry.py index 2cc704ff..f030b735 100644 --- a/stack_orchestrator/deploy/webapp/deploy_webapp_from_registry.py +++ b/stack_orchestrator/deploy/webapp/deploy_webapp_from_registry.py @@ -39,11 +39,12 @@ def process_app_deployment_request( app_deployment_request, deployment_record_namespace, dns_record_namespace, - dns_suffix, + default_dns_suffix, deployment_parent_dir, kube_config, image_registry, force_rebuild, + fqdn_policy, logger ): logger.log("BEGIN - process_app_deployment_request") @@ -56,14 +57,15 @@ def process_app_deployment_request( requested_name = hostname_for_deployment_request(app_deployment_request, laconic) logger.log(f"Determined requested name: {requested_name}") - # HACK if "." in requested_name: - raise Exception("Only unqualified hostnames allowed at this time.") - - fqdn = f"{requested_name}.{dns_suffix}" + if "allow" == fqdn_policy or "preexisting" == fqdn_policy: + fqdn = requested_name + else: + raise Exception(f"{requested_name} is invalid: only unqualified hostnames are allowed.") + else: + fqdn = f"{requested_name}.{default_dns_suffix}" # 3. check ownership of existing dnsrecord vs this request - # TODO: Support foreign DNS dns_crn = f"{dns_record_namespace}/{fqdn}" dns_record = laconic.get_record(dns_crn) if dns_record: @@ -75,7 +77,9 @@ def process_app_deployment_request( logger.log(f"Matched DnsRecord ownership: {matched_owner}") else: raise Exception("Unable to confirm ownership of DnsRecord %s for request %s" % - (dns_record.id, app_deployment_request.id)) + (dns_crn, app_deployment_request.id)) + elif "preexisting" == fqdn_policy: + raise Exception(f"No pre-existing DnsRecord {dns_crn} could be found for request {app_deployment_request.id}.") # 4. get build and runtime config from request env_filename = None @@ -191,6 +195,7 @@ def dump_known_requests(filename, requests, status="SEEN"): @click.option("--state-file", help="File to store state about previously seen requests.") @click.option("--only-update-state", help="Only update the state file, don't process any requests anything.", is_flag=True) @click.option("--dns-suffix", help="DNS domain to use eg, laconic.servesthe.world") +@click.option("--fqdn-policy", help="How to handle requests with an FQDN: prohibit, allow, preexisting", default="prohibit") @click.option("--record-namespace-dns", help="eg, crn://laconic/dns") @click.option("--record-namespace-deployments", help="eg, crn://laconic/deployments") @click.option("--dry-run", help="Don't do anything, just report what would be done.", is_flag=True) @@ -201,7 +206,7 @@ def dump_known_requests(filename, requests, status="SEEN"): @click.pass_context def command(ctx, kube_config, laconic_config, image_registry, deployment_parent_dir, # noqa: C901 request_id, discover, state_file, only_update_state, - dns_suffix, record_namespace_dns, record_namespace_deployments, dry_run, + dns_suffix, fqdn_policy, record_namespace_dns, record_namespace_deployments, dry_run, include_tags, exclude_tags, force_rebuild, log_dir): if request_id and discover: print("Cannot specify both --request-id and --discover", file=sys.stderr) @@ -220,6 +225,10 @@ def command(ctx, kube_config, laconic_config, image_registry, deployment_parent_ print("--dns-suffix, --record-namespace-dns, and --record-namespace-deployments are all required", file=sys.stderr) sys.exit(2) + if fqdn_policy not in ["prohibit", "allow", "preexisting"]: + print("--fqdn-policy must be one of 'prohibit', 'allow', or 'preexisting'", file=sys.stderr) + sys.exit(2) + # Split CSV and clean up values. include_tags = [tag.strip() for tag in include_tags.split(",") if tag] exclude_tags = [tag.strip() for tag in exclude_tags.split(",") if tag] @@ -334,6 +343,7 @@ def command(ctx, kube_config, laconic_config, image_registry, deployment_parent_ kube_config, image_registry, force_rebuild, + fqdn_policy, logger ) status = "DEPLOYED"