From e6397062b4e228b57a310bf877a9a5eaaa43e900 Mon Sep 17 00:00:00 2001 From: ms Date: Sat, 25 Sep 2021 09:21:23 +0200 Subject: integrating instance configuration into 'taler-local' --- bin/WIP/taler-local | 222 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 157 insertions(+), 65 deletions(-) diff --git a/bin/WIP/taler-local b/bin/WIP/taler-local index 7e6b5fd..6863e90 100755 --- a/bin/WIP/taler-local +++ b/bin/WIP/taler-local @@ -32,8 +32,9 @@ from typing import List, Callable from shutil import copy from string import ascii_letters, ascii_uppercase from sys import exit +from urllib.parse import urljoin from os import remove -from requests import get, auth +import requests from collections import OrderedDict import errno from pathlib import Path @@ -396,23 +397,23 @@ def prepare(): print(msg, env="") # Runs a command synchronously. - # FIXME: avoid overriding the log file. - def cmd(name, args, env=os.environ): - handle = launch(name, args, env) + def cmd(args, env=os.environ, custom_name=None): + handle = launch(args, env, custom_name) return_code = handle.wait() if return_code != 0: print("Command: " + " ".join(args) + " failed, return code: " + str(return_code)) - print(f"See logs in /tmp/{name}.log") + print(f"See logs in /tmp/$command.log") return False return handle - def kill(name, s): + def kill(s): s.terminate() s.wait() # Runs a command in the background. - def launch(name, cmd, env=os.environ): - log_file = open("/tmp/{name}.log", "w") + def launch(cmd, env=os.environ, custom_name=None): + name = custom_name if custom_name else cmd[0] + log_file = open("/tmp/{name}.log", "a+") handle = Popen( cmd, stdin=DEVNULL, @@ -420,16 +421,16 @@ def prepare(): stderr=log_file, env=env ) - atexit.register(lambda: kill(name, handle)) + atexit.register(lambda: kill(handle)) return handle - def check_running(name, check_url): - print_nn(f"Checking {name} is running...") + def check_running(check_url): + print_nn(f"Checking {check_url} is served correctly...") for i in range(10): print_nn(".") try: # Raises if the service is not reachable. - response = get(check_url) + response = requests.get(check_url) # Raises if the request gets a non 200 OK. response.raise_for_status() except: @@ -469,7 +470,6 @@ def prepare(): ): # make connection cmd( - "new-ebics-connection", [ "libeufin-cli", "connections", "new-ebics-connection", @@ -483,7 +483,6 @@ def prepare(): ) # connect cmd( - "bankconnection-connect", [ "libeufin-cli", "connections", "connect", bank_connection_name @@ -492,7 +491,6 @@ def prepare(): ) # Import bank account cmd( - "download-bank-accounts", [ "libeufin-cli", "connections", "download-bank-accounts", @@ -501,7 +499,6 @@ def prepare(): env ) cmd( - "import-bank-account", [ "libeufin-cli", "connections", "import-bank-account", @@ -515,7 +512,6 @@ def prepare(): ) # Set background tasks. cmd( - "task-schedule-submit-payments", [ "libeufin-cli", "accounts", "task-schedule", bank_account_name_nexus, @@ -526,7 +522,6 @@ def prepare(): env ) cmd( - "task-schedule-fetch-reports", [ "libeufin-cli", "accounts", "task-schedule", bank_account_name_nexus, @@ -551,7 +546,6 @@ def prepare(): env ): cmd( - "ebicssubscriber-create", [ "libeufin-cli", "sandbox", "--sandbox-url", sandbox_url, @@ -563,7 +557,6 @@ def prepare(): env ) cmd( - "ebicsbankaccount-create", [ "libeufin-cli", "sandbox", "--sandbox-url", sandbox_url, @@ -606,7 +599,7 @@ def prepare(): fstream.write(key + " = " + value + "\n") fstream.write("\n") fstream.close() - + # Writes on disk too, like the other config_* functions. def config_main( filename, outdir, @@ -799,8 +792,8 @@ def prepare(): SANDBOX_ADMIN_PASSWORD = "secret" EXCHANGE_NEXUS_USERNAME = "exchange-nexus-user" EXCHANGE_NEXUS_PASSWORD = "exchange-nexus-password" - FRONTENDS_API_KEY = "secret:secret" - TALER_MERCHANT_TOKEN = "secret" # same as above? + FRONTENDS_API_TOKEN = "secret:secret" + TALER_MERCHANT_TOKEN = "secret:secret" # same as above? # URLs REV_PROXY = "http://localhost:8080" @@ -831,13 +824,13 @@ def prepare(): merchant_wire_address=IBAN_MERCHANT, exchange_wire_gateway_username=EXCHANGE_NEXUS_USERNAME, exchange_wire_gateway_password=EXCHANGE_NEXUS_PASSWORD, - frontend_api_key=FRONTENDS_API_KEY + frontend_api_key=FRONTENDS_API_TOKEN ) config_sync( "sync.conf", outdir=CFG_OUTDIR, currency=CURRENCY, - api_key=FRONTENDS_API_KEY, + api_key=FRONTENDS_API_TOKEN, rev_proxy_url=REV_PROXY ) config_anastasis( @@ -845,20 +838,23 @@ def prepare(): outdir=CFG_OUTDIR, currency=CURRENCY, rev_proxy_url=REV_PROXY, - api_key=FRONTENDS_API_KEY + api_key=FRONTENDS_API_TOKEN ) print_nn("Reset and init exchange DB..") - cmd("exchange-dbinit", ["taler-exchange-dbinit", "--reset"]) + cmd(["taler-exchange-dbinit", "--reset"]) print(" OK") print_nn("Remove previous key and data files..") - cmd("remove-taler-data", ["rm", "-fr", Path.home() / ".taler-data" / "*"]) + cmd( + ["rm", "-fr", Path.home() / ".taler-data" / "*"], + custom_name="remove-taler-data" + ) print(" OK") print_nn("Launching the exchange...") - exchange_handle = launch("exchange", ["taler-exchange-httpd"]) - if not check_running("exchange-httpd", REV_PROXY + "/exchange/keys"): + exchange_handle = launch(["taler-exchange-httpd"]) + if not check_running(REV_PROXY + "/exchange/keys"): exit(1) print(" OK") print_nn("Launching the exchange RSA helper...") @@ -866,11 +862,11 @@ def prepare(): print_nn("Launching the exchange RSA helper...") exchange_eddsa_handle = launch("exchange-eddsa", ["taler-exchange-secmod-eddsa"]) print_nn("exchange-offline: signing the exchange keys, hence testing the crypto helpers are correct...") - cmd("taler-exchange-offline", ["taler-exchange-offline", "download", "sign", "upload"]) + cmd(["taler-exchange-offline", "download", "sign", "upload"]) print(" OK") PAYTO_URI=mc.sections["exchange-account-1"]["payto-uri"] print_nn("exchange-offline: enabling {PAYTO_URI}...") - cmd("exchange-offline", ["taler-exchange-offline", "enable-account", PAYTO_URI, "upload"]) + cmd(["taler-exchange-offline", "enable-account", PAYTO_URI, "upload"]) print(" OK") # Set up wire fees for next 5 years @@ -878,7 +874,7 @@ def prepare(): YEAR = NOW.year print_nn("Setting wire fees for the next 5 years...") for year in range(YEAR, YEAR+5): - cmd("exchange-offline", + cmd( [ "taler-exchange-offline", "wire-fee", @@ -887,28 +883,28 @@ def prepare(): CURRENCY + ":0.01", CURRENCY + ":0.01", "upload" - ] + ], + custom_name="set-wire-fee" ) print(" OK") print_nn("Getting exchange master public key via /keys..") try: - response = get(REV_PROXY + "/exchange/keys") + response = requests.get(REV_PROXY + "/exchange/keys") response.raise_for_status() except: EXCHANGE_MASTER_PUB = response.json().get("master_public_key") print(" OK") print_nn("Stopping exchange HTTP daemon and crypto helpers...") - kill("exchange-rsa", exchange_rsa_handle) - kill("exchange-eddsa", exchange_eddsa_handle) + kill(exchange_rsa_handle) + kill(exchange_eddsa_handle) print(" OK") print_nn("Add this exchange to the auditor...") cmd( - "auditor-exchange", [ "taler-auditor-exchange", "-m", EXCHANGE_MASTER_PUB, "-u", REV_PROXY + "/exchange" - ] + ], ) ## Step 4: Set up euFin print_nn("Resetting euFin databases...") @@ -922,12 +918,12 @@ def prepare(): print_nn("Create Sandbox superuser...") cmd( - "sandbox-superuser", [ "libeufin-sandbox", "superuser", SANDBOX_ADMIN_USERNAME, "--password", SANDBOX_ADMIN_PASSWORD - ] + ], + custom_name="sandbox-superuser", ) print(" OK") print_nn("Launching Sandbox...") @@ -935,23 +931,23 @@ def prepare(): "libeufin-sandbox", "serve", "--with-unix-socket", "/tmp/sandbox.sock" ]) - if not check_running("sandbox", SANDBOX_URL): + if not check_running(SANDBOX_URL): exit(1) print(" OK") print_nn("Make Sandbox EBICS host...") cmd( - "sandbox-create-ebicshost", [ "libeufin-cli", "sandbox", "--sandbox-url", SANDBOX_URL, "ebicshost", "create", "--host-id", EBICS_HOST_ID, ], - get_sandbox_cli_env( + env=get_sandbox_cli_env( SANDBOX_ADMIN_USERNAME, SANDBOX_ADMIN_PASSWORD - ) + ), + custom_name="sandbox-create-ebicshost", ) print(" OK") @@ -999,12 +995,12 @@ def prepare(): ) print_nn("Make Nexus superuser ...") cmd( - "nexus-superuser", [ "libeufin-nexus", "superuser", EXCHANGE_NEXUS_USERNAME, "--password", EXCHANGE_NEXUS_PASSWORD - ] + ], + custom_name="nexus-superuser", ) print(" OK") print_nn("Launching Nexus...") @@ -1012,7 +1008,7 @@ def prepare(): "libeufin-nexus", "serve", "--with-unix-socket", "/tmp/nexus.sock" ]) - if not check_running("nexus", NEXUS_URL): + if not check_running(NEXUS_URL): exit(1) print(" OK") @@ -1032,7 +1028,6 @@ def prepare(): ) print_nn("Create Taler facade ...") cmd( - "create-taler-facade", [ "libeufin-cli", "facades", "new-taler-wire-gateway-facade", @@ -1041,17 +1036,18 @@ def prepare(): EXCHANGE_BANK_CONNECTION, EXCHANGE_BANK_ACCOUNT_NEXUS ], - get_nexus_cli_env( + env=get_nexus_cli_env( EXCHANGE_NEXUS_USERNAME, EXCHANGE_NEXUS_PASSWORD, NEXUS_URL - ) + ), + custom_name="create-taler-facade", ) print(" OK") try: - response = get( + response = requests.get( NEXUS_URL + "/facades", - auth=auth.HTTPBasicAuth( + auth=requests.auth.HTTPBasicAuth( EXCHANGE_NEXUS_USERNAME, EXCHANGE_NEXUS_PASSWORD ) @@ -1063,62 +1059,158 @@ def prepare(): FACADE_URL=response.json().get("facade")[0].get("baseUrl") print_nn("Terminating Nexus...") - kill("nexus", handle_nexus) + kill(handle_nexus) print(" OK") print_nn("Terminating Sandbox...") - kill("sandbox", handle_sandbox) + kill(handle_sandbox) print(" OK") # Finish configuration now: cmd( - "specify-exchange-pub-for-merchant", [ "taler-config", "-s" f"merchant-exchange-{CURRENCY}", "-o" "master_key", "-V", EXCHANGE_MASTER_PUB - ] + ], + custom_name="specify-exchange-pub-for-merchant", ) # Point the exchange to the facade. cmd( - "specify-facade-url", [ "taler-config", "-s" f"exchange-account-credentials-1", "-o" "wire_gateway_url", "-V", FACADE_URL - ] + ], + custom_name="specify-facade-url", ) cmd( - "specify-username-for-facade", [ "taler-config", "-s" f"exchange-account-credentials-1", "-o" "username", "-V", EXCHANGE_NEXUS_USERNAME - ] + ], + custom_name="specify-username-for-facade", ) cmd( - "specify-password-for-facade", [ "taler-config", "-s" f"exchange-account-credentials-1", "-o" "password", "-V", EXCHANGE_NEXUS_PASSWORD - ] + ], + custom_name="specify-password-for-facade", ) ## Step 6: Set up merchant print_nn("Reset and init merchant database...") - cmd("merchant-dbinit", ["taler-merchant-dbinit", "--reset"]) + cmd(["taler-merchant-dbinit", "--reset"]) print(" OK") - # FIXME: Configure instances here! + def ensure_instance( + currency, instance_id, + backend_url, bank_hostname, + wire_method, merchant_wire_address, + auth_token + ): + auth_header = {"Authorization": f"Bearer {auth_token}"} + resp = requests.get( + urljoin(backend_url, f"management/instances/{instance_id}"), + headers = auth_header + ) + req = dict( + id=instance_id, + name=f"Name of '{instance_id}'", + payto_uris=["payto://{wire_method}/{bank_hostname}/{merchant_wire_address}"], + address=dict(), + jurisdiction=dict(), + default_max_wire_fee=f"{currency}:1", + default_wire_fee_amortization=3, + default_max_deposit_fee=f"{currency}:1", + default_wire_transfer_delay=dict(d_ms="forever"), + default_pay_delay=dict(d_ms="forever"), + auth=dict(method="token", token=auth_token), + ) + http_method = requests.post + endpoint = "management/instances" + # Instance exists, patching it. + if resp.status_code == 200: + print(f"Patching instance '{instance_id}'") + http_method = requests.patch + endpoint = f"management/instances/{instance_id}" + resp = http_method( + urljoin(backend_url, endpoint), + json=req, + headers = auth_header + ) + if resp.status_code < 200 or resp.status_code >= 300: + print(f"Could not create (or patch) instance '{instance_id}'") + print(f"Backend responds: {resp.status_code}/{resp.text}") + exit(1) + print_nn("Start merchant (with TALER_MERCHANT_TOKEN into the env)...") + auth_env = os.environ.copy() + auth_env["TALER_MERCHANT_TOKEN"] = TALER_MERCHANT_TOKEN + merchant_handle = launch( + ["taler-merchant-httpd"], + env=auth_env + ) + if not check_running("/merchant-backend"): + # check_running logs errors already. + exit(1) + print(" OK") + ensure_instance( + currency=CURRENCY, + instance_id="default", + backend_url = REV_PROXY + "/merchant-backend", + auth_token = TALER_MERCHANT_TOKEN, + bank_hostname = REV_PROXY + "/sandbox", + wire_method = "sepa", + merchant_wire_address = "UNUSED_IBAN", # Won't pass Camt validation. + auth_token=FRONTENDS_API_TOKEN + ) + print_nn("Stopping the merchant...") + kill(merchant_handle) + print(" OK") + print_nn("Restartin the merchant WITHOUT the auth-token in the env...") + merchant_handle = launch(["taler-merchant-httpd"]) + if not check_running("/merchant-backend"): + # check_running logs errors already. + exit(1) + print(" OK") + print_nn("Creating the 'donations' instance...") + ensure_instance( + currency=CURRENCY, + instance_id="donations", + backend_url = REV_PROXY + "/merchant-backend", + auth_token = TALER_MERCHANT_TOKEN, + bank_hostname = REV_PROXY + "/sandbox", + wire_method = "sepa", + merchant_wire_address = "UNUSED_IBAN", # Won't pass Camt validation. + auth_token=FRONTENDS_API_TOKEN + ) + print(" OK") + print_nn("Creating the 'gnunet' instance...") + ensure_instance( + currency=CURRENCY, + instance_id="gnunet", + backend_url = REV_PROXY + "/merchant-backend", + auth_token = TALER_MERCHANT_TOKEN, + bank_hostname = REV_PROXY + "/sandbox", + wire_method = "sepa", + merchant_wire_address = IBAN_MERCHANT, + auth_token=FRONTENDS_API_TOKEN + ) + print(" OK") + print_nn("Stopping the merchant backend...") + kill(merchant_handle) + print(" OK") if __name__ == "__main__": cli() -- cgit v1.2.3