diff options
author | MS <ms@taler.net> | 2023-12-11 19:57:47 +0100 |
---|---|---|
committer | MS <ms@taler.net> | 2023-12-11 19:57:47 +0100 |
commit | 579d93541d44ef63ef036c565d7626c76cd80d8b (patch) | |
tree | efb6cf61bfdfc10a1e861a23e4cf47934f80ff3c /regional-currency | |
parent | 29918880f335aff089a91b52716e24cea1199c9d (diff) | |
download | deployment-579d93541d44ef63ef036c565d7626c76cd80d8b.tar.gz deployment-579d93541d44ef63ef036c565d7626c76cd80d8b.tar.bz2 deployment-579d93541d44ef63ef036c565d7626c76cd80d8b.zip |
regional setup: rename to address any currency
Diffstat (limited to 'regional-currency')
21 files changed, 986 insertions, 0 deletions
diff --git a/regional-currency/.gitignore b/regional-currency/.gitignore new file mode 100644 index 0000000..4492389 --- /dev/null +++ b/regional-currency/.gitignore @@ -0,0 +1,3 @@ +nexus.log +sandbox.log +config/ diff --git a/regional-currency/.shellcheckrc b/regional-currency/.shellcheckrc new file mode 100644 index 0000000..e170f39 --- /dev/null +++ b/regional-currency/.shellcheckrc @@ -0,0 +1 @@ +disable=SC2018,SC2019 diff --git a/regional-currency/README b/regional-currency/README new file mode 100644 index 0000000..599336a --- /dev/null +++ b/regional-currency/README @@ -0,0 +1,2 @@ +Refer to the following document: +https://docs.taler.net/libeufin/regional-manual.html#guided-basic-setup diff --git a/regional-currency/config_libeufin.sh b/regional-currency/config_libeufin.sh new file mode 100755 index 0000000..ee9e707 --- /dev/null +++ b/regional-currency/config_libeufin.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -eu + +libeufin-dbconfig +./config_libeufin_nexus.sh +./config_libeufin_bank.sh diff --git a/regional-currency/config_libeufin_bank.sh b/regional-currency/config_libeufin_bank.sh new file mode 100755 index 0000000..5a32844 --- /dev/null +++ b/regional-currency/config_libeufin_bank.sh @@ -0,0 +1,128 @@ +#!/bin/bash +# This file is in the public domain. +# +# This script configure and launches libeufin-bank. +# The setup provides the admin account at the bank, and +# another account for the exchange at the bank. +# +# The environment must provide the following variables: +# - BANK_ADMIN_PASSWORD: password of the Netzbon administrator. +# - BANK_EXCHANGE_PASSWORD: password of the exchange +# bank account hosted at Sandbox. The related +# username is: exchange-at-sandbox +# - BANK_NAME: human-readable name for the bank +# - DOMAIN_NAME: DNS domain name to use for the setup +# - ENABLE_TLS (http or https?) +# +# OUTPUTS: +# +# EXCHANGE_PAYTO -- payto-URI of the exchange +# EXCHANGE_WIRE_GATEWAY_URL -- URL of the wire gateway for the exchange + +set -eu + +source functions.sh +source config/user.conf +source config/internal.conf + +if test -z "${BANK_NAME:-}"; then + say "Error: config/user.conf does not specify BANK_NAME" + exit 1 +fi +if test -z "${DOMAIN_NAME:-}"; then + say "Error: config/user.conf does not specify DOMAIN_NAME" + exit 1 +fi +if test -z "${BANK_ADMIN_PASSWORD:-}"; then + say "Error: config/user.conf does not specify BANK_ADMIN_PASSWORD" + exit 1 +fi +if test -z "${BANK_EXCHANGE_PASSWORD:-}"; then + say "Error: config/user.conf does not specify BANK_EXCHANGE_PASSWORD" + exit 1 +fi + +say "Configure the bank with ${CURRENCY}..." + +cat <<EOF > /etc/libeufin/libeufin-bank.conf +[libeufin-bank] +CURRENCY=${CURRENCY} +DEFAULT_EXCHANGE=${PROTO}://exchange.${DOMAIN_NAME} +SERVE=tcp +PORT=${BANK_PORT} +ALLOW_CONVERSION=yes +FIAT_CURRENCY=${FIAT_CURRENCY} +TAN_SMS=libeufin-tan-sms.sh +TAN_EMAIL=libeufin-tan-email.sh +ALLOW_EDIT_CASHOUT_PAYTO_URI=yes + +[CURRENCY-NETZBON] +enabled=yes +name=NetzBon +code=NETZBON +fractional_input_digits=2 +fractional_normal_digits=2 +fractional_trailing_zero_digits=2 +alt_unit_names={"0":"NETZBON"} + +EOF + +# FIXME: include this in the bank _and_ make sure it gets loaded + +say "Setting up libeufin-bank admin account..." +sudo -u libeufin-bank \ + libeufin-bank passwd \ + -c /etc/libeufin/libeufin-bank.conf \ + admin "${BANK_ADMIN_PASSWORD}" + +say "Setting up admin's debt limit..." +sudo -u libeufin-bank \ + libeufin-bank edit-account \ + -c /etc/libeufin/libeufin-bank.conf \ + admin --debit_threshold=${CURRENCY}:200000000 + +say "Setting up SPA configuration..." +echo "settings = { bankName: \"${BANK_NAME}\" }" >/etc/libeufin/settings.js + +say "Create exchange account..." +if test -z "${EXCHANGE_PAYTO:-}"; then + EXCHANGE_PAYTO_NEW="$(sudo -u libeufin-bank libeufin-bank create-account -c /etc/libeufin/libeufin-bank.conf --username exchange --password "${BANK_EXCHANGE_PASSWORD}" --name Exchange --exchange)?receiver-name=Exchange" + echo "EXCHANGE_PAYTO=\"${EXCHANGE_PAYTO_NEW}\"" >> config/internal.conf +fi + +if test -z "${EXCHANGE_WIRE_GATEWAY_URL:-}"; then + EXCHANGE_WIRE_GATEWAY_URL_NEW="${PROTO}://bank.$DOMAIN_NAME/accounts/exchange/taler-wire-gateway/" + echo "EXCHANGE_WIRE_GATEWAY_URL=\"${EXCHANGE_WIRE_GATEWAY_URL_NEW}\"" >> config/internal.conf +fi + +say "Start the bank..." +systemctl enable --now libeufin-bank + +say "Waiting for the bank (/config)..." +curl --max-time 2 \ + --retry-all-errors \ + --retry-delay 4 \ + --retry 10 \ + ${PROTO}://bank.${DOMAIN_NAME}/config +say "DONE" + +say "Setting conversion figures..." + +curl -u "admin:${BANK_ADMIN_PASSWORD}" \ + -H 'Content-Type: application/json; charset=utf-8' \ + ${PROTO}://bank.${DOMAIN_NAME}/conversion-info/conversion-rate \ +--data-binary @- << EOF +{ + "cashin_ratio": "1", + "cashin_fee": "${CURRENCY}:0", + "cashin_tiny_amount": "${CURRENCY}:2", + "cashin_rounding_mode": "nearest", + "cashin_min_amount": "${FIAT_CURRENCY}:1", + "cashout_ratio": "1", + "cashout_fee": "${FIAT_CURRENCY}:0", + "cashout_tiny_amount": "${FIAT_CURRENCY}:2", + "cashout_rounding_mode": "zero", + "cashout_min_amount": "${CURRENCY}:1" +} +EOF +say "DONE" diff --git a/regional-currency/config_libeufin_nexus.sh b/regional-currency/config_libeufin_nexus.sh new file mode 100755 index 0000000..491a757 --- /dev/null +++ b/regional-currency/config_libeufin_nexus.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# This file is in the public domain. +# +# This script configure and launches libeufin-bank. +# The setup provides the admin account at the bank, and +# another account for the exchange at the bank. +# +# The environment must provide the following variables: +set -eu + +source functions.sh +source config/user.conf + +taler-config -s nexus-ebics -o currency \ + -V $FIAT_CURRENCY -c /etc/libeufin/libeufin-nexus.conf + +say "Start nexus tasks..." +systemctl enable --now libeufin-nexus-ebics-fetch +systemctl enable --now libeufin-nexus-ebics-submit diff --git a/regional-currency/config_nginx.sh b/regional-currency/config_nginx.sh new file mode 100755 index 0000000..2fe561c --- /dev/null +++ b/regional-currency/config_nginx.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +source functions.sh +source config/user.conf + +export PROTO +export DOMAIN_NAME +export BANK_PORT + +envsubst <nginx-conf/backend.taler-nginx.conf >"/etc/nginx/sites-available/backend.${DOMAIN_NAME}" +envsubst <nginx-conf/bank.taler-nginx.conf >"/etc/nginx/sites-available/bank.${DOMAIN_NAME}" +envsubst <nginx-conf/exchange.taler-nginx.conf >"/etc/nginx/sites-available/exchange.${DOMAIN_NAME}" + +# Create nginx symlinks + +ln -sf /etc/nginx/sites-available/backend."${DOMAIN_NAME}" /etc/nginx/sites-enabled/backend."${DOMAIN_NAME}" +ln -sf /etc/nginx/sites-available/bank."${DOMAIN_NAME}" /etc/nginx/sites-enabled/bank."${DOMAIN_NAME}" +ln -sf /etc/nginx/sites-available/exchange."${DOMAIN_NAME}" /etc/nginx/sites-enabled/exchange."${DOMAIN_NAME}" + +if test "${ENABLE_TLS}" == "y"; then + + # Replace http with https in the demobank-ui configuration + + sed -i "s/http:\/\/bank./https:\/\/bank./g" /etc/libeufin/settings.json + + # Certbot + + say "Obtaining TLS certificates" + + certbot --nginx -d backend."${DOMAIN_NAME}" \ + -d bank."${DOMAIN_NAME}" \ + -d exchange."${DOMAIN_NAME}" +else + sed -i "s/https:\/\/bank./http:\/\/bank./g" /etc/libeufin/settings.json +fi + +say "Restarting Nginx with new configuration" +systemctl reload nginx diff --git a/regional-currency/functions.sh b/regional-currency/functions.sh new file mode 100755 index 0000000..a596f72 --- /dev/null +++ b/regional-currency/functions.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# Message +function say() { + echo "TALER: " "$@" +} + +# Check user if the user is root +function check_user() { + if [ "$(whoami)" != "root" ]; then + say "Please run this script as root" + exit 1 + fi +} + +function ask_questions() { + if test -z "${CURRENCY:-}"; then + read -r -p "Enter the name of the regional currency (e.g. 'NETZBON'): " CURRENCY + # convert to all-caps + CURRENCY=$(echo "${CURRENCY}" | tr a-z A-Z) + # libeufin currenly doesn't like currency names less than 3 letters. + if [[ ${#CURRENCY} -lt 3 || ${#CURRENCY} -gt 11 ]]; then + say "Currency name must be between 3 and 10 letters" + exit 1 + fi + echo "CURRENCY=${CURRENCY}" >>config/user.conf + fi + if test -z "${FIAT_CURRENCY:-}"; then + read -r -p "Enter the name of the fiat currency (e.g. 'CHF'): " FIAT_CURRENCY + # convert to all-caps + FIAT_CURRENCY=$(echo "${FIAT_CURRENCY}" | tr a-z A-Z) + # libeufin currenly doesn't like currency names less than 3 letters. + if [[ ${#FIAT_CURRENCY} -lt 3 || ${#FIAT_CURRENCY} -gt 11 ]]; then + say "Currency name must be between 3 and 10 letters" + exit 1 + fi + echo "FIAT_CURRENCY=${FIAT_CURRENCY}" >>config/user.conf + fi + if test -z "${BANK_NAME:-}"; then + read -r -p "Enter the human-readable name of the bank (e.g. 'Taler Bank'): " BANK_NAME + echo "BANK_NAME=\"${BANK_NAME}\"" >>config/user.conf + fi + if test -z "${ENABLE_TLS:-}"; then + read -r -p "Use TLS? (y/n): " ENABLE_TLS + echo "ENABLE_TLS=${ENABLE_TLS}" >>config/user.conf + fi + if test -z "${DO_OFFLINE:-}"; then + read -r -p "Run taler-exchange-offline? (y/n): " DO_OFFLINE + echo "DO_OFFLINE=${DO_OFFLINE}" >>config/user.conf + fi + if test -z "${MASTER_PUBLIC_KEY:-}"; then + if test "${DO_OFFLINE:-y}" == n; then + read -r -p "Enter the exchange-offline master public key: " MASTER_PUBLIC_KEY + echo "MASTER_PUBLIC_KEY=${MASTER_PUBLIC_KEY}" >>config/user.conf + fi + fi + if test -z "${BANK_ADMIN_PASSWORD:-}"; then + read -r -s -p "Enter the admin password for the bank: " BANK_ADMIN_PASSWORD + echo "BANK_ADMIN_PASSWORD=$(printf '%q' "${BANK_ADMIN_PASSWORD}")" >>config/user.conf + echo "" # force new line + fi + if test -z "${DOMAIN_NAME:-}"; then + read -r -p "Enter the domain name: " DOMAIN_NAME + # convert to lower-case + DOMAIN_NAME=$(echo "${DOMAIN_NAME}" | tr A-Z a-z) + echo "DOMAIN_NAME=${DOMAIN_NAME}" >>config/user.conf + fi +} + +# Set DISTRO to the detected distro or return non-zero +# status if distro not supported. +function detect_distro() { + unset DISTRO + # shellcheck disable=SC2034 + uname -a | grep Ubuntu >/dev/null && DISTRO=ubuntu && return 0 + # shellcheck disable=SC2034 + uname -a | grep Debian >/dev/null && DISTRO=debian && return 0 + echo "Unsupported distro, should be either ubuntu or debian" >&2 + return 1 +} + +function config_services() { + ./config_nginx.sh + ./config_libeufin.sh + ./setup-exchange.sh + ./setup-merchant.sh +} diff --git a/regional-currency/incoming_template.xml b/regional-currency/incoming_template.xml new file mode 100644 index 0000000..635fca7 --- /dev/null +++ b/regional-currency/incoming_template.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.08" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:camt.054.001.08 camt.054.001.08.xsd"> + <BkToCstmrDbtCdtNtfctn> + <GrpHdr> + <MsgId>20231106375204337320698</MsgId> + <CreDtTm>2023-11-06T23:39:09</CreDtTm> + <MsgPgntn> + <PgNb>1</PgNb> + <LastPgInd>true</LastPgInd> + </MsgPgntn> + <AddtlInf>NOT-INGESTED</AddtlInf> + </GrpHdr> + <Ntfctn> + <Id>20231106375204337320700</Id> + <CreDtTm>2023-11-06T23:39:09</CreDtTm> + <FrToDt> + <FrDtTm>2023-11-04T00:00:00</FrDtTm> + <ToDtTm>2023-11-06T23:59:59</ToDtTm> + </FrToDt> + <RptgSrc> + <Prtry>OTHR</Prtry> + </RptgSrc> + <Acct> + <Id> + <IBAN>NOT-INGESTED</IBAN> + </Id> + <Ownr> + <Nm>NOT-INGESTED</Nm> + </Ownr> + </Acct> + <Ntry> + <NtryRef>NOT-INGESTED</NtryRef> + <Amt Ccy="CHF">5.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <RvslInd>false</RvslInd> + <Sts> + <Cd>BOOK</Cd> + </Sts> + <BookgDt> + <Dt>2023-11-06</Dt> + </BookgDt> + <ValDt> + <Dt>2023-11-06</Dt> + </ValDt> + <AcctSvcrRef>NOT-INGESTED</AcctSvcrRef> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>AUTT</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <NtryDtls> + <Btch> + <NbOfTxs>1</NbOfTxs> + </Btch> + <TxDtls> + <Refs> + <AcctSvcrRef>BANK_ID</AcctSvcrRef> + <InstrId>NOT-INGESTED</InstrId> + <EndToEndId>NOT-INGESTED</EndToEndId> + <Prtry> + <Tp>00</Tp> + <Ref>NOT-INGESTED</Ref> + </Prtry> + </Refs> + <Amt Ccy="CHF">5.00</Amt> + <CdtDbtInd>CRDT</CdtDbtInd> + <BkTxCd> + <Domn> + <Cd>PMNT</Cd> + <Fmly> + <Cd>RCDT</Cd> + <SubFmlyCd>ATXN</SubFmlyCd> + </Fmly> + </Domn> + </BkTxCd> + <RltdPties> + <Dbtr> + <Pty> + <Nm>Test User</Nm> + </Pty> + </Dbtr> + <DbtrAcct> + <Id> + <IBAN>DEBTOR_IBAN</IBAN> + </Id> + </DbtrAcct> + <CdtrAcct> + <Id> + <IBAN>NOT-INGESTED</IBAN> + </Id> + </CdtrAcct> + </RltdPties> + <RltdAgts> + <DbtrAgt> + <FinInstnId> + <ClrSysMmbId> + <MmbId>NOT-INGESTED</MmbId> + </ClrSysMmbId> + <Nm>NOT-INGESTED</Nm> + <PstlAdr> + <AdrLine>NOT-INGESTED</AdrLine> + <AdrLine>NOT-INGESTED</AdrLine> + </PstlAdr> + </FinInstnId> + </DbtrAgt> + </RltdAgts> + <RmtInf> + <Ustrd>RESERVE_PUB</Ustrd> + <Strd> + <AddtlRmtInf>?REJECT?0</AddtlRmtInf> + <AddtlRmtInf>?ERROR?000</AddtlRmtInf> + </Strd> + </RmtInf> + <RltdDts> + <AccptncDtTm>2023-11-06T20:00:00</AccptncDtTm> + </RltdDts> + </TxDtls> + </NtryDtls> + <AddtlNtryInf>NOT-INGESTED</AddtlNtryInf> + </Ntry> + </Ntfctn> + </BkToCstmrDbtCdtNtfctn> +</Document> diff --git a/regional-currency/install_packages.sh b/regional-currency/install_packages.sh new file mode 100755 index 0000000..76ab05b --- /dev/null +++ b/regional-currency/install_packages.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# This file is in the public domain. + +set -eu + +source functions.sh +source config/user.conf +source config/internal.conf + +detect_distro + +# Program versions +PG_VERSION=15 + +## Update + +apt update + +## General requirements + +apt install uuid-runtime \ + curl \ + jq \ + wget \ + nginx \ + postgresql-${PG_VERSION} \ + postgresql-client-${PG_VERSION} \ + dbconfig-pgsql \ + certbot \ + python3-certbot-nginx -y + +## Add GNU Taler deb.taler.net to /etc/apt/sources.list + +say "Adding GNU Taler apt repository" +say "Detected distro $DISTRO" + +case $DISTRO in +debian) # TODO stable again when it is back ? + echo "deb [signed-by=/etc/apt/keyrings/taler-systems.gpg] https://deb.taler.net/apt/debian bookworm main" >/etc/apt/sources.list.d/taler.list + ;; +ubuntu) + echo "deb [signed-by=/etc/apt/keyrings/taler-systems.gpg] https://deb.taler.net/apt/ubuntu stable main" >/etc/apt/sources.list.d/taler.list + ;; +*) + say "Unsupported distro: $DISTRO" + exit 1 + ;; +esac + +wget -P /etc/apt/keyrings https://taler.net/taler-systems.gpg + +## Specific GNU Taler packages + +apt update +apt install taler-exchange \ + taler-merchant \ + taler-harness \ + taler-wallet-cli \ + libeufin-bank \ + libeufin-nexus -y diff --git a/regional-currency/main.sh b/regional-currency/main.sh new file mode 100755 index 0000000..97773ea --- /dev/null +++ b/regional-currency/main.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# This file is in the public domain. + +# main.sh is the main script that asks the questions and +# puts the answers into environment variables located at "config/taler-internal.conf or config/taler.conf" files +# Nginx configuration - Reads values directly from these "config files". + +set -eu + +# include functions source file + +source functions.sh + +# include variables from configuration +mkdir -p config/ +touch config/user.conf config/internal.conf +# Values supplied by user +source config/user.conf +# Values we generated +source config/internal.conf + +# Ask questions to user +# START USER INTERACTION +say "Welcome to the GNU Taler Debian setup!" +say "" +say "All configuration values asked during the setup script" +say "can be changed in config/user.conf" + +ask_questions + +# END USER INTERACTION + +# Check if the user is root, otherwise EXIT. +check_user + +# Installation of deb packages required +. install_packages.sh + +# Check DNS settings +if ! ping -c1 "exchange.${DOMAIN_NAME}" &>/dev/null; then + say "Could not ping exchange.${DOMAIN_NAME}." + say "Please make sure your DNS/network are working." + exit 1 +fi +if ! ping -c1 "bank.${DOMAIN_NAME}" &>/dev/null; then + say "Could not ping bank.${DOMAIN_NAME}." + say "Please make sure your DNS/network are working." + exit 1 +fi + +if test -z "${BANK_EXCHANGE_PASSWORD:-}"; then + BANK_EXCHANGE_PASSWORD=$(uuidgen) + echo "BANK_EXCHANGE_PASSWORD=\"${BANK_EXCHANGE_PASSWORD}\"" >>config/internal.conf +fi + +if test -z "${BANK_PORT:-}"; then + echo "BANK_PORT=8080" >>config/user.conf +fi + +if test -z "${PROTO:-}"; then + if test "${ENABLE_TLS:-}" == "y"; then + PROTO="https" + else + PROTO="http" + fi + echo "PROTO=$PROTO">>config/internal.conf +fi + +# FIXME: remove once the merchant .deb gets updated +rm /usr/bin/taler-merchant-dbconfig +wget -P /usr/bin/ https://git.taler.net/merchant.git/plain/contrib/taler-merchant-dbconfig +chmod a+x /usr/bin/taler-merchant-dbconfig + +config_services + +# Final message to the user +say "Congratulations, you have successfully installed GNU Taler" +say "Your bank is at ${PROTO}://bank.${DOMAIN_NAME}/" +say "A merchant is at ${PROTO}://backend.${DOMAIN_NAME}/" +say "You should set credentials for the merchant soon." +say "For the SMS cash-out TAN, make sure that telesign-secret" +say "is found in the PATH and that it defines the CUSTOMER_ID" +say "and API_KEY environment variables." + +exit 0 +# END INSTALLATION diff --git a/regional-currency/nginx-conf/backend.taler-nginx.conf b/regional-currency/nginx-conf/backend.taler-nginx.conf new file mode 100644 index 0000000..3e20704 --- /dev/null +++ b/regional-currency/nginx-conf/backend.taler-nginx.conf @@ -0,0 +1,14 @@ +server { + + listen 80; + listen [::]:80; + + server_name backend.${DOMAIN_NAME}; + + location / { + proxy_pass http://unix:/var/run/taler/merchant-httpd/merchant-http.sock; + proxy_set_header X-Forwarded-Proto "${PROTO}"; + proxy_set_header X-Forwarded-Host "backend.${DOMAIN_NAME}"; + proxy_set_header X-Forwarded-Prefix /; + } +} diff --git a/regional-currency/nginx-conf/bank.taler-nginx.conf b/regional-currency/nginx-conf/bank.taler-nginx.conf new file mode 100644 index 0000000..9e2ce5b --- /dev/null +++ b/regional-currency/nginx-conf/bank.taler-nginx.conf @@ -0,0 +1,18 @@ +server { + listen 80; + listen [::]:80; + + server_name bank.${DOMAIN_NAME}; + + access_log /var/log/nginx/libeufin-sandbox.log; + error_log /var/log/nginx/libeufin-sandbox.err; + + # TODO should we proxy SPA with nginx for perf and fallback to bank server on 404 ? + location / { + proxy_pass http://localhost:${BANK_PORT}; + #Fixes withdrawal http request + proxy_set_header X-Forwarded-Proto "${PROTO}"; + proxy_set_header X-Forwarded-Host "bank.${DOMAIN_NAME}"; + proxy_set_header X-Forwarded-Prefix /; + } +} diff --git a/regional-currency/nginx-conf/exchange.taler-nginx.conf b/regional-currency/nginx-conf/exchange.taler-nginx.conf new file mode 100644 index 0000000..0f470a1 --- /dev/null +++ b/regional-currency/nginx-conf/exchange.taler-nginx.conf @@ -0,0 +1,12 @@ +server { + + listen 80; + listen [::]:80; + + server_name exchange.${DOMAIN_NAME}; + + location / { + proxy_pass http://unix:/var/run/taler/exchange-httpd/exchange-http.sock; + } + +} diff --git a/regional-currency/setup-exchange.sh b/regional-currency/setup-exchange.sh new file mode 100755 index 0000000..2c4c06f --- /dev/null +++ b/regional-currency/setup-exchange.sh @@ -0,0 +1,228 @@ +#!/bin/bash +# This file is in the public domain. +# +# This script configure and launches the Taler exchange. +# +# The environment must provide the following variables: +# +# - BANK_EXCHANGE_PASSWORD (exchange password for libeufin-bank) +# - EXCHANGE_WIRE_GATEWAY_URL (where is the exchange wire gateway / libeufin-nexus) +# - EXCHANGE_PAYTO (exchange account PAYTO) +# - ENABLE_TLS (http or https?) +# - DOMAIN_NAME: DNS domain name to use for the setup +# + +set -eu + +notify_exit() { + [[ $1 == 0 ]] || echo Script "$0" failed, exit code "$1" +} + +notify_err() { + echo "errexit on line $(caller)" >&2 +} + +trap '(exit 130)' INT +trap '(exit 143)' TERM +trap notify_err ERR +# shellcheck disable=SC2154 +trap 'rc=$?; notify_exit $rc; exit $rc' EXIT + +# End of error handling setup + +source functions.sh +source config/user.conf +source config/internal.conf + +EXCHANGE_DB="taler-exchange" + +say "Beginning Exchange setup" + +if test -z "${BANK_EXCHANGE_PASSWORD:-}"; then + say "Failure: BANK_EXCHANGE_PASSWORD not set" + exit 1 +fi +if test -z "${EXCHANGE_WIRE_GATEWAY_URL:-}"; then + say "Failure: EXCHANGE_WIRE_GATEWAY_URL not set" + exit 1 +fi +if test -z "${EXCHANGE_PAYTO:-}"; then + say "Failure: EXCHANGE_PAYTO not set" + exit 1 +fi + +function die() { + say "$1" + exit 1 +} + +# Just try if sudo works for diagnostics +sudo -i -u taler-exchange-offline id >/dev/null || die "Error: Unable to switch to taler-exchange-offline user" + + +chmod a+r /etc/taler/taler.conf # FIXME-CG: Debian installation should set this + +# Create master key as taler-exchange-offline *unless* user already +# set the MASTER_PUBLIC_KEY to some value we can use. +export MASTER_PRIV_DIR=.local/share/taler/exchange/offline-keys +export MASTER_PRIV_FILE=${MASTER_PRIV_DIR}/master.priv +export SECMOD_TOFU_FILE=${MASTER_PRIV_DIR}/secm_tofus.pub +if test -z "${MASTER_PUBLIC_KEY:-}"; then + if test "${DO_OFFLINE:-y}" == n; then + say "Error: No MASTER_PUBLIC_KEY but DO_OFFLINE set to NO" + exit 1 + fi + say "Setting up offline key" + echo -e "[exchange-offline]\n"\ + "MASTER_PRIV_FILE=\$HOME/${MASTER_PRIV_FILE}\n"\ + "SECM_TOFU_FILE=\$HOME/${SECMOD_TOFU_FILE}\n"\ + >/etc/taler/conf.d/offline-setup.conf + + MASTER_PUBLIC_KEY=$(sudo -i -u taler-exchange-offline taler-exchange-offline -c /etc/taler/taler.conf -LDEBUG setup) + echo "MASTER_PUBLIC_KEY=\"${MASTER_PUBLIC_KEY}\"" >>config/user.conf + if test -z "${DO_OFFLINE:-}"; then + # Set 'DO_OFFLINE' + DO_OFFLINE=y + echo "DO_OFFLINE=y" >>config/user.conf + fi +else + say "Master public key is $MASTER_PUBLIC_KEY" + if test ${DO_OFFLINE:-y} == y; then + MASTER_PUBLIC_KEY2=$(sudo -i -u taler-exchange-offline taler-exchange-offline -c /etc/taler/taler.conf setup) + if test "${MASTER_PUBLIC_KEY2}" != "${MASTER_PUBLIC_KEY}"; then + say "Error: master public key missmatch ${MASTER_PUBLIC_KEY2} does not match ${MASTER_PUBLIC_KEY}" + exit 1 + fi + fi +fi + +export MASTER_PUBLIC_KEY + +say "Stopping running exchange before reconfiguration" +systemctl stop taler-exchange.target + +say "Configuring exchange" + +export EXCHANGE_BASE_URL="$PROTO://exchange.${DOMAIN_NAME}/" + +cat << EOF > /etc/taler/conf.d/setup.conf +[taler] +CURRENCY=${CURRENCY} +CURRENCY_ROUND_UNIT=${CURRENCY}:0.01 + +[exchange] +AML_THRESHOLD=${CURRENCY}:1000000 +MASTER_PUBLIC_KEY=${MASTER_PUBLIC_KEY} +BASE_URL=${EXCHANGE_BASE_URL} +STEFAN_ABS=${CURRENCY}:0 +STEFAN_LOG=${CURRENCY}:0 +STEFAN_LIN=0 + +[merchant-exchange-${DOMAIN_NAME}] +MASTER_KEY=${MASTER_PUBLIC_KEY} +CURRENCY=${CURRENCY} +EXCHANGE_BASE_URL=${EXCHANGE_BASE_URL} + +[exchange-account-default] +PAYTO_URI=${EXCHANGE_PAYTO} +ENABLE_DEBIT=YES +ENABLE_CREDIT=YES +@inline-secret@ exchange-accountcredentials-default ../secrets/exchange-accountcredentials-default.secret.conf +EOF + +# FIXME-CG: def already in the Git, remove this +# after the next .deb release +cat << EOF > /etc/taler/conf.d/netzbon.conf +[currency-netzbon] +ENABLED=YES +name=NetzBon +code=NETZBON +fractional_input_digits=2 +fractional_normal_digits=2 +fractional_trailing_zero_digits=2 +alt_unit_names = {"0":"NETZBON"} +EOF +chmod a+r /etc/taler/conf.d/netzbon.conf + +cat << EOF > /etc/taler/secrets/exchange-db.secret.conf +[exchangedb-postgres] +CONFIG=postgres:///exchange +EOF + +chmod 440 /etc/taler/secrets/exchange-db.secret.conf +chown root:taler-exchange-db /etc/taler/secrets/exchange-db.secret.conf + +cat << EOF > /etc/taler/secrets/exchange-accountcredentials-default.secret.conf + +[exchange-accountcredentials-default] +WIRE_GATEWAY_URL=${EXCHANGE_WIRE_GATEWAY_URL} +WIRE_GATEWAY_AUTH_METHOD=basic +USERNAME=exchange +PASSWORD=${BANK_EXCHANGE_PASSWORD} +EOF + +chmod 400 /etc/taler/secrets/exchange-accountcredentials-default.secret.conf +chown taler-exchange-wire:taler-exchange-db /etc/taler/secrets/exchange-accountcredentials-default.secret.conf + +taler-harness deployment gen-coin-config \ + --min-amount "${CURRENCY}":0.01 \ + --max-amount "${CURRENCY}":100 | + sed -e "s/FEE_DEPOSIT = ${CURRENCY}:0.01/FEE_DEPOSIT = ${CURRENCY}:0/" \ + >/etc/taler/conf.d/"${CURRENCY}"-coins.conf + +# FIXME-DOLD: this belongs with taler-harness +for SEC in $(taler-config -c /etc/taler/conf.d/"${CURRENCY}"-coins.conf -S | grep COIN-); do + taler-config -c /etc/taler/conf.d/"${CURRENCY}"-coins.conf -s "$SEC" -o CIPHER -V "RSA" +done + +# NOTE: already fixed in exchange.git, leaving in place +# until 0.9.4 release of fixed exchange Debian package. -CG +say "Initializing exchange database" +taler-exchange-dbconfig -c /etc/taler/taler.conf || true # FIXME-CG: no exit 77 if DB exist +# NOTE: latest exchange.git dbconfig no longer exits with 77, should remove || true with 0.9.4 exchange release. + +say "Launching exchange" +systemctl enable --now taler-exchange.target + +say "Waiting for exchange HTTP service (/config)..." +curl --max-time 2 \ + --retry-all-errors \ + --retry-delay 1 \ + --retry 10 \ + "${EXCHANGE_BASE_URL}"config &>/dev/null +say "DONE" + +say "Waiting for exchange management keys (this may take a while)..." +curl --max-time 30 \ + --retry-delay 1 \ + --retry 60 \ + "${EXCHANGE_BASE_URL}"management/keys &>/dev/null +say "DONE" + +if test ${DO_OFFLINE} == y; then + say "Offline interaction..." + + sudo -i -u taler-exchange-offline \ + taler-exchange-offline \ + -c /etc/taler/taler.conf \ + download \ + sign \ + upload + + sudo -i -u taler-exchange-offline \ + taler-exchange-offline \ + enable-account "${EXCHANGE_PAYTO}" \ + wire-fee now iban "${CURRENCY}":0 "${CURRENCY}":0 \ + global-fee now "${CURRENCY}":0 "${CURRENCY}":0 "${CURRENCY}":0 1h 6a 0 \ + upload +fi + +say "Waiting for exchange /keys..." +curl --max-time 2 \ + --retry-connrefused \ + --retry-delay 1 \ + --retry 10 \ + "${EXCHANGE_BASE_URL}"keys &>/dev/null +say "DONE" + +say "Exchange setup finished" diff --git a/regional-currency/setup-merchant.sh b/regional-currency/setup-merchant.sh new file mode 100755 index 0000000..917e653 --- /dev/null +++ b/regional-currency/setup-merchant.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -eu + +source functions.sh +source config/user.conf +source config/internal.conf + +say "Setting up merchant database" +taler-merchant-dbconfig + +say "Launching taler-merchant-httpd" +systemctl enable --now taler-merchant-httpd diff --git a/regional-currency/transfer.sh b/regional-currency/transfer.sh new file mode 100755 index 0000000..d49d445 --- /dev/null +++ b/regional-currency/transfer.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# This file is in the public domain. + +set -eu + +source functions.sh + +if test -z "${3:-}"; then + say "This tool allows you to send funds from the 'admin' account" + say "to a normal user's bank account within the system for testing." + say " " + say "Call with three arguments:" + say "1) target bank account name to credit" + say "2) amount to transfer (e.g. ${CURRENCY:-CURRENCY}:42.42)" + say "3) wire transfer subject to use" + say " " + exit 1 +fi + +# shellcheck disable=SC1091 +source /etc/libeufin/sandbox.env +export LIBEUFIN_SANDBOX_DB_CONNECTION + +libeufin-sandbox make-transaction --credit-account "$1" --debit-account admin "$2" "$3" diff --git a/regional-currency/vagrant/.gitignore b/regional-currency/vagrant/.gitignore new file mode 100644 index 0000000..8000dd9 --- /dev/null +++ b/regional-currency/vagrant/.gitignore @@ -0,0 +1 @@ +.vagrant diff --git a/regional-currency/vagrant/README b/regional-currency/vagrant/README new file mode 100644 index 0000000..e9387d3 --- /dev/null +++ b/regional-currency/vagrant/README @@ -0,0 +1,2 @@ +This folder contains a vagrant configuration (https://developer.hashicorp.com/vagrant) +that allows us to easily spin up a virtual machine to test the setup instructions. diff --git a/regional-currency/vagrant/Vagrantfile b/regional-currency/vagrant/Vagrantfile new file mode 100644 index 0000000..7cb3574 --- /dev/null +++ b/regional-currency/vagrant/Vagrantfile @@ -0,0 +1,77 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure +# configures the configuration version (we support older styles for +# backwards compatibility). Please don't change it unless you know what +# you're doing. +Vagrant.configure("2") do |config| + # The most common configuration options are documented and commented below. + # For a complete reference, please see the online documentation at + # https://docs.vagrantup.com. + + # Every Vagrant development environment requires a box. You can search for + # boxes at https://vagrantcloud.com/search. + config.vm.box = "ubuntu/kinetic64" + + config.ssh.forward_agent = true + config.ssh.forward_x11 = true + + # Disable automatic box update checking. If you disable this, then + # boxes will only be checked for updates when the user runs + # `vagrant box outdated`. This is not recommended. + # config.vm.box_check_update = false + + # Create a forwarded port mapping which allows access to a specific port + # within the machine from a port on the host machine. In the example below, + # accessing "localhost:8080" will access port 80 on the guest machine. + # NOTE: This will enable public access to the opened port + # config.vm.network "forwarded_port", guest: 80, host: 8080 + + # Create a forwarded port mapping which allows access to a specific port + # within the machine from a port on the host machine and only allow access + # via 127.0.0.1 to disable public access + # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" + + # Create a private network, which allows host-only access to the machine + # using a specific IP. + # config.vm.network "private_network", ip: "192.168.33.10" + + # Create a public network, which generally matched to bridged network. + # Bridged networks make the machine appear as another physical device on + # your network. + # config.vm.network "public_network" + + # Share an additional folder to the guest VM. The first argument is + # the path on the host to the actual folder. The second argument is + # the path on the guest to mount the folder. And the optional third + # argument is a set of non-required options. + # config.vm.synced_folder "../data", "/vagrant_data" + + # Provider-specific configuration so you can fine-tune various + # backing providers for Vagrant. These expose provider-specific options. + # Example for VirtualBox: + # + config.vm.provider "virtualbox" do |vb| + # Display the VirtualBox GUI when booting the machine + vb.gui = true + + # Customize the amount of memory on the VM: + vb.memory = "4096" + + # Required, or wayland doesn't seem to work + vb.customize ['modifyvm', :id, '--graphicscontroller', 'vmsvga'] + end + # + # View the documentation for the provider you are using for more + # information on available options. + + # Enable provisioning with a shell script. Additional provisioners such as + # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the + # documentation for more information about their specific syntax and use. + config.vm.provision "shell", reboot: true, inline: <<-SHELL + apt-get update + apt-get upgrade -y + apt-get install -y ubuntu-desktop gnome-shell firefox virtualbox-guest-additions-iso git + SHELL +end diff --git a/regional-currency/withdraw.sh b/regional-currency/withdraw.sh new file mode 100755 index 0000000..850d343 --- /dev/null +++ b/regional-currency/withdraw.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +if test "$1" = "--help" || test "$1" = "-h"; then + echo "./withdraw [RESERVE_PUB]" + echo + echo "Injects one incoming CHF payment into nexus database" + echo "in order to trigger a Taler withdrawal. The reserve" + echo "pub can be passed either as the first parameter, or" + echo "it'll be generated by the CLI wallet. In both cases," + echo "the exchange to withdraw from is \$PROTO://exchange.\$DOMAIN" + + exit 0 +fi + +RESERVE_PUB="$1" # maybe passed +set -eu + +. config/user.conf # DOMAIN_NAME & CURRENCY +. config/internal.conf # PROTO + +NEXUS_CONFIG_FILE=/etc/libeufin/libeufin-nexus.conf +if test -z "$RESERVE_PUB"; then + RESERVE_PUB=$(taler-wallet-cli \ + api 'acceptManualWithdrawal' \ + '{"exchangeBaseUrl":"'${PROTO}'://exchange.'$DOMAIN_NAME'", + "amount":"'$CURRENCY':5" + }' | jq -r .result.reservePub) +fi +DEBTOR_IBAN="CH8389144317421994586" +CAMT_054=$(sed \ + -e "s/RESERVE_PUB/$RESERVE_PUB/" \ + -e "s/BANK_ID/$(uuidgen | cut -c-34)/" \ + -e "s/DEBTOR_IBAN/$DEBTOR_IBAN/" \ + incoming_template.xml) + +echo "$CAMT_054" | sudo -i -u libeufin-nexus \ + libeufin-nexus ebics-fetch -c $NEXUS_CONFIG_FILE --import + +taler-wallet-cli run-until-done |