anastasis-gtk

Demonstrator GUI for Anastasis
Log | Files | Refs | README | LICENSE

test_prepare.sh (17801B)


      1 #!/bin/bash
      2 # Shell script to launch Taler components
      3 # and Anastasis providers for local test
      4 # using TESTKUDOS.
      5 
      6 set -eu
      7 
      8 # Exit, with status code "skip" (no 'real' failure)
      9 function exit_skip() {
     10     echo " SKIP: $1"
     11     exit 77
     12 }
     13 
     14 # Exit, with error message (hard failure)
     15 function exit_fail() {
     16     echo " FAIL: $1"
     17     exit 1
     18 }
     19 
     20 # Cleanup to run whenever we exit
     21 function cleanup()
     22 {
     23     if test -n "${SETUP_PID:-}"
     24     then
     25         kill -TERM "$SETUP_PID" 2> /dev/null || true
     26         wait "$SETUP_PID" 2> /dev/null || true
     27     fi
     28     for n in `jobs -p`
     29     do
     30         kill -SIGCONT $n # in case one provider was suspended
     31         kill $n 2> /dev/null || true
     32     done
     33     rm -rf $CONF $CONF.edited $CONF_4 $CONF_IBAN $WALLET_DB $R1FILE $R2FILE $B1FILE $B2FILE $TMP_DIR
     34     wait
     35 }
     36 
     37 
     38 # Launch the GNU Taler services (bank, exchange, merchant) via
     39 # taler-unified-setup.sh and return once they are up.  Mirrors the setup()
     40 # helper of exchange/src/testing/setup.sh; we cannot source that file as it is
     41 # not installed.  Arguments are passed on to taler-unified-setup.sh.
     42 function taler_setup()
     43 {
     44     local FIFO_DIR
     45     local FIFO_OUT
     46 
     47     # Create a named pipe in a temp directory we own.
     48     FIFO_DIR=`mktemp -d fifo-XXXXXX`
     49     FIFO_OUT="$FIFO_DIR/out"
     50     mkfifo "$FIFO_OUT"
     51     # Open pipe as FD 3 (RW) and FD 4 (RO)
     52     exec 3<> "$FIFO_OUT" 4< "$FIFO_OUT"
     53     rm -rf "$FIFO_DIR"
     54     # '-W' is required for our termination logic to work.
     55     taler-unified-setup.sh -W "$@" >&3 2> taler-unified-setup.log &
     56     SETUP_PID=$!
     57     exec 3>&-
     58     # taler-unified-setup.sh prints "READY:$TESTROOT" once everything is up.
     59     # Read until EOF instead of 'sed -u /READY:/ q' so that we can tell "the
     60     # system came up" apart from "taler-unified-setup.sh died first".
     61     READY=0
     62     while IFS= read -r LINE <&4
     63     do
     64         case "$LINE" in
     65             READY:*)
     66                 READY=1
     67                 break
     68                 ;;
     69         esac
     70     done
     71     exec 4>&-
     72     if test 1 != $READY
     73     then
     74         exit_skip "Failed to launch Taler services, see taler-unified-setup.log"
     75     fi
     76 }
     77 
     78 
     79 # Create a bank account at libeufin-bank.  Prints its payto URI.
     80 # $1 = username, $2 = password, $3 = legal name, $4 = payto URI (optional)
     81 function make_bank_account() {
     82     if test -z "${4:-}"
     83     then
     84         libeufin-bank create-account \
     85                       -c $CONF_IBAN \
     86                       -u "$1" -p "$2" --name "$3" 2>> iban-setup.log
     87     else
     88         libeufin-bank create-account \
     89                       -c $CONF_IBAN \
     90                       -u "$1" -p "$2" --name "$3" --payto_uri "$4" 2>> iban-setup.log
     91     fi
     92 }
     93 
     94 
     95 # Transfer funds from the debit account to the Anastasis account and have
     96 # the Anastasis IBAN helper pick the transfer up.
     97 # $1 = amount ($CURRENCY:X.Y), $2 = subject.
     98 function wire_transfer_to_anastasis() {
     99     curl -s -X POST \
    100          --user "${DEBIT_USERNAME}:${DEBIT_PASSWORD}" \
    101          -H "Content-Type: application/json" \
    102          -d "{\"payto_uri\":\"${PAYTO_CREDIT}&message=$(echo "$2" | jq -sRr @uri)&amount=$1\"}" \
    103          "${IBAN_BANK_URL}accounts/${DEBIT_USERNAME}/transactions" > /dev/null
    104     anastasis-helper-authorization-iban -c $CONF_4 -t -L INFO
    105 }
    106 
    107 
    108 if test "${1:-}" != "free" -a "${1:-}" != "fees"
    109 then
    110     echo "Launch script with either 'free' or 'fees' argument to launch providers with/without fees."
    111     exit 1
    112 fi
    113 
    114 # The provider configurations run helper commands that ship next to this
    115 # script (notably 'scat', the [authorization-email] COMMAND).  anastasis-httpd
    116 # resolves them via PATH, so make sure our own directory is on it.
    117 SRCDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    118 export PATH="$SRCDIR:$PATH"
    119 
    120 export CONF_1="test_anastasis_reducer_1.conf"
    121 export CONF_2="test_anastasis_reducer_2.conf"
    122 export CONF_3="test_anastasis_reducer_3.conf"
    123 if test $1 = 'free'
    124 then
    125     CONF4="test_anastasis_reducer_4_free.conf"
    126 else
    127     CONF4="test_anastasis_reducer_4.conf"
    128 fi
    129 
    130 # Taler configuration file will be edited, so we create one
    131 # from the template.
    132 export CONF=`mktemp test_reducerXXXXXX.conf`
    133 export CONF_4=`mktemp test_reducer_4XXXXXX.conf`
    134 export CONF_IBAN=`mktemp test_reducer_ibanXXXXXX.conf`
    135 cp test_reducer.conf $CONF
    136 cp $CONF4 $CONF_4
    137 
    138 TMP_DIR=`mktemp -d keys-tmp-XXXXXX`
    139 # wallet-core needs an sqlite3 database; a '.json' name selects the
    140 # no-longer-supported in-memory backend.
    141 WALLET_DB=`mktemp test_reducer_walletXXXXXX.sqlite3`
    142 B1FILE=`mktemp test_reducer_stateB1XXXXXX`
    143 B2FILE=`mktemp test_reducer_stateB2XXXXXX`
    144 R1FILE=`mktemp test_reducer_stateR1XXXXXX`
    145 R2FILE=`mktemp test_reducer_stateR2XXXXXX`
    146 IBAN_ACTIVE='false'
    147 SETUP_PID=''
    148 
    149 # Install cleanup handler (except for kill -9)
    150 trap cleanup EXIT
    151 
    152 # Check we can actually run
    153 if test $1 = 'fees'
    154 then
    155     echo -n "Testing for taler"
    156     taler-exchange-httpd -h > /dev/null || exit_skip " taler-exchange required"
    157     taler-merchant-httpd -h > /dev/null || exit_skip " taler-merchant required"
    158     # note: 'taler-unified-setup.sh -h' exits non-zero (its exit trap wins)
    159     command -v taler-unified-setup.sh > /dev/null || exit_skip " taler-unified-setup.sh required"
    160     echo " FOUND"
    161 
    162     echo -n "Testing for libeufin-bank"
    163     libeufin-bank --help >/dev/null </dev/null || exit_skip " MISSING"
    164     echo " FOUND"
    165 
    166     echo -n "Testing for taler-wallet-cli"
    167     taler-wallet-cli -v >/dev/null </dev/null || exit_skip " MISSING"
    168     echo " FOUND"
    169 
    170     echo -n "Testing for jq"
    171     jq --version >/dev/null </dev/null || exit_skip " MISSING"
    172     echo " FOUND"
    173 fi
    174 
    175 echo -n "Testing for anastasis-httpd"
    176 anastasis-httpd -h >/dev/null </dev/null || exit_skip " MISSING"
    177 echo " FOUND"
    178 
    179 echo -n "Initialize anastasis database ..."
    180 # Name of the Postgres database we will use for the script.
    181 # Will be dropped, do NOT use anything that might be used
    182 # elsewhere
    183 TARGET_DB_1=`anastasis-config -c $CONF_1 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"`
    184 TARGET_DB_2=`anastasis-config -c $CONF_2 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"`
    185 TARGET_DB_3=`anastasis-config -c $CONF_3 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"`
    186 TARGET_DB_4=`anastasis-config -c $CONF_4 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"`
    187 
    188 dropdb $TARGET_DB_1 >/dev/null 2>/dev/null || true
    189 createdb $TARGET_DB_1 || exit_skip "Could not create database $TARGET_DB_1"
    190 anastasis-dbinit -c $CONF_1 2> anastasis-dbinit_1.log
    191 dropdb $TARGET_DB_2 >/dev/null 2>/dev/null || true
    192 createdb $TARGET_DB_2 || exit_skip "Could not create database $TARGET_DB_2"
    193 anastasis-dbinit -c $CONF_2 2> anastasis-dbinit_2.log
    194 dropdb $TARGET_DB_3 >/dev/null 2>/dev/null || true
    195 createdb $TARGET_DB_3 || exit_skip "Could not create database $TARGET_DB_3"
    196 anastasis-dbinit -c $CONF_3 2> anastasis-dbinit_3.log
    197 dropdb $TARGET_DB_4 >/dev/null 2>/dev/null || true
    198 createdb $TARGET_DB_4 || exit_skip "Could not create database $TARGET_DB_4"
    199 anastasis-dbinit -c $CONF_4 2> anastasis-dbinit_4.log
    200 
    201 echo " OK"
    202 
    203 if test $1 = 'fees'
    204 then
    205 
    206     echo -n "Setting up Taler databases ..."
    207     TALER_DB=talercheck
    208     # bank, exchange and merchant share one database here
    209     taler-exchange-config -c $CONF -s exchangedb-postgres -o CONFIG -V postgres:///$TALER_DB
    210     taler-exchange-config -c $CONF -s merchantdb-postgres -o CONFIG -V postgres:///$TALER_DB
    211     taler-exchange-config -c $CONF -s libeufin-bankdb-postgres -o CONFIG -V postgres:///$TALER_DB
    212     taler-exchange-config -c $CONF -s exchange -o KEYDIR -V "${TMP_DIR}/keydir/"
    213     taler-exchange-config -c $CONF -s exchange -o REVOCATION_DIR -V "${TMP_DIR}/revdir/"
    214     DATA_DIR=`taler-exchange-config -f -c $CONF -s PATHS -o TALER_HOME`
    215     rm -rf $DATA_DIR
    216     dropdb $TALER_DB >/dev/null 2>/dev/null || true
    217     createdb $TALER_DB || exit_skip "Could not create database $TALER_DB"
    218     echo " OK"
    219 
    220     # taler-unified-setup.sh launches the bank (libeufin-bank), the exchange
    221     # (including the secmods and the offline key ceremony) and the merchant
    222     # (including taler-merchant-exchangekeyupdate, without which the merchant
    223     # never learns the exchange's keys and refuses to create orders).  It
    224     # writes the configuration it actually uses to "$CONF.edited".
    225     echo "Launching Taler services ..."
    226     taler_setup -c $CONF -L INFO -b -e -m -w -r merchant-exchange-default
    227     echo "Taler services up"
    228 
    229     BANK_PORT=`taler-exchange-config -c $CONF.edited -s libeufin-bank -o PORT`
    230     BANK_URL="http://localhost:${BANK_PORT}/"
    231     EXCHANGE_URL=`taler-exchange-config -c $CONF.edited -s exchange -o BASE_URL`
    232     MERCHANT_PORT=`taler-merchant-config -c $CONF.edited -s merchant -o PORT`
    233     MERCHANT_URL="http://localhost:${MERCHANT_PORT}/"
    234 
    235     echo -n "Configuring merchant instance ..."
    236     # POST to the merchant and fail loudly if it does not like the request.
    237     # $1 = path, $2 = JSON body
    238     function merchant_post() {
    239         local RESP
    240         local CODE
    241 
    242         RESP=`curl -s -w '\n%{http_code}' -H "Content-Type: application/json" \
    243                    -X POST -d "$2" "${MERCHANT_URL}$1"`
    244         CODE=`echo "$RESP" | tail -n1`
    245         case "$CODE" in
    246             20*)
    247                 ;;
    248             *)
    249                 echo " FAILED ($CODE)"
    250                 echo "$RESP" | head -n-1
    251                 exit_fail "merchant rejected POST /$1"
    252                 ;;
    253         esac
    254     }
    255     # The default instance is called "admin" and is served at the root of the
    256     # merchant; the historic /instances/default/ prefix is gone.  'use_stefan'
    257     # is required by the current merchant protocol.
    258     merchant_post management/instances \
    259         '{"auth":{"method":"external"},"id":"admin","name":"default","address":{},"jurisdiction":{},"use_stefan":true,"default_max_wire_fee":"TESTKUDOS:1","default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us":3600000000},"default_pay_delay":{"d_us":3600000000}}'
    260     # 'fortythree' is one of the accounts taler-unified-setup.sh registers
    261     merchant_post private/accounts \
    262         '{"payto_uri":"payto://x-taler-bank/localhost/fortythree?receiver-name=Forty+Three"}'
    263     echo " OK"
    264 
    265     echo -n "Preparing wallet"
    266     rm -f $WALLET_DB
    267     taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api \
    268                      --expect-success 'withdrawTestBalance' \
    269                      "$(jq -n '
    270     {
    271         amount: "TESTKUDOS:100",
    272         corebankApiBaseUrl: $BANK_URL,
    273         exchangeBaseUrl: $EXCHANGE_URL
    274     }' \
    275     --arg BANK_URL "$BANK_URL" \
    276     --arg EXCHANGE_URL "$EXCHANGE_URL"
    277   )" 2> wallet-withdraw.log >/dev/null
    278     echo -n "."
    279     # the wallet's withdrawal only completes once the exchange has seen the
    280     # incoming wire transfer
    281     taler-exchange-wirewatch -c $CONF.edited -t 2> wirewatch-once.log
    282     echo -n "."
    283     taler-wallet-cli --wallet-db=$WALLET_DB run-until-done 2> wallet-run.log >/dev/null
    284     echo " OK"
    285 
    286     echo -n "Setting up IBAN authentication ..."
    287     # The IBAN challenge needs a bank that speaks IBAN and whose incoming
    288     # transfers Anastasis can see through the taler-revenue API.  That cannot
    289     # be the bank the exchange uses: libeufin-bank serves a single WIRE_TYPE,
    290     # and the exchange side of this test is x-taler-bank.  So we run a second,
    291     # IBAN-typed libeufin-bank for this one authorization method -- it also
    292     # matches the fact that the IBAN challenge is priced in EUR.
    293     IBAN_DB=anastasisibancheck
    294     IBAN_BANK_PORT=8092
    295     IBAN_BANK_URL="http://localhost:${IBAN_BANK_PORT}/"
    296     REASON=""
    297     # both IBANs must pass the checksum: libeufin-bank rejects malformed ones
    298     IBAN_CREDIT="DE44500105175407324931"
    299     IBAN_DEBIT="FR1420041010050500013M02606"
    300     PERSON_CREDIT_NAME="Person Credit"
    301     CREDIT_USERNAME=anastasis-credit-user
    302     CREDIT_PASSWORD=anastasis-credit-password
    303     DEBIT_USERNAME=anastasis-debit-user
    304     DEBIT_PASSWORD=anastasis-debit-password
    305     PAYTO_CREDIT="payto://iban/${IBAN_CREDIT}?receiver-name=Person+Credit"
    306     PAYTO_DEBIT="payto://iban/${IBAN_DEBIT}?receiver-name=Person+Debit"
    307     IBAN_REVENUE_URL="${IBAN_BANK_URL}accounts/${CREDIT_USERNAME}/taler-revenue/"
    308     # the challenge is priced in this currency, e.g. "EUR:1"
    309     IBAN_CURRENCY=`anastasis-config -c $CONF_4 -s authorization-iban -o COST | cut -d: -f1`
    310     cat > $CONF_IBAN <<EOF
    311 # Generated by test_prepare.sh: the "customer's bank" for IBAN challenges.
    312 [PATHS]
    313 TALER_HOME = \${PWD}/test_reducer_home/
    314 TALER_DATA_HOME = \$TALER_HOME/.local/share/taler/
    315 TALER_CONFIG_HOME = \$TALER_HOME/.config/taler/
    316 TALER_CACHE_HOME = \$TALER_HOME/.cache/taler/
    317 TALER_RUNTIME_DIR = \${TMPDIR:-\${TMP:-/tmp}}/taler-system-runtime-\${USER}/
    318 
    319 [libeufin-bank]
    320 CURRENCY = ${IBAN_CURRENCY}
    321 BASE_URL = ${IBAN_BANK_URL}
    322 SERVE = tcp
    323 PORT = ${IBAN_BANK_PORT}
    324 WIRE_TYPE = iban
    325 IBAN_PAYTO_BIC = SANDBOXX
    326 DEFAULT_CUSTOMER_DEBT_LIMIT = ${IBAN_CURRENCY}:200
    327 DEFAULT_ADMIN_DEBT_LIMIT = ${IBAN_CURRENCY}:2000
    328 ALLOW_REGISTRATION = YES
    329 PWD_HASH_CONFIG = { "cost": 4 }
    330 PWD_AUTH_COMPAT = yes
    331 
    332 [libeufin-bankdb-postgres]
    333 CONFIG = postgres:///${IBAN_DB}
    334 EOF
    335     IBAN_ACTIVE='true'
    336     dropdb $IBAN_DB >/dev/null 2>/dev/null || true
    337     if ! createdb $IBAN_DB 2>> iban-setup.log
    338     then
    339         IBAN_ACTIVE='false'
    340     else
    341         libeufin-bank dbinit -c $CONF_IBAN >> iban-setup.log 2>&1
    342         libeufin-bank serve -c $CONF_IBAN >> iban-setup.log 2>&1 &
    343         IBAN_BANK_PID=$!
    344         for n in `seq 1 50`
    345         do
    346             sleep 0.2
    347             wget --tries=1 --timeout=1 "${IBAN_BANK_URL}config" \
    348                  -o /dev/null -O /dev/null >/dev/null && break
    349         done
    350         make_bank_account "$CREDIT_USERNAME" "$CREDIT_PASSWORD" \
    351                           "$PERSON_CREDIT_NAME" "$PAYTO_CREDIT" > /dev/null &&
    352         make_bank_account "$DEBIT_USERNAME" "$DEBIT_PASSWORD" \
    353                           "Person Debit" "$PAYTO_DEBIT" > /dev/null &&
    354         libeufin-bank edit-account -c $CONF_IBAN \
    355                       --debit_threshold="${IBAN_CURRENCY}:1000" \
    356                       "$DEBIT_USERNAME" >> iban-setup.log 2>&1 ||
    357             IBAN_ACTIVE='false'
    358         # Make sure the bank speaks the revenue API that
    359         # anastasis-helper-authorization-iban expects (an empty history is
    360         # answered with 204), so that a version mismatch disables IBAN
    361         # authentication instead of failing challenges at run time.
    362         CODE=`curl -s -o /dev/null -w "%{http_code}" \
    363               --user "${CREDIT_USERNAME}:${CREDIT_PASSWORD}" \
    364               "${IBAN_REVENUE_URL}history?limit=1"`
    365         if test $IBAN_ACTIVE = 'true' &&
    366            test 200 != "$CODE" && test 204 != "$CODE"
    367         then
    368             REASON="revenue API at ${IBAN_REVENUE_URL} answered $CODE"
    369             IBAN_ACTIVE='false'
    370             kill $IBAN_BANK_PID 2> /dev/null || true
    371         fi
    372     fi
    373     if test $IBAN_ACTIVE = 'false'
    374     then
    375         echo " DISABLED (${REASON:-see iban-setup.log})"
    376         anastasis-config -c $CONF_4 -s authorization-iban -o ENABLED -V NO
    377     else
    378         anastasis-config -c $CONF_4 -s authorization-iban -o CURRENCY -V "${IBAN_CURRENCY}"
    379         anastasis-config -c $CONF_4 -s authorization-iban -o CREDIT_IBAN -V "${IBAN_CREDIT}"
    380         anastasis-config -c $CONF_4 -s authorization-iban -o BUSINESS_NAME -V "${PERSON_CREDIT_NAME}"
    381         anastasis-config -c $CONF_4 -s authorization-iban -o WIRE_GATEWAY_URL \
    382                          -V "${IBAN_REVENUE_URL}"
    383         anastasis-config -c $CONF_4 -s authorization-iban -o WIRE_GATEWAY_AUTH_METHOD -V "basic"
    384         anastasis-config -c $CONF_4 -s authorization-iban -o USERNAME -V "${CREDIT_USERNAME}"
    385         anastasis-config -c $CONF_4 -s authorization-iban -o PASSWORD -V "${CREDIT_PASSWORD}"
    386         anastasis-config -c $CONF_4 -s authorization-iban -o ENABLED -V YES
    387         echo " OK"
    388     fi
    389 else
    390     anastasis-config -c $CONF_4 -s authorization-iban -o ENABLED -V NO
    391 fi
    392 
    393 
    394 echo -n "Launching anastasis services ..."
    395 # PREFIX="valgrind --log-file=anastasis-httpd.%p.log"
    396 PREFIX=""
    397 $PREFIX anastasis-httpd -L INFO -c $CONF_1 2> anastasis-httpd_1.log &
    398 PPID_1=$!
    399 $PREFIX anastasis-httpd -L INFO -c $CONF_2 2> anastasis-httpd_2.log &
    400 PPID_2=$!
    401 $PREFIX anastasis-httpd -L INFO -c $CONF_3 2> anastasis-httpd_3.log &
    402 PPID_3=$!
    403 $PREFIX anastasis-httpd -L INFO -c $CONF_4 2> anastasis-httpd_4.log &
    404 PPID_4=$!
    405 export PPID_1
    406 export PPID_2
    407 export PPID_3
    408 export PPID_4
    409 echo " OK"
    410 
    411 echo -n "Waiting for anastasis services ..."
    412 
    413 # Wait for anastasis services to be available
    414 for n in `seq 1 50`
    415 do
    416     echo -n "."
    417     sleep 0.1
    418     OK=0
    419    # anastasis_01
    420     wget --tries=1 --timeout=1 http://localhost:8086/ -o /dev/null -O /dev/null >/dev/null || continue
    421     # anastasis_02
    422     wget --tries=1 --timeout=1 http://localhost:8087/ -o /dev/null -O /dev/null >/dev/null || continue
    423     # anastasis_03
    424     wget --tries=1 --timeout=1 http://localhost:8088/ -o /dev/null -O /dev/null >/dev/null || continue
    425     # anastasis_04
    426     wget --tries=1 --timeout=1 http://localhost:8089/ -o /dev/null -O /dev/null >/dev/null || continue
    427     OK=1
    428     break
    429 done
    430 
    431 if [ 1 != $OK ]
    432 then
    433     exit_skip "Failed to launch anastasis services"
    434 fi
    435 echo "OK"
    436 
    437 export -f wire_transfer_to_anastasis
    438 
    439 echo "You can now run anastasis-gtk in TESTLAND."
    440 echo " "
    441 echo "We will now start a sub-shell. Please note:"
    442 echo '- to terminate the test environment by leaving the sub-shell use: exit'
    443 if test $IBAN_ACTIVE = 'true'
    444 then
    445     echo '- for IBAN authentication use: wire_transfer_to_anastasis "$AMOUNT" "$SUBJECT"'
    446     echo "- for your customer IBAN, use: ${IBAN_DEBIT}"
    447     export IBAN_BANK_URL
    448     export PAYTO_CREDIT
    449     export DEBIT_USERNAME
    450     export DEBIT_PASSWORD
    451     export CONF_4
    452 fi
    453 if test $1 = 'fees'
    454 then
    455     echo '- to pay, use: taler-wallet-cli --wallet-db=$WALLET_DB handle-uri $PAY_URI -y'
    456     export WALLET_DB
    457 fi
    458 
    459 echo '- use kill -SIGSTOP $PPID_$NUM ($NUM: 1-4) to suspend providers'
    460 
    461 bash
    462 
    463 exit 0