From dbd2e44b6fe86316c8aad2286fdc0d287f4daa8d Mon Sep 17 00:00:00 2001 From: Linus Gasser Date: Tue, 26 Sep 2023 16:37:27 +0200 Subject: [PATCH] Modify scripts for login, creating a form, and voting --- .gitignore | 1 + README.docker.md | 16 +++--- go.mod | 2 + scripts/README.md | 18 +++++++ scripts/init_dela.sh | 15 ------ scripts/local_forms.sh | 44 +++++++++++++++++ scripts/local_login.sh | 6 +++ scripts/local_proxies.sh | 15 ++++++ scripts/local_vars.sh | 9 ++++ scripts/local_votes.sh | 20 ++++++++ scripts/run_local.sh | 74 +++++++++++++++++++--------- web/backend/{README.md => readme.md} | 21 +++++++- 12 files changed, 194 insertions(+), 47 deletions(-) create mode 100644 scripts/README.md create mode 100755 scripts/local_forms.sh create mode 100755 scripts/local_login.sh create mode 100755 scripts/local_proxies.sh create mode 100644 scripts/local_vars.sh create mode 100755 scripts/local_votes.sh rename web/backend/{README.md => readme.md} (75%) diff --git a/.gitignore b/.gitignore index 752b0635c..361116e9b 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ deb-package/dist/** dela/ bin/ nodes/ +cookies.txt diff --git a/README.docker.md b/README.docker.md index bc66a08f9..b14736199 100644 --- a/README.docker.md +++ b/README.docker.md @@ -43,27 +43,29 @@ And then copy the two lines to the `.env` file. There are two Docker Compose file you may use: -* `docker-compose/docker-compose.yml` for the preprod version, or +* `docker-compose/docker-compose.yml` for the currently released version, or * `docker-compose/docker-compose.debug.yml` for the development/debugging version -You run +You can either run ``` export COMPOSE_FILE= ``` -The preprod version will create an environment without any debugging tools that's as close as possible to a real environment. -It is meant to be used to test the `main` branch before deploying it to production. Use the development/debugging version -for setting up your local development environment. +or pass the `-f/--file ` argument to choose between +the files. + +Using the currently released version will pull the images from the GitHub container registry. + +If you instead use the development/debugging version the images will be build locally and you can debug your developments. Run ``` -docker compose build docker compose up ``` -to set up the environment. +(possibly with the `-f/--file` argument) to set up the environment. /!\ Any subsequent `docker compose` commands must be run with `COMPOSE_FILE` being set to the Docker Compose file that defines the current environment. diff --git a/go.mod b/go.mod index 9189fbb70..84db3ed80 100644 --- a/go.mod +++ b/go.mod @@ -48,3 +48,5 @@ require ( google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) + +replace go.dedis.ch/dela => ./dela \ No newline at end of file diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 000000000..80ef9ba27 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,18 @@ +# Scripts for running D-voting locally + +The following scripts are available to configure and run D-voting locally. They should be called in this order: + +- `run_local.sh` - sets up a complete system with 4 nodes, the db, the authentication-server, + and the frontend. + The script runs only the DB in a docker environment, all the rest is run directly on the machine. + This allows for easier debugging and faster testing of the different parts, mainly the + authentication-server, but also the frontend. + For debugging Dela, you still need to re-run everything. +- `local_proxies.sh` needs to be run once after the `run_local.sh` script +- `local_forms.sh` creates a new form and prints its ID +- `local_votes.sh` casts the given number of votes. THE ENCRYPTION IS WRONG AND WILL NOT WORK. But it allows to test + missing votes + +The following script is only called by the other scripts: + +- `local_login.sh` logs into the frontend and stores the cookie diff --git a/scripts/init_dela.sh b/scripts/init_dela.sh index b5ba25879..542ca3059 100755 --- a/scripts/init_dela.sh +++ b/scripts/init_dela.sh @@ -2,43 +2,29 @@ MEMBERS=""; -if [ -z "$COMPOSE_FILE" ]; then - echo "'COMPOSE_FILE' variable not set"; - exit 1; -fi - - # share the certificate -echo "[1/4] add nodes to network"; for container in dela-worker-1 dela-worker-2 dela-worker-3; do TOKEN_ARGS=$(docker compose exec dela-worker-0 /bin/bash -c 'LLVL=error dvoting --config /data/node minogrpc token'); - echo "generated token for $container"; docker compose exec "$container" dvoting --config /data/node minogrpc join --address //dela-worker-0:2000 $TOKEN_ARGS; - echo "$container joined network"; done # create a new chain with the nodes -echo "[2/4] create a new chain"; for container in dela-worker-0 dela-worker-1 dela-worker-2 dela-worker-3; do # add node to the chain MEMBERS="$MEMBERS --member $(docker compose exec $container /bin/bash -c 'LLVL=error dvoting --config /data/node ordering export')"; done docker compose exec dela-worker-0 dvoting --config /data/node ordering setup $MEMBERS; -echo "created new chain"; # authorize the signer to handle the access contract on each node -echo "[3/4] allow nodes to access contracts on each other"; for signer in dela-worker-0 dela-worker-1 dela-worker-2 dela-worker-3; do IDENTITY=$(docker compose exec "$signer" crypto bls signer read --path /data/node/private.key --format BASE64_PUBKEY); for node in dela-worker-0 dela-worker-1 dela-worker-2 dela-worker-3; do docker compose exec "$node" dvoting --config /data/node access add --identity "$IDENTITY"; - echo "$node allowed $signer to access contract on it"; done done # update the access contract -echo "[4/4] grant permissions to update contract"; for container in dela-worker-0 dela-worker-1 dela-worker-2 dela-worker-3; do IDENTITY=$(docker compose exec "$container" crypto bls signer read --path /data/node/private.key --format BASE64_PUBKEY); docker compose exec dela-worker-0 dvoting --config /data/node pool add\ @@ -55,5 +41,4 @@ for container in dela-worker-0 dela-worker-1 dela-worker-2 dela-worker-3; do --args $IDENTITY\ --args access:command\ --args GRANT - echo "$container has been granted permission to update contract"; done diff --git a/scripts/local_forms.sh b/scripts/local_forms.sh new file mode 100755 index 000000000..ad29d77b3 --- /dev/null +++ b/scripts/local_forms.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) +. "$SCRIPT_DIR/local_login.sh" + +echo "add form" +RESP=$(curl -sk "$FRONTEND_URL/api/evoting/forms" -X POST -H 'Content-Type: application/json' -b cookies.txt --data-raw '{"Configuration":{"MainTitle":"{\"en\":\"Colours\",\"fr\":\"\",\"de\":\"\"}","Scaffold":[{"ID":"5DRhKsY2","Title":"Colours","TitleFr":"","TitleDe":"","Order":["d0mSUfpv"],"Ranks":[],"Selects":[{"ID":"d0mSUfpv","Title":"{\"en\":\"RGB\",\"fr\":\"\",\"de\":\"\"}","TitleDe":"","TitleFr":"","MaxN":1,"MinN":1,"Choices":["{\"en\":\"Red\"}","{\"en\":\"Green\"}","{\"en\":\"Blue\"}"],"ChoicesMap":{},"Hint":"{\"en\":\"\",\"fr\":\"\",\"de\":\"\"}","HintFr":"","HintDe":""}],"Texts":[],"Subjects":[]}]}}') +FORMID=$(echo "$RESP" | jq -r .FormID) +echo "add permissions - it's normal to have a timeout error after this command" +curl -k "$FRONTEND_URL/api/evoting/authorizations" -X PUT -H 'Content-Type: application/json' -b cookies.txt --data "$(jq -cn --arg FormID $FORMID '$ARGS.named')" -m 1 + +echo "initialize nodes" +curl -k "$FRONTEND_URL/api/evoting/services/dkg/actors" -X POST -H 'Content-Type: application/json' -b cookies.txt --data "$(jq -cn --arg FormID $FORMID --arg Proxy http://localhost:2001 '$ARGS.named')" +curl -k "$FRONTEND_URL/api/evoting/services/dkg/actors" -X POST -H 'Content-Type: application/json' -b cookies.txt --data "$(jq -cn --arg FormID $FORMID --arg Proxy http://localhost:2003 '$ARGS.named')" +curl -k "$FRONTEND_URL/api/evoting/services/dkg/actors" -X POST -H 'Content-Type: application/json' -b cookies.txt --data "$(jq -cn --arg FormID $FORMID --arg Proxy http://localhost:2005 '$ARGS.named')" +curl -k "$FRONTEND_URL/api/evoting/services/dkg/actors" -X POST -H 'Content-Type: application/json' -b cookies.txt --data "$(jq -cn --arg FormID $FORMID --arg Proxy http://localhost:2007 '$ARGS.named')" + +echo "set node up" +curl -k "$FRONTEND_URL/api/evoting/services/dkg/actors/$FORMID" -X PUT -H 'Content-Type: application/json' -b cookies.txt --data-raw '{"Action":"setup","Proxy":"http://localhost:2001"}' + +echo "open election" +sleep 8 +curl -k "$FRONTEND_URL/api/evoting/forms/$FORMID" -X PUT -b cookies.txt -H 'Content-Type: application/json' --data-raw '{"Action":"open"}' >/dev/null +echo "Form with ID $FORMID has been set up" + +echo "Adding $SCIPER_ADMIN to voters" +tmpfile=$(mktemp) +echo -n "$SCIPER_ADMIN" > "$tmpfile" +(cd web/backend && npx ts-node src/cli.ts addVoters --election-id $FORMID --scipers-file "$tmpfile" ) +echo "Restarting backend to take into account voters" +"$SCRIPT_DIR/run_local.sh" backend +. "$SCRIPT_DIR/local_login.sh" + +if [[ "$1" ]]; then + echo "Casting $1 votes" + for i in $(seq $1); do + echo "Casting vote #$i" + curl -sk "$FRONTEND_URL/api/evoting/forms/$FORMID/vote" -X POST -H 'Content-Type: Application/json' \ + -H "Origin: $FRONTEND_URL" -b cookies.txt \ + --data-raw '{"Ballot":[{"K":[54,152,33,11,201,233,212,157,204,176,136,138,54,213,239,198,79,55,71,26,91,244,98,215,208,239,48,253,195,53,192,94],"C":[105,121,87,164,68,242,166,194,222,179,253,231,213,63,34,66,212,41,214,175,178,83,229,156,255,38,55,234,168,222,81,185]}],"UserID":null}' \ + >/dev/null + sleep 1 + done +fi diff --git a/scripts/local_login.sh b/scripts/local_login.sh new file mode 100755 index 000000000..6ab1435a8 --- /dev/null +++ b/scripts/local_login.sh @@ -0,0 +1,6 @@ +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +. "$SCRIPT_DIR/local_vars.sh" + +if ! [[ -f cookies.txt ]]; then + curl -k "$FRONTEND_URL/api/get_dev_login" -X GET -c cookies.txt -o /dev/null -s +fi diff --git a/scripts/local_proxies.sh b/scripts/local_proxies.sh new file mode 100755 index 000000000..af64ce0b7 --- /dev/null +++ b/scripts/local_proxies.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +. "$SCRIPT_DIR/local_login.sh" + +echo "adding proxies"; + +for node in $( seq 0 3 ); do + NodeAddr="localhost:$(( 2000 + node * 2))" + ProxyAddr="localhost:$(( 2001 + node * 2))" + echo -n "Adding proxy for node $(( node + 1)): " + curl -sk "$FRONTEND_URL/api/proxies/" -X POST -H 'Content-Type: application/json' -b cookies.txt \ + --data-raw "{\"NodeAddr\":\"$LocalAddr\",\"Proxy\":\"$ProxyAddr\"}" + echo +done diff --git a/scripts/local_vars.sh b/scripts/local_vars.sh new file mode 100644 index 000000000..c466657c1 --- /dev/null +++ b/scripts/local_vars.sh @@ -0,0 +1,9 @@ +export SCIPER_ADMIN=100100 +export DATABASE_USERNAME=dvoting +export DATABASE_PASSWORD=postgres +export FRONTEND_URL="http://localhost:3000" +export DELA_NODE_URL="http://localhost:2001" +export BACKEND_HOST="localhost" +export BACKEND_PORT="6000" +export SESSION_SECRET="session secret" +export REACT_APP_NOMOCK=on diff --git a/scripts/local_votes.sh b/scripts/local_votes.sh new file mode 100755 index 000000000..c48a90d03 --- /dev/null +++ b/scripts/local_votes.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +if ! [[ "$1" && "$2" ]]; then + echo "Syntax is: $0 #votes FORMID" + exit 1 +fi + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) +. "$SCRIPT_DIR/local_login.sh" + +FORMID=$2 +echo "Casting $1 votes to form $FORMID" +for i in $(seq $1); do + echo "Casting vote #$i" + curl -sk "$FRONTEND_URL/api/evoting/forms/$FORMID/vote" -X POST -H 'Content-Type: Application/json' \ + -H "Origin: $FRONTEND_URL" -b cookies.txt \ + --data-raw '{"Ballot":[{"K":[54,152,33,11,201,233,212,157,204,176,136,138,54,213,239,198,79,55,71,26,91,244,98,215,208,239,48,253,195,53,192,94],"C":[105,121,87,164,68,242,166,194,222,179,253,231,213,63,34,66,212,41,214,175,178,83,229,156,255,38,55,234,168,222,81,185]}],"UserID":null}' \ + >/dev/null + sleep 1 +done diff --git a/scripts/run_local.sh b/scripts/run_local.sh index 3b9f63be2..4692b527f 100755 --- a/scripts/run_local.sh +++ b/scripts/run_local.sh @@ -11,6 +11,9 @@ if [[ $(git rev-parse --show-toplevel) != $(pwd) ]]; then exit 1 fi +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +. "$SCRIPT_DIR/local_vars.sh" + asdf_shell() { if ! asdf list "$1" | grep -wq "$2"; then asdf install "$1" "$2" @@ -66,13 +69,13 @@ function init_nodes() { echo "Starting nodes" for n in $(seq 4); do - NODEPORT=$((2000 + n * 2)) - PROXYPORT=$((2001 + n * 2)) + NODEPORT=$((2000 + n * 2 - 2)) + PROXYPORT=$((2001 + n * 2 - 2)) NODEDIR=./nodes/node-$n mkdir -p $NODEDIR rm -f $NODEDIR/node.log dvoting --config $NODEDIR start --postinstall --proxyaddr :$PROXYPORT --proxykey $PUBLIC_KEY \ - --listen tcp://0.0.0.0:$NODEPORT --public http://localhost:$NODEPORT --routing tree --noTLS | + --listen tcp://0.0.0.0:$NODEPORT --public http://localhost:$NODEPORT --routing tree | ts "Node-$n: " | tee $NODEDIR/node.log & done @@ -91,7 +94,7 @@ function init_dela() { for n in $(seq 2 4); do TOKEN_ARGS=$(dvoting --config ./nodes/node-1 minogrpc token) NODEDIR=./nodes/node-$n - dvoting --config $NODEDIR minogrpc join --address //localhost:2002 $TOKEN_ARGS + dvoting --config $NODEDIR minogrpc join --address //localhost:2000 $TOKEN_ARGS done echo " Create a new chain with the nodes" @@ -122,6 +125,8 @@ function init_dela() { --args go.dedis.ch/dela.Evoting --args access:grant_command --args all --args access:identity --args $IDENTITY \ --args access:command --args GRANT done + + rm -f cookies.txt } function kill_db() { @@ -136,12 +141,13 @@ function init_db() { -e POSTGRES_PASSWORD=$DATABASE_PASSWORD -e POSTGRES_USER=$DATABASE_USERNAME \ --name postgres_dvoting -p 5432:5432 postgres:15 >/dev/null - echo "Adding SCIPER to admin" + echo "Adding $SCIPER_ADMIN to admin" (cd web/backend && npx ts-node src/cli.ts addAdmin --sciper $SCIPER_ADMIN | grep -v Executing) } function kill_backend() { pkill -f "web/backend" || true + rm -f cookies.txt } function start_backend() { @@ -150,6 +156,8 @@ function start_backend() { echo "Running backend" (cd web/backend && npm run start-dev | ts "Backend: " &) + + while ! lsof -ln | grep -q :6000; do sleep .1; done } function kill_frontend() { @@ -164,27 +172,45 @@ function start_frontend() { (cd web/frontend && npm run start-dev | ts "Frontend: " &) } -export SCIPER_ADMIN=100100 -export DATABASE_USERNAME=dvoting -export DATABASE_PASSWORD=postgres -export FRONT_END_URL="http://localhost:3000" -export DELA_NODE_URL="http://localhost:2003" -export BACKEND_HOST="localhost" -export BACKEND_PORT="6000" -export SESSION_SECRET="session secret" -export REACT_APP_NOMOCK=on - -if [[ "$1" == "clean" ]]; then +case "$1" in +clean) kill_frontend kill_nodes kill_backend kill_db exit -fi - -build_dela -init_nodes -init_dela -init_db -start_backend -start_frontend + ;; + +build) + build_dela + ;; + +init_nodes) + init_nodes + ;; + +init_dela) + init_dela + ;; + +init_db) + init_db + ;; + +backend) + start_backend + ;; + +frontend) + start_frontend + ;; + +*) + build_dela + init_nodes + init_dela + init_db + start_backend + start_frontend + ;; +esac diff --git a/web/backend/README.md b/web/backend/readme.md similarity index 75% rename from web/backend/README.md rename to web/backend/readme.md index f7daa365e..455e3f7eb 100644 --- a/web/backend/README.md +++ b/web/backend/readme.md @@ -10,7 +10,26 @@ Copy the database credentials from `config.env.template` to `/d-voting/bachend/s ## Generate a keypair -Use the `cli` program to generate the keys: +Here is a small piece of code in Go to generate the keypair for the backend: + +```go +package main + +import ( + "fmt" + "go.dedis.ch/kyber/v3/group/edwards25519" + "go.dedis.ch/kyber/v3/util/key" +) + +func main() { + pair := key.NewKeyPair(&edwards25519.SuiteEd25519{}) + + fmt.Println("PUBLIC_KEY:", pubK) + fmt.Println("PRIVATE_KEY:", privK) +} +``` + +You can also use the `cli` program to generate the keys: ```sh npm run keygen