diff options
Diffstat (limited to 'src/cli')
36 files changed, 2148 insertions, 873 deletions
diff --git a/src/cli/.gitignore b/src/cli/.gitignore index dbf01fa..111e321 100644 --- a/src/cli/.gitignore +++ b/src/cli/.gitignore @@ -1,6 +1,13 @@ *.log +*.err +*.out anastasis-reducer test_reducer_home *.trs taler-bank.err wallet.err +anastasis-discover +talercheck +test_reducer.conf.edited +wallet-withdraw.out +libeufin-transfer-initiate.out diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am index 8434c91..8b2a9a0 100644 --- a/src/cli/Makefile.am +++ b/src/cli/Makefile.am @@ -2,6 +2,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include bin_PROGRAMS = \ + anastasis-discover \ anastasis-reducer if USE_COVERAGE @@ -19,7 +20,11 @@ check_SCRIPTS = \ test_anastasis_reducer_done_policy_review.sh \ test_anastasis_reducer_enter_secret.sh \ test_anastasis_reducer_recovery_enter_user_attributes.sh \ - test_iban.sh + test_anastasis_reducer_recovery_no_pay.sh \ + test_anastasis_reducer_recovery_hanging.sh + +# Removed for now, libeufin is not yet working OK for this. +# test_iban.sh AM_TESTS_ENVIRONMENT=export ANASTASIS_PREFIX=$${ANASTASIS_PREFIX:-@libdir@};export PATH=$${ANASTASIS_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; @@ -29,12 +34,19 @@ TESTS = \ EXTRA_DIST = \ $(check_SCRIPTS) \ + setup.sh \ + test_reducer_home/.local/share/taler/exchange-offline/master.priv \ test_reducer.conf \ + test_reducer_free.conf \ test_free_reducer.conf \ test_anastasis_reducer_1.conf \ test_anastasis_reducer_2.conf \ test_anastasis_reducer_3.conf \ test_anastasis_reducer_4.conf \ + test_anastasis_reducer_free_1.conf \ + test_anastasis_reducer_free_2.conf \ + test_anastasis_reducer_free_3.conf \ + test_anastasis_reducer_free_4.conf \ resources/00-backup.json \ resources/01-backup.json \ resources/02-backup.json \ @@ -58,3 +70,17 @@ anastasis_reducer_LDADD = \ -lgnunetutil \ -ljansson \ $(XLIB) + + +anastasis_discover_SOURCES = \ + anastasis-cli-discover.c +anastasis_discover_LDADD = \ + $(top_builddir)/src/util/libanastasisutil.la \ + $(top_builddir)/src/reducer/libanastasisredux.la \ + -ltalerjson \ + -ltalerutil \ + -lgnunetjson \ + -lgnunetcurl \ + -lgnunetutil \ + -ljansson \ + $(XLIB) diff --git a/src/cli/anastasis-cli-discover.c b/src/cli/anastasis-cli-discover.c new file mode 100644 index 0000000..f614165 --- /dev/null +++ b/src/cli/anastasis-cli-discover.c @@ -0,0 +1,261 @@ +/* + This file is part of Anastasis + Copyright (C) 2022 Anastasis SARL + + Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Lesser General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file cli/anastasis-cli-discover.c + * @brief command line tool to discover recovery policies + * @author Christian Grothoff + */ + +#include "platform.h" +#include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_curl_lib.h> +#include "anastasis_redux.h" +#include <taler/taler_util.h> +#include <taler/taler_error_codes.h> +#include <taler/taler_json_lib.h> +#include "anastasis_util_lib.h" + +/** + * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). + */ +static struct GNUNET_CURL_RescheduleContext *rc; + +/** + * Curl context for communication with anastasis backend + */ +static struct GNUNET_CURL_Context *ctx; + +/** + * Input to -a option given. + */ +static char *input; + +/** + * JSON containing previous state + */ +static json_t *prev_state; + +/** + * JSON containing arguments for action + */ +static json_t *arguments; + +/** + * Handle to an ongoing action. + */ +struct ANASTASIS_PolicyDiscovery *pd; + +/** + * Return value from main. + */ +static int global_ret; + + +/** + * Function called on each discovered recovery policy. Called + * with all arguments NULL if we have received all policies that + * we could possibly receive for the current operation. + * + * The client can then start a new policy discovery process, using the + * smallest (also most recent) @a version received per @a provider_url + * in the cursor to resume. Note that in this case, the application + * logic is responsible for de-duplication using @a hcpd, or it may show + * policies again if they are at different providers under versions not + * queried up to the cursor. + * + * @param cls closure + * @param hcpd hash of the compressed policy document (unique per policy) + * @param provider_url which provider claims to have this policy + * @param version version of the policy at this provider + * @param attribute_mask combination of optional identity attributes + * present in the state that was used to locate this version + * @param server_time when did the provider receive the upload + * @param secret_name name the user assigned to the backup + */ +static void +print_policy_cb (void *cls, + const struct GNUNET_HashCode *hcpd, + const char *provider_url, + uint32_t version, + json_int_t attribute_mask, + struct GNUNET_TIME_Timestamp server_time, + const char *secret_name, + const json_t *providers) +{ + if (NULL == hcpd) + { + fprintf (stderr, + "All results received, terminating\n"); + pd = NULL; + global_ret = 0; + GNUNET_SCHEDULER_shutdown (); + return; + } + fprintf (stdout, + "%s %u %u : \"%s\" \"%s\" (%s)\n", + provider_url, + (unsigned int) version, + (unsigned int) attribute_mask, + GNUNET_TIME_timestamp2s (server_time), + secret_name, + GNUNET_h2s (hcpd)); +} + + +/** + * @brief Shutdown the application. + * + * @param cls closure + */ +static void +shutdown_task (void *cls) +{ + (void) cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Shutdown initiated\n"); + if (NULL != pd) + { + ANASTASIS_policy_discovery_stop (pd); + pd = NULL; + } + ANASTASIS_redux_done (); + if (NULL != ctx) + { + GNUNET_CURL_fini (ctx); + ctx = NULL; + } + if (NULL != rc) + { + GNUNET_CURL_gnunet_rc_destroy (rc); + rc = NULL; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Shutdown complete\n"); +} + + +/** + * @brief Start the application + * + * @param cls closure + * @param args arguments left + * @param cfgfile config file name + * @param cfg handle for the configuration file + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + (void) cls; + json_error_t error; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Starting anastasis-discover\n"); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); + /* load cursor */ + if (NULL != input) + { + arguments = json_loads (input, + JSON_DECODE_ANY, + &error); + if (NULL == arguments) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Failed to parse arguments on line %u:%u: %s!\n", + error.line, + error.column, + error.text); + GNUNET_SCHEDULER_shutdown (); + return; + } + } + /* load state */ + if (NULL != args[0]) + { + prev_state = json_load_file (args[0], + JSON_DECODE_ANY, + &error); + args++; + } + else + { + prev_state = json_loadf (stdin, + JSON_DECODE_ANY, + &error); + } + if (NULL == prev_state) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Failed to parse initial state on line %u:%u: %s!\n", + error.line, + error.column, + error.text); + GNUNET_SCHEDULER_shutdown (); + return; + } + /* initialize HTTP client event loop */ + ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &rc); + rc = GNUNET_CURL_gnunet_rc_create (ctx); + ANASTASIS_redux_init (ctx); + pd = ANASTASIS_policy_discovery_start (prev_state, + arguments, + &print_policy_cb, + NULL); +} + + +int +main (int argc, + char *const *argv) +{ + /* the available command line options */ + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_option_string ('a', + "arguments", + "JSON", + "pass a JSON string containing cursor to use", + &input), + + GNUNET_GETOPT_OPTION_END + }; + enum GNUNET_GenericReturnValue ret; + + /* FIRST get the libtalerutil initialization out + of the way. Then throw that one away, and force + the SYNC defaults to be used! */ + (void) TALER_project_data_default (); + GNUNET_OS_init (ANASTASIS_project_data_default ()); + ret = GNUNET_PROGRAM_run (argc, + argv, + "anastasis-discover", + "This is an application for finding secrets that could be recovered.\n", + options, + &run, + NULL); + if (GNUNET_SYSERR == ret) + return 3; + if (GNUNET_NO == ret) + return 0; + return global_ret; +} + + +/* end of anastasis-cli-discover.c */ diff --git a/src/cli/anastasis-cli-redux.c b/src/cli/anastasis-cli-redux.c index dc9c7ab..e2d2e1d 100644 --- a/src/cli/anastasis-cli-redux.c +++ b/src/cli/anastasis-cli-redux.c @@ -1,6 +1,6 @@ /* This file is part of Anastasis - Copyright (C) 2020,2021 Anastasis SARL + Copyright (C) 2020,2021,2022 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -41,6 +41,12 @@ static struct GNUNET_CURL_RescheduleContext *rc; static struct GNUNET_CURL_Context *ctx; /** + * Application ID to include in the user attributes. + * (-a option). + */ +char *application_id; + +/** * -b option given. */ static int b_flag; @@ -146,6 +152,9 @@ action_cb (void *cls, "Redux failed with error %d: %s\n", error_code, TALER_ErrorCode_get_hint (error_code)); + json_dumpf (result_state, + stderr, + JSON_INDENT (2)); } GNUNET_SCHEDULER_shutdown (); global_ret = (TALER_EC_NONE != error_code) ? 1 : 0; @@ -309,6 +318,21 @@ run (void *cls, &rc); rc = GNUNET_CURL_gnunet_rc_create (ctx); ANASTASIS_redux_init (ctx); + /* Expand identity_attributes if -a is given explicitly and we + are at the respective step of the reduction */ + if ( (0 == strcasecmp (action, + "enter_user_attributes")) && + (NULL != application_id) && + (NULL != arguments) ) + { + json_t *attr = json_object_get (arguments, + "identity_attributes"); + if (NULL != attr) + GNUNET_assert (0 == + json_object_set_new (attr, + "application-id", + json_string (application_id))); + } ra = ANASTASIS_redux_action (prev_state, action, arguments, @@ -324,6 +348,16 @@ main (int argc, { /* the available command line options */ struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_option_string ('A', + "application", + "ID", + "set the application ID", + &application_id), + GNUNET_GETOPT_option_string ('a', + "arguments", + "JSON", + "pass a JSON string containing arguments to reducer", + &input), GNUNET_GETOPT_option_flag ('b', "backup", "use reducer to handle states for backup process", @@ -332,12 +366,6 @@ main (int argc, "restore", "use reducer to handle states for restore process", &r_flag), - GNUNET_GETOPT_option_string ('a', - "arguments", - "JSON", - "pass a JSON string containing arguments to reducer", - &input), - GNUNET_GETOPT_OPTION_END }; enum GNUNET_GenericReturnValue ret; @@ -354,6 +382,7 @@ main (int argc, options, &run, NULL); + GNUNET_free (application_id); if (GNUNET_SYSERR == ret) return 3; if (GNUNET_NO == ret) diff --git a/src/cli/resources/00-backup.json b/src/cli/resources/00-backup.json index 6e6c320..700f8cd 100644 --- a/src/cli/resources/00-backup.json +++ b/src/cli/resources/00-backup.json @@ -2,7 +2,8 @@ "continents": [ "Europe", "North America", - "Testcontinent" + "Demoworld" ], - "backup_state": "CONTINENT_SELECTING" -}
\ No newline at end of file + "backup_state": "CONTINENT_SELECTING", + "reducer_type": "backup" +} diff --git a/src/cli/resources/00-recovery.json b/src/cli/resources/00-recovery.json index acff19a..e9b14f3 100644 --- a/src/cli/resources/00-recovery.json +++ b/src/cli/resources/00-recovery.json @@ -4,5 +4,6 @@ "North America", "Testcontinent" ], + "reducer_type": "recovery", "recovery_state": "CONTINENT_SELECTING" -}
\ No newline at end of file +} diff --git a/src/cli/resources/01-backup.json b/src/cli/resources/01-backup.json index 842d3af..be2a9d9 100644 --- a/src/cli/resources/01-backup.json +++ b/src/cli/resources/01-backup.json @@ -2,15 +2,16 @@ "continents": [ "Europe", "North America", - "Testcontinent" + "Demoworld" ], "backup_state": "COUNTRY_SELECTING", - "selected_continent": "Testcontinent", + "reducer_type": "backup", + "selected_continent": "Demoworld", "countries": [ { "code": "xx", "name": "Testland", - "continent": "Testcontinent", + "continent": "Demoworld", "continent_i18n": { "xx": "Testkontinent" }, @@ -19,23 +20,7 @@ "de_CH": "Testlandi", "fr": "Testpais", "en": "Testland" - }, - "currency": "TESTKUDOS" - }, - { - "code": "xy", - "name": "Demoland", - "continent": "Testcontinent", - "continent_i18n": { - "xx": "Testkontinent" - }, - "name_i18n": { - "de_DE": "Demolandt", - "de_CH": "Demolandi", - "fr": "Demopais", - "en": "Demoland" - }, - "currency": "KUDOS" + } } ] -}
\ No newline at end of file +} diff --git a/src/cli/resources/01-recovery.json b/src/cli/resources/01-recovery.json index 11aafd3..5489814 100644 --- a/src/cli/resources/01-recovery.json +++ b/src/cli/resources/01-recovery.json @@ -5,6 +5,7 @@ "Testcontinent" ], "recovery_state": "COUNTRY_SELECTING", + "reducer_type": "recovery", "selected_continent": "Testcontinent", "countries": [ { @@ -38,4 +39,4 @@ "currency": "KUDOS" } ] -}
\ No newline at end of file +} diff --git a/src/cli/resources/02-backup.json b/src/cli/resources/02-backup.json index c9bba16..a298b69 100644 --- a/src/cli/resources/02-backup.json +++ b/src/cli/resources/02-backup.json @@ -2,50 +2,31 @@ "continents": [ "Europe", "North America", - "Testcontinent" + "Demoworld" ], "backup_state": "USER_ATTRIBUTES_COLLECTING", + "reducer_type": "backup", "selected_continent": "Testcontinent", "countries": [ { "code": "xx", "name": "Testland", - "continent": "Testcontinent", - "continent_i18n": { - "xx": "Testkontinent" - }, + "continent": "Demoworld", "name_i18n": { "de_DE": "Testlandt", "de_CH": "Testlandi", "fr": "Testpais", "en": "Testland" - }, - "currency": "TESTKUDOS" - }, - { - "code": "xy", - "name": "Demoland", - "continent": "Testcontinent", - "continent_i18n": { - "xx": "Testkontinent" - }, - "name_i18n": { - "de_DE": "Demolandt", - "de_CH": "Demolandi", - "fr": "Demopais", - "en": "Demoland" - }, - "currency": "KUDOS" + } } ], "authentication_providers": { - "http://localhost:8086/": {}, - "http://localhost:8087/": {}, - "http://localhost:8088/": {}, - "http://localhost:8089/": {} + "http://localhost:8086/": { "status" : "not-contacted" }, + "http://localhost:8087/": { "status" : "not-contacted" }, + "http://localhost:8088/": { "status" : "not-contacted" }, + "http://localhost:8089/": { "status" : "not-contacted" } }, "selected_country": "xx", - "currencies": [ "TESTKUDOS" ], "required_attributes": [ { "type": "string", diff --git a/src/cli/resources/02-recovery.json b/src/cli/resources/02-recovery.json index 79cfd6d..875fae0 100644 --- a/src/cli/resources/02-recovery.json +++ b/src/cli/resources/02-recovery.json @@ -5,6 +5,7 @@ "Testcontinent" ], "recovery_state": "USER_ATTRIBUTES_COLLECTING", + "reducer_type": "recovery", "selected_continent": "Testcontinent", "countries": [ { @@ -39,10 +40,10 @@ } ], "authentication_providers": { - "http://localhost:8086/": {}, - "http://localhost:8087/": {}, - "http://localhost:8088/": {}, - "http://localhost:8089/": {} + "http://localhost:8086/": { "status" : "not-contacted" }, + "http://localhost:8087/": { "status" : "not-contacted" }, + "http://localhost:8088/": { "status" : "not-contacted" }, + "http://localhost:8089/": { "status" : "not-contacted" } }, "selected_country": "xx", "currencies": [ "TESTKUDOS" ], diff --git a/src/cli/resources/03-backup.json b/src/cli/resources/03-backup.json index 4dd5368..15627a9 100644 --- a/src/cli/resources/03-backup.json +++ b/src/cli/resources/03-backup.json @@ -2,44 +2,27 @@ "continents": [ "Europe", "North America", - "Testcontinent" + "Demoworld" ], "backup_state": "AUTHENTICATIONS_EDITING", - "selected_continent": "Testcontinent", + "reducer_type": "backup", + "selected_continent": "Demoworld", "countries": [ { "code": "xx", "name": "Testland", - "continent": "Testcontinent", - "continent_i18n": { - "xx": "Testkontinent" - }, + "continent": "Demoworld", "name_i18n": { "de_DE": "Testlandt", "de_CH": "Testlandi", "fr": "Testpais", "en": "Testland" - }, - "currency": "TESTKUDOS" - }, - { - "code": "xy", - "name": "Demoland", - "continent": "Testcontinent", - "continent_i18n": { - "xx": "Testkontinent" - }, - "name_i18n": { - "de_DE": "Demolandt", - "de_CH": "Demolandi", - "fr": "Demopais", - "en": "Demoland" - }, - "currency": "KUDOS" + } } ], "authentication_providers": { "http://localhost:8086/": { + "status" : "ok", "methods": [ { "type": "question", @@ -52,13 +35,13 @@ "truth_lifetime": { "d_ms": 63115200000 }, - "currency": "TESTKUDOS", "business_name": "Data loss #1 Inc.", "storage_limit_in_megabytes": 1, - "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0", + "provider_salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0", "http_status": 200 }, "http://localhost:8087/": { + "status" : "ok", "methods": [ { "type": "question", @@ -71,13 +54,13 @@ "truth_lifetime": { "d_ms": 63115200000 }, - "currency": "TESTKUDOS", "business_name": "Data loss #2 Inc.", "storage_limit_in_megabytes": 1, - "salt": "D378FWXHJB8JHPQFQRZGGV9PWG", + "provider_salt": "D378FWXHJB8JHPQFQRZGGV9PWG", "http_status": 200 }, "http://localhost:8088/": { + "status" : "ok", "methods": [ { "type": "question", @@ -90,13 +73,13 @@ "truth_lifetime": { "d_ms": 63115200000 }, - "currency": "TESTKUDOS", "business_name": "Data loss #3 Inc.", "storage_limit_in_megabytes": 1, - "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR", + "provider_salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR", "http_status": 200 }, "http://localhost:8089/": { + "status" : "ok", "methods": [ { "type": "question", @@ -109,15 +92,13 @@ "truth_lifetime": { "d_ms": 63115200000 }, - "currency": "TESTKUDOS", "business_name": "Data loss #4 Inc.", "storage_limit_in_megabytes": 1, - "salt": "PN0VJF6KDSBYN40SGRCEXPB07M", + "provider_salt": "PN0VJF6KDSBYN40SGRCEXPB07M", "http_status": 200 } }, "selected_country": "xx", - "currencies": ["TESTKUDOS"], "required_attributes": [ { "type": "string", diff --git a/src/cli/resources/04-backup.json b/src/cli/resources/04-backup.json index db51f5a..c7dc6fe 100644 --- a/src/cli/resources/04-backup.json +++ b/src/cli/resources/04-backup.json @@ -2,44 +2,27 @@ "continents": [ "Europe", "North America", - "Testcontinent" + "Demoworld" ], "backup_state": "AUTHENTICATIONS_EDITING", - "selected_continent": "Testcontinent", + "reducer_type": "backup", + "selected_continent": "Demoworld", "countries": [ { "code": "xx", "name": "Testland", - "continent": "Testcontinent", - "continent_i18n": { - "xx": "Testkontinent" - }, + "continent": "Demoworld", "name_i18n": { "de_DE": "Testlandt", "de_CH": "Testlandi", "fr": "Testpais", "en": "Testland" - }, - "currency": "TESTKUDOS" - }, - { - "code": "xy", - "name": "Demoland", - "continent": "Testcontinent", - "continent_i18n": { - "xx": "Testkontinent" - }, - "name_i18n": { - "de_DE": "Demolandt", - "de_CH": "Demolandi", - "fr": "Demopais", - "en": "Demoland" - }, - "currency": "KUDOS" + } } ], "authentication_providers": { "http://localhost:8086/": { + "status" : "ok", "methods": [ { "type": "question", @@ -52,13 +35,13 @@ "truth_lifetime": { "d_ms": 63115200000 }, - "currency": "TESTKUDOS", "business_name": "Data loss #1 Inc.", "storage_limit_in_megabytes": 1, - "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0", + "provider_salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0", "http_status": 200 }, "http://localhost:8087/": { + "status" : "ok", "methods": [ { "type": "question", @@ -71,13 +54,13 @@ "truth_lifetime": { "d_ms": 63115200000 }, - "currency": "TESTKUDOS", "business_name": "Data loss #2 Inc.", "storage_limit_in_megabytes": 1, - "salt": "D378FWXHJB8JHPQFQRZGGV9PWG", + "provider_salt": "D378FWXHJB8JHPQFQRZGGV9PWG", "http_status": 200 }, "http://localhost:8088/": { + "status" : "ok", "methods": [ { "type": "question", @@ -90,13 +73,13 @@ "truth_lifetime": { "d_ms": 63115200000 }, - "currency": "TESTKUDOS", "business_name": "Data loss #3 Inc.", "storage_limit_in_megabytes": 1, - "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR", + "provider_salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR", "http_status": 200 }, "http://localhost:8089/": { + "status" : "ok", "methods": [ { "type": "question", @@ -109,10 +92,9 @@ "truth_lifetime": { "d_ms": 63115200000 }, - "currency": "TESTKUDOS", "business_name": "Data loss #4 Inc.", "storage_limit_in_megabytes": 1, - "salt": "PN0VJF6KDSBYN40SGRCEXPB07M", + "provider_salt": "PN0VJF6KDSBYN40SGRCEXPB07M", "http_status": 200 } }, diff --git a/src/cli/resources/05-backup.json b/src/cli/resources/05-backup.json index 143d9e3..c8f52f0 100644 --- a/src/cli/resources/05-backup.json +++ b/src/cli/resources/05-backup.json @@ -5,6 +5,7 @@ "Testcontinent" ], "backup_state": "POLICIES_REVIEWING", + "reducer_type": "backup", "selected_continent": "Testcontinent", "countries": [ { @@ -40,6 +41,7 @@ ], "authentication_providers": { "http://localhost:8086/": { + "status" : "ok", "methods": [ { "type": "question", @@ -55,10 +57,11 @@ "currency": "TESTKUDOS", "business_name": "Data loss #1 Inc.", "storage_limit_in_megabytes": 1, - "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0", + "provider_salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0", "http_status": 200 }, "http://localhost:8087/": { + "status" : "ok", "methods": [ { "type": "question", @@ -74,10 +77,11 @@ "currency": "TESTKUDOS", "business_name": "Data loss #2 Inc.", "storage_limit_in_megabytes": 1, - "salt": "D378FWXHJB8JHPQFQRZGGV9PWG", + "provider_salt": "D378FWXHJB8JHPQFQRZGGV9PWG", "http_status": 200 }, "http://localhost:8088/": { + "status" : "ok", "methods": [ { "type": "question", @@ -93,10 +97,11 @@ "currency": "TESTKUDOS", "business_name": "Data loss #3 Inc.", "storage_limit_in_megabytes": 1, - "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR", + "provider_salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR", "http_status": 200 }, "http://localhost:8089/": { + "status" : "ok", "methods": [ { "type": "question", @@ -112,7 +117,7 @@ "currency": "TESTKUDOS", "business_name": "Data loss #4 Inc.", "storage_limit_in_megabytes": 1, - "salt": "PN0VJF6KDSBYN40SGRCEXPB07M", + "provider_salt": "PN0VJF6KDSBYN40SGRCEXPB07M", "http_status": 200 } }, diff --git a/src/cli/resources/06-backup.json b/src/cli/resources/06-backup.json index 9944a17..04d8b02 100644 --- a/src/cli/resources/06-backup.json +++ b/src/cli/resources/06-backup.json @@ -5,6 +5,7 @@ "Testcontinent" ], "backup_state": "SECRET_EDITING", + "reducer_type": "backup", "selected_continent": "Testcontinent", "countries": [ { @@ -40,6 +41,7 @@ ], "authentication_providers": { "http://localhost:8086/": { + "status" : "ok", "methods": [ { "type": "question", @@ -55,10 +57,11 @@ "currency": "TESTKUDOS", "business_name": "Data loss #1 Inc.", "storage_limit_in_megabytes": 1, - "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0", + "provider_salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0", "http_status": 200 }, "http://localhost:8087/": { + "status" : "ok", "methods": [ { "type": "question", @@ -74,10 +77,11 @@ "currency": "TESTKUDOS", "business_name": "Data loss #2 Inc.", "storage_limit_in_megabytes": 1, - "salt": "D378FWXHJB8JHPQFQRZGGV9PWG", + "provider_salt": "D378FWXHJB8JHPQFQRZGGV9PWG", "http_status": 200 }, "http://localhost:8088/": { + "status" : "ok", "methods": [ { "type": "question", @@ -93,10 +97,11 @@ "currency": "TESTKUDOS", "business_name": "Data loss #3 Inc.", "storage_limit_in_megabytes": 1, - "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR", + "provider_salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR", "http_status": 200 }, "http://localhost:8089/": { + "status" : "ok", "methods": [ { "type": "question", @@ -112,7 +117,7 @@ "currency": "TESTKUDOS", "business_name": "Data loss #4 Inc.", "storage_limit_in_megabytes": 1, - "salt": "PN0VJF6KDSBYN40SGRCEXPB07M", + "provider_salt": "PN0VJF6KDSBYN40SGRCEXPB07M", "http_status": 200 } }, diff --git a/src/cli/setup.sh b/src/cli/setup.sh new file mode 100755 index 0000000..6d26168 --- /dev/null +++ b/src/cli/setup.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# This file is in the public domain + +# Script to be inlined into the main test scripts. Defines function 'setup()' +# which wraps around 'taler-unified-setup.sh' to launch GNU Taler services. +# Call setup() with the arguments to pass to 'taler-unified-setup'. setup() +# will then launch GNU Taler, wait for the process to be complete before +# returning. The script will also install an exit handler to ensure the GNU +# Taler processes are stopped when the shell exits. + +set -eu + +# Cleanup to run whenever we exit +function exit_cleanup() +{ + if [ ! -z ${SETUP_PID+x} ] + then + echo "Killing taler-unified-setup ($SETUP_PID)" >&2 + kill -TERM "$SETUP_PID" 2> /dev/null || true + wait "$SETUP_PID" 2> /dev/null || true + fi +} + +# Install cleanup handler (except for kill -9) +trap exit_cleanup EXIT + +function setup() +{ + echo "Starting test system ..." >&2 + # Create a named pipe in a temp directory we own. + FIFO_DIR=$(mktemp -p "${TMPDIR:-/tmp}" -d fifo-XXXXXX) + FIFO_OUT=$(echo "$FIFO_DIR/out") + mkfifo "$FIFO_OUT" + # Open pipe as FD 3 (RW) and FD 4 (RO) + exec 3<> "$FIFO_OUT" 4< "$FIFO_OUT" + rm -rf "$FIFO_DIR" + # We require '-W' for our termination logic to work. + taler-unified-setup.sh -W "$@" >&3 & + SETUP_PID=$! + # Close FD3 + exec 3>&- + sed -u '/<<READY>>/ q' <&4 + # Close FD4 + exec 4>&- + echo "Test system ready" >&2 +} + +# Exit, with status code "skip" (no 'real' failure) +function exit_fail() { + echo "$@" >&2 + exit 1 +} + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo "SKIPPING: $1" + exit 77 +} + +function get_payto_uri() { + export LIBEUFIN_SANDBOX_USERNAME="$1" + export LIBEUFIN_SANDBOX_PASSWORD="$2" + export LIBEUFIN_SANDBOX_URL="http://localhost:18082" + libeufin-cli sandbox demobank info --bank-account "$1" | jq --raw-output '.paytoUri' +} + +function get_bankaccount_transactions() { + export LIBEUFIN_SANDBOX_USERNAME=$1 + export LIBEUFIN_SANDBOX_PASSWORD=$2 + export LIBEUFIN_SANDBOX_URL="http://localhost:18082" + libeufin-cli sandbox demobank list-transactions --bank-account $1 +} diff --git a/src/cli/test_anastasis_reducer_1.conf b/src/cli/test_anastasis_reducer_1.conf index 3a05690..2a3a0e4 100644 --- a/src/cli/test_anastasis_reducer_1.conf +++ b/src/cli/test_anastasis_reducer_1.conf @@ -3,7 +3,7 @@ [anastasis] PORT = 8086 -SERVER_SALT = AUfO1KGOKYIFlFQg +PROVIDER_SALT = AUfO1KGOKYIFlFQg BUSINESS_NAME = "Data loss #1 Inc." [stasis-postgres] diff --git a/src/cli/test_anastasis_reducer_2.conf b/src/cli/test_anastasis_reducer_2.conf index 4eef5f0..71b133f 100644 --- a/src/cli/test_anastasis_reducer_2.conf +++ b/src/cli/test_anastasis_reducer_2.conf @@ -3,7 +3,7 @@ [anastasis] PORT = 8087 -SERVER_SALT = BUfO1KGOKYIFlFQg +PROVIDER_SALT = BUfO1KGOKYIFlFQg BUSINESS_NAME = "Data loss #2 Inc." [stasis-postgres] diff --git a/src/cli/test_anastasis_reducer_3.conf b/src/cli/test_anastasis_reducer_3.conf index 08f4700..47233ff 100644 --- a/src/cli/test_anastasis_reducer_3.conf +++ b/src/cli/test_anastasis_reducer_3.conf @@ -3,7 +3,7 @@ [anastasis] PORT = 8088 -SERVER_SALT = CUfO1KGOKYIFlFQg +PROVIDER_SALT = CUfO1KGOKYIFlFQg BUSINESS_NAME = "Data loss #3 Inc." [stasis-postgres] diff --git a/src/cli/test_anastasis_reducer_4.conf b/src/cli/test_anastasis_reducer_4.conf index dee90e3..f515a78 100644 --- a/src/cli/test_anastasis_reducer_4.conf +++ b/src/cli/test_anastasis_reducer_4.conf @@ -3,7 +3,7 @@ [anastasis] PORT = 8089 -SERVER_SALT = DUfO1KGOKYIFlFQg +PROVIDER_SALT = DUfO1KGOKYIFlFQg BUSINESS_NAME = "Data loss #4 Inc." [stasis-postgres] diff --git a/src/cli/test_anastasis_reducer_backup_enter_user_attributes.sh b/src/cli/test_anastasis_reducer_backup_enter_user_attributes.sh index b8662e8..8a04b0a 100755 --- a/src/cli/test_anastasis_reducer_backup_enter_user_attributes.sh +++ b/src/cli/test_anastasis_reducer_backup_enter_user_attributes.sh @@ -126,16 +126,6 @@ fi echo "OK" -echo -n "Test user attributes collection in a recovery state ..." -anastasis-reducer -a \ - '{"identity_attributes": { - "full_name": "Max Musterman", - "sq_number": "4", - "birthdate": "2000-01-01"}}' \ - enter_user_attributes resources/02-recovery.json $TFILE 2> /dev/null && exit_fail "Expected recovery to fail due to lacking policy data" - -echo "OK" - rm -f $TFILE exit 0 diff --git a/src/cli/test_anastasis_reducer_done_authentication.sh b/src/cli/test_anastasis_reducer_done_authentication.sh index 87c738c..545c733 100755 --- a/src/cli/test_anastasis_reducer_done_authentication.sh +++ b/src/cli/test_anastasis_reducer_done_authentication.sh @@ -46,9 +46,9 @@ echo " OK" echo -n "Test done authentication (next) ..." -anastasis-reducer next resources/04-backup.json $TFILE +anastasis-reducer next resources/04-backup.json "$TFILE" -STATE=`jq -r -e .backup_state < $TFILE` +STATE=$(jq -r -e .backup_state < "$TFILE") if test "$STATE" != "POLICIES_REVIEWING" then exit_fail "Expected new state to be AUTHENTICATIONS_EDITING, got $STATE" diff --git a/src/cli/test_anastasis_reducer_enter_secret.sh b/src/cli/test_anastasis_reducer_enter_secret.sh index 8005f08..3b25537 100755 --- a/src/cli/test_anastasis_reducer_enter_secret.sh +++ b/src/cli/test_anastasis_reducer_enter_secret.sh @@ -1,6 +1,7 @@ #!/bin/bash # This file is in the public domain. +# shellcheck disable=SC2317 ## Coloring style Text shell script COLOR='\033[0;35m' NOCOLOR='\033[0m' @@ -9,46 +10,22 @@ NORM="$(tput sgr0)" set -eu -# Exit, with status code "skip" (no 'real' failure) -function exit_skip() { - echo " SKIP: $1" - exit 77 -} - -# Exit, with error message (hard failure) -function exit_fail() { - echo " FAIL: $1" - exit 1 -} - -# Cleanup to run whenever we exit -function cleanup() -{ - for n in `jobs -p` - do - kill $n 2> /dev/null || true - done - rm -rf $CONF $WALLET_DB $TFILE $UFILE $TMP_DIR - wait -} - -CONF_1="test_anastasis_reducer_1.conf" -CONF_2="test_anastasis_reducer_2.conf" -CONF_3="test_anastasis_reducer_3.conf" -CONF_4="test_anastasis_reducer_4.conf" - -# Exchange configuration file will be edited, so we create one -# from the template. -CONF=`mktemp test_reducerXXXXXX.conf` -cp test_reducer.conf $CONF - -TMP_DIR=`mktemp -d keys-tmp-XXXXXX` -WALLET_DB=`mktemp test_reducer_walletXXXXXX.json` -TFILE=`mktemp test_reducer_statePPXXXXXX` -UFILE=`mktemp test_reducer_stateBFXXXXXX` - -# Install cleanup handler (except for kill -9) -trap cleanup EXIT +# Replace with 0 for nexus... +USE_FAKEBANK=1 +if [ 1 = "$USE_FAKEBANK" ] +then + ACCOUNT="exchange-account-2" + WIRE_METHOD="x-taler-bank" + BANK_FLAGS="-f -d $WIRE_METHOD -u $ACCOUNT" + BANK_URL="http://localhost:18082/" + MERCHANT_PAYTO="payto://x-taler-bank/localhost/anastasis?receiver-name=anastasis" +else + ACCOUNT="exchange-account-1" + WIRE_METHOD="iban" + BANK_FLAGS="-ns -d $WIRE_METHOD -u $ACCOUNT" + BANK_URL="http://localhost:18082/" + MERCHANT_PAYTO="payto://iban/SANDBOXX/DE648226?receiver-name=anastasis" +fi # Check we can actually run echo -n "Testing for jq" @@ -63,9 +40,6 @@ taler-exchange-httpd -h > /dev/null || exit_skip " taler-exchange required" taler-merchant-httpd -h > /dev/null || exit_skip " taler-merchant required" echo " FOUND" -echo -n "Testing for taler-bank-manage" -taler-bank-manage --help >/dev/null </dev/null || exit_skip " MISSING" -echo " FOUND" echo -n "Testing for taler-wallet-cli" taler-wallet-cli -v >/dev/null </dev/null || exit_skip " MISSING" echo " FOUND" @@ -74,87 +48,65 @@ echo -n "Testing for anastasis-httpd" anastasis-httpd -h >/dev/null </dev/null || exit_skip " MISSING" echo " FOUND" -echo -n "Initialize anastasis database ..." -# Name of the Postgres database we will use for the script. -# Will be dropped, do NOT use anything that might be used -# elsewhere -TARGET_DB_1=`anastasis-config -c $CONF_1 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` -TARGET_DB_2=`anastasis-config -c $CONF_2 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` -TARGET_DB_3=`anastasis-config -c $CONF_3 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` -TARGET_DB_4=`anastasis-config -c $CONF_4 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` - -dropdb $TARGET_DB_1 >/dev/null 2>/dev/null || true -createdb $TARGET_DB_1 || exit_skip "Could not create database $TARGET_DB_1" -anastasis-dbinit -c $CONF_1 2> anastasis-dbinit_1.log -dropdb $TARGET_DB_2 >/dev/null 2>/dev/null || true -createdb $TARGET_DB_2 || exit_skip "Could not create database $TARGET_DB_2" -anastasis-dbinit -c $CONF_2 2> anastasis-dbinit_2.log -dropdb $TARGET_DB_3 >/dev/null 2>/dev/null || true -createdb $TARGET_DB_3 || exit_skip "Could not create database $TARGET_DB_3" -anastasis-dbinit -c $CONF_3 2> anastasis-dbinit_3.log -dropdb $TARGET_DB_4 >/dev/null 2>/dev/null || true -createdb $TARGET_DB_4 || exit_skip "Could not create database $TARGET_DB_4" -anastasis-dbinit -c $CONF_4 2> anastasis-dbinit_4.log +. setup.sh +# Launch exchange, merchant and bank. +# shellcheck disable=SC2086 +setup -c "test_reducer.conf" \ + -aemw \ + $BANK_FLAGS -echo " OK" -echo -n "Generating Taler auditor, exchange and merchant configurations ..." - -DATA_DIR=`taler-config -f -c $CONF -s PATHS -o TALER_HOME` -rm -rf $DATA_DIR - -# obtain key configuration data -MASTER_PRIV_FILE=`taler-config -f -c $CONF -s "EXCHANGE-OFFLINE" -o "MASTER_PRIV_FILE"` -MASTER_PRIV_DIR=`dirname $MASTER_PRIV_FILE` -mkdir -p $MASTER_PRIV_DIR -gnunet-ecc -g1 $MASTER_PRIV_FILE > /dev/null 2> /dev/null -MASTER_PUB=`gnunet-ecc -p $MASTER_PRIV_FILE` -EXCHANGE_URL=`taler-config -c $CONF -s EXCHANGE -o BASE_URL` -MERCHANT_PORT=`taler-config -c $CONF -s MERCHANT -o PORT` -MERCHANT_URL=http://localhost:${MERCHANT_PORT}/ -BANK_PORT=`taler-config -c $CONF -s BANK -o HTTP_PORT` -BANK_URL=http://localhost:${BANK_PORT}/ -AUDITOR_URL=http://localhost:8083/ -AUDITOR_PRIV_FILE=`taler-config -f -c $CONF -s AUDITOR -o AUDITOR_PRIV_FILE` -AUDITOR_PRIV_DIR=`dirname $AUDITOR_PRIV_FILE` -mkdir -p $AUDITOR_PRIV_DIR -gnunet-ecc -g1 $AUDITOR_PRIV_FILE > /dev/null 2> /dev/null -AUDITOR_PUB=`gnunet-ecc -p $AUDITOR_PRIV_FILE` - -# patch configuration -TALER_DB=talercheck -taler-config -c $CONF -s exchange -o MASTER_PUBLIC_KEY -V $MASTER_PUB -taler-config -c $CONF -s merchant-exchange-default -o MASTER_KEY -V $MASTER_PUB -taler-config -c $CONF -s exchangedb-postgres -o CONFIG -V postgres:///$TALER_DB -taler-config -c $CONF -s auditordb-postgres -o CONFIG -V postgres:///$TALER_DB -taler-config -c $CONF -s merchantdb-postgres -o CONFIG -V postgres:///$TALER_DB -taler-config -c $CONF -s bank -o database -V postgres:///$TALER_DB -taler-config -c $CONF -s exchange -o KEYDIR -V "${TMP_DIR}/keydir/" -taler-config -c $CONF -s exchange -o REVOCATION_DIR -V "${TMP_DIR}/revdir/" +# Cleanup to run whenever we exit +function cleanup() +{ + exit_cleanup + for n in $(jobs -p) + do + kill "$n" 2> /dev/null || true + done + rm -rf "$CONF" "$WALLET_DB" "$TFILE" "$UFILE" "$TMP_DIR" + wait +} -echo " OK" +CONF_1="test_anastasis_reducer_1.conf" +CONF_2="test_anastasis_reducer_2.conf" +CONF_3="test_anastasis_reducer_3.conf" +CONF_4="test_anastasis_reducer_4.conf" -echo -n "Setting up exchange ..." +# Exchange configuration file will be edited, so we create one +# from the template. +CONF="test_reducer.conf.edited" -# reset database -dropdb $TALER_DB >/dev/null 2>/dev/null || true -createdb $TALER_DB || exit_skip "Could not create database $TALER_DB" -taler-exchange-dbinit -c $CONF -taler-merchant-dbinit -c $CONF -taler-auditor-dbinit -c $CONF -taler-auditor-exchange -c $CONF -m $MASTER_PUB -u $EXCHANGE_URL +TMP_DIR=$(mktemp -p "${TMPDIR:-/tmp}" -d keys-tmp-XXXXXX) +WALLET_DB=$(mktemp -p "${TMPDIR:-/tmp}" test_reducer_walletXXXXXX.json) +TFILE=$(mktemp -p "${TMPDIR:-/tmp}" test_reducer_statePPXXXXXX) +UFILE=$(mktemp -p "${TMPDIR:-/tmp}" test_reducer_stateBFXXXXXX) -echo " OK" +# Install cleanup handler (except for kill -9) +trap cleanup EXIT -# Launch services -echo -n "Launching taler services ..." -taler-bank-manage-testing $CONF postgres:///$TALER_DB serve > taler-bank.log 2> taler-bank.err & -taler-exchange-secmod-eddsa -c $CONF 2> taler-exchange-secmod-eddsa.log & -taler-exchange-secmod-rsa -c $CONF 2> taler-exchange-secmod-rsa.log & -taler-exchange-httpd -c $CONF 2> taler-exchange-httpd.log & -taler-merchant-httpd -c $CONF -L INFO 2> taler-merchant-httpd.log & -taler-exchange-wirewatch -c $CONF 2> taler-exchange-wirewatch.log & -taler-auditor-httpd -L INFO -c $CONF 2> taler-auditor-httpd.log & + +echo -n "Initialize anastasis databases ..." +# Name of the Postgres database we will use for the script. +# Will be dropped, do NOT use anything that might be used +# elsewhere +TARGET_DB_1=$(anastasis-config -c "$CONF_1" -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///") +TARGET_DB_2=$(anastasis-config -c "$CONF_2" -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///") +TARGET_DB_3=$(anastasis-config -c "$CONF_3" -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///") +TARGET_DB_4=$(anastasis-config -c "$CONF_4" -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///") + +dropdb "$TARGET_DB_1" >/dev/null 2>/dev/null || true +createdb "$TARGET_DB_1" || exit_skip "Could not create database $TARGET_DB_1" +anastasis-dbinit -c "$CONF_1" 2> anastasis-dbinit_1.log +dropdb "$TARGET_DB_2" >/dev/null 2>/dev/null || true +createdb "$TARGET_DB_2" || exit_skip "Could not create database $TARGET_DB_2" +anastasis-dbinit -c "$CONF_2" 2> anastasis-dbinit_2.log +dropdb "$TARGET_DB_3" >/dev/null 2>/dev/null || true +createdb "$TARGET_DB_3" || exit_skip "Could not create database $TARGET_DB_3" +anastasis-dbinit -c "$CONF_3" 2> anastasis-dbinit_3.log +dropdb "$TARGET_DB_4" >/dev/null 2>/dev/null || true +createdb "$TARGET_DB_4" || exit_skip "Could not create database $TARGET_DB_4" +anastasis-dbinit -c "$CONF_4" 2> anastasis-dbinit_4.log echo " OK" @@ -165,82 +117,9 @@ $PREFIX anastasis-httpd -c $CONF_2 2> anastasis-httpd_2.log & $PREFIX anastasis-httpd -c $CONF_3 2> anastasis-httpd_3.log & $PREFIX anastasis-httpd -c $CONF_4 2> anastasis-httpd_4.log & -# Wait for bank to be available (usually the slowest) -for n in `seq 1 50` -do - echo -n "." - sleep 0.2 - OK=0 - # bank - wget --tries=1 --timeout=1 http://localhost:8082/ -o /dev/null -O /dev/null >/dev/null || continue - OK=1 - break -done - -if [ 1 != $OK ] -then - exit_skip "Failed to launch services (bank)" -fi - -# Wait for all other taler services to be available -for n in `seq 1 50` -do - echo -n "." - sleep 0.1 - OK=0 - # exchange - wget --tries=1 --timeout=1 http://localhost:8081/seed -o /dev/null -O /dev/null >/dev/null || continue - # merchant - wget --tries=1 --timeout=1 http://localhost:9966/ -o /dev/null -O /dev/null >/dev/null || continue - # auditor - wget --tries=1 --timeout=1 http://localhost:8083/ -o /dev/null -O /dev/null >/dev/null || continue - OK=1 - break -done - -if [ 1 != $OK ] -then - exit_skip "Failed to launch taler services" -fi - -echo "OK" - -echo -n "Setting up keys ..." -taler-exchange-offline -c $CONF \ - download \ - sign \ - enable-account payto://x-taler-bank/localhost/Exchange \ - enable-auditor $AUDITOR_PUB $AUDITOR_URL "TESTKUDOS Auditor" \ - wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 \ - upload &> taler-exchange-offline.log - -echo -n "." - -for n in `seq 1 3` -do - echo -n "." - OK=0 - wget --tries=1 --timeout=1 http://localhost:8081/keys -o /dev/null -O /dev/null >/dev/null || continue - OK=1 - break -done - -if [ 1 != $OK ] -then - exit_skip "Failed to setup keys" -fi - -echo " OK" - -echo -n "Setting up auditor signatures ..." -taler-auditor-offline -c $CONF \ - download sign upload &> taler-auditor-offline.log -echo " OK" - echo -n "Waiting for anastasis services ..." - # Wait for anastasis services to be available -for n in `seq 1 50` +for n in $(seq 1 50) do echo -n "." sleep 0.1 @@ -257,7 +136,7 @@ do break done -if [ 1 != $OK ] +if [ 1 != "$OK" ] then exit_skip "Failed to launch anastasis services" fi @@ -266,154 +145,193 @@ echo "OK" echo -n "Configuring merchant instance ..." # Setup merchant -curl -H "Content-Type: application/json" -X POST -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_ms" : 3600000},"default_pay_delay":{"d_ms": 3600000}}' http://localhost:9966/management/instances +curl -H "Content-Type: application/json" -X POST -d '{"auth":{"method":"external"},"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' http://localhost:9966/management/instances + + +curl -H "Content-Type: application/json" -X POST -d '{"payto_uri":"'"$MERCHANT_PAYTO"'"}' http://localhost:9966/private/accounts + echo " DONE" -echo -en $COLOR$BOLD"Test enter secret in a backup state ..."$NORM$NOCOLOR +echo -en "${COLOR}${BOLD}Test enter secret in a backup state ...${NORM}${NOCOLOR}" $PREFIX anastasis-reducer -a \ '{"secret": { "value" : "veryhardtoguesssecret", "mime" : "text/plain" } }' \ - enter_secret resources/06-backup.json $TFILE + enter_secret resources/06-backup.json "$TFILE" -STATE=`jq -r -e .backup_state < $TFILE` -if test "$STATE" != "SECRET_EDITING" +STATE=$(jq -r -e .backup_state < "$TFILE") +if [ "$STATE" != "SECRET_EDITING" ] then - jq -e . $TFILE + jq -e . "$TFILE" exit_fail "Expected new state to be 'SECRET_EDITING', got '$STATE'" fi echo " DONE" -echo -en $COLOR$BOLD"Test expiration change ..."$NORM$NOCOLOR +echo -en "${COLOR}${BOLD}Test expiration change ...${NORM}${NOCOLOR}" -MILLIS=`date '+%s'`000 +SECS=$(date '+%s') # Use 156 days into the future to get 1 year -MILLIS=`expr $MILLIS + 13478400000` +SECS=$(( SECS + 13478400 )) $PREFIX anastasis-reducer -a \ "$(jq -n ' - {"expiration": { "t_ms" : $MSEC } }' \ - --argjson MSEC $MILLIS + {"expiration": { "t_s" : $SEC } }' \ + --argjson SEC "$SECS" )" \ - update_expiration $TFILE $UFILE + update_expiration "$TFILE" "$UFILE" -STATE=`jq -r -e .backup_state < $UFILE` +STATE=$(jq -r -e .backup_state < "$UFILE") if test "$STATE" != "SECRET_EDITING" then - jq -e . $UFILE + jq -e . "$UFILE" exit_fail "Expected new state to be 'SECRET_EDITING', got '$STATE'" fi -FEES=`jq -r -e '.upload_fees[0].fee' < $UFILE` +FEES=$(jq -r -e '.upload_fees[0].fee' < "$UFILE") # 4x 4.99 for annual fees, plus 4x0.01 for truth uploads -if test "$FEES" != "TESTKUDOS:20" +if [ "$FEES" != "TESTKUDOS:20" ] then - jq -e . $TFILE + jq -e . "$UFILE" exit_fail "Expected upload fees to be 'TESTKUDOS:20', got '$FEES'" fi echo " DONE" -echo -en $COLOR$BOLD"Test advance to payment ..."$NORM$NOCOLOR +echo -en "${COLOR}${BOLD}Test advance to payment ...${NORM}${NOCOLOR}" -$PREFIX anastasis-reducer next $UFILE $TFILE +$PREFIX anastasis-reducer next "$UFILE" "$TFILE" -STATE=`jq -r -e .backup_state < $TFILE` -if test "$STATE" != "TRUTHS_PAYING" +STATE=$(jq -r -e .backup_state < "$TFILE") +if [ "$STATE" != "TRUTHS_PAYING" ] then - jq -e . $TFILE + jq -e . "$TFILE" exit_fail "Expected new state to be 'TRUTHS_PAYING', got '$STATE'" fi -TMETHOD=`jq -r -e '.policies[0].methods[0].truth.type' < $TFILE` -if test $TMETHOD != "question" -then - exit_fail "Expected method to be >='question', got $TMETHOD" -fi +# FIXME: this test is specific to how the +# C reducer stores state (redundantly!), should converge eventually! + +#TMETHOD=$(jq -r -e '.policies[0].methods[0].truth.type' < $TFILE) +#if test $TMETHOD != "question" +#then +# exit_fail "Expected method to be >='question', got $TMETHOD" +#fi +# +#echo " OK" + -echo " OK" #Pay -echo -en $COLOR$BOLD"Withdrawing amount to wallet ..."$NORM$NOCOLOR +echo -en "${COLOR}${BOLD}Withdrawing amount to wallet ...${NORM}${NOCOLOR}" + +EXCHANGE_URL="$(taler-config -c "$CONF" -s exchange -o BASE_URL)" -rm $WALLET_DB -taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api 'withdrawTestBalance' \ +rm "$WALLET_DB" +taler-wallet-cli \ + --no-throttle \ + --wallet-db="$WALLET_DB" \ + api \ + --expect-success 'withdrawTestBalance' \ "$(jq -n ' { amount: "TESTKUDOS:40", - bankBaseUrl: $BANK_URL, + corebankApiBaseUrl: $BANK_URL, exchangeBaseUrl: $EXCHANGE_URL }' \ - --arg BANK_URL "$BANK_URL" \ - --arg EXCHANGE_URL "$EXCHANGE_URL" - )" 2>wallet.err >wallet.log -taler-wallet-cli --wallet-db=$WALLET_DB run-until-done 2>wallet.err >wallet.log + --arg BANK_URL "${BANK_URL}" \ + --arg EXCHANGE_URL "${EXCHANGE_URL}" + )" 2>wallet-withdraw.err \ + >wallet-withdraw.log +taler-wallet-cli \ + --no-throttle \ + --wallet-db="$WALLET_DB" \ + run-until-done \ + 2>wallet-withdraw-finish.err \ + >wallet-withdraw-finish.log echo " OK" -echo -en $COLOR$BOLD"Making payments for truth uploads ... "$NORM$NOCOLOR -OBJECT_SIZE=`jq -r -e '.payments | length' < $TFILE` -for ((INDEX=0; INDEX < $OBJECT_SIZE; INDEX++)) +echo -en "${COLOR}${BOLD}Making payments for truth uploads ... ${NORM}${NOCOLOR}" +OBJECT_SIZE=$(jq -r -e '.payments | length' < "$TFILE") +for ((INDEX=0; INDEX < "$OBJECT_SIZE"; INDEX++)) do - PAY_URI=`jq --argjson INDEX $INDEX -r -e '.payments[$INDEX]' < $TFILE` + PAY_URI=$(jq --argjson INDEX $INDEX -r -e '.payments[$INDEX]' < "$TFILE") # run wallet CLI echo -n "$INDEX" - taler-wallet-cli --wallet-db=$WALLET_DB handle-uri $PAY_URI -y 2>wallet.err >wallet.log + taler-wallet-cli \ + --no-throttle \ + --wallet-db="$WALLET_DB" \ + handle-uri "${PAY_URI}" \ + -y \ + 2>wallet-pay1.err \ + >wallet-pay1.log echo -n "," done echo " OK" -echo -e $COLOR$BOLD"Running wallet run-pending..."$NORM$NOCOLOR -taler-wallet-cli --wallet-db=$WALLET_DB run-pending 2>wallet.err >wallet.log -echo -e $COLOR$BOLD"Payments done"$NORM$NOCOLOR - - -echo -en $COLOR$BOLD"Try to upload again ..."$NORM$NOCOLOR -$PREFIX anastasis-reducer pay $TFILE $UFILE -mv $UFILE $TFILE +echo -e "${COLOR}${BOLD}Running wallet run-until-done...${NORM}${NOCOLOR}" +taler-wallet-cli \ + --wallet-db="$WALLET_DB" \ + run-until-done \ + 2>wallet-pay-finish.err \ + >wallet-pay-finish.log +echo -e "${COLOR}${BOLD}Payments done${NORM}${NOCOLOR}" + + +echo -en "${COLOR}${BOLD}Try to upload again ...${NORM}${NOCOLOR}" +$PREFIX anastasis-reducer pay "$TFILE" "$UFILE" +mv "$UFILE" "$TFILE" echo " OK" -STATE=`jq -r -e .backup_state < $TFILE` -if test "$STATE" != "POLICIES_PAYING" +STATE="$(jq -r -e .backup_state < "$TFILE")" +if [ "$STATE" != "POLICIES_PAYING" ] then exit_fail "Expected new state to be 'POLICIES_PAYING', got '$STATE'" fi -export TFILE -export UFILE - -echo -en $COLOR$BOLD"Making payments for policy uploads ... "$NORM$NOCOLOR -OBJECT_SIZE=`jq -r -e '.policy_payment_requests | length' < $TFILE` -for ((INDEX=0; INDEX < $OBJECT_SIZE; INDEX++)) +echo -en "${COLOR}${BOLD}Making payments for policy uploads ... ${NORM}${NOCOLOR}" +OBJECT_SIZE="$(jq -r -e '.policy_payment_requests | length' < "$TFILE")" +for ((INDEX=0; INDEX < "$OBJECT_SIZE"; INDEX++)) do - PAY_URI=`jq --argjson INDEX $INDEX -r -e '.policy_payment_requests[$INDEX].payto' < $TFILE` + PAY_URI="$(jq --argjson INDEX "$INDEX" -r -e '.policy_payment_requests[$INDEX].payto' < "$TFILE")" # run wallet CLI export PAY_URI echo -n "$INDEX" - taler-wallet-cli --wallet-db=$WALLET_DB handle-uri $PAY_URI -y 2>wallet.err >wallet.log + taler-wallet-cli \ + --wallet-db="$WALLET_DB" \ + handle-uri "$PAY_URI" \ + -y \ + 2>"wallet-pay2-$INDEX.err" \ + >"wallet-pay2-$INDEX.log" echo -n "," done echo " OK" -echo -e $COLOR$BOLD"Running wallet run-pending..."$NORM$NOCOLOR -taler-wallet-cli --wallet-db=$WALLET_DB run-pending 2>wallet.err >wallet.log -echo -e $COLOR$BOLD"Payments done"$NORM$NOCOLOR +echo -e "${COLOR}${BOLD}Running wallet run-until-done...${NORM}${NOCOLOR}" +taler-wallet-cli \ + --wallet-db="$WALLET_DB" \ + run-until-done \ + 2>wallet-pay2-finish.err \ + >wallet-pay2-finish.log +echo -e "${COLOR}${BOLD}Payments done${NORM}${NOCOLOR}" -echo -en $COLOR$BOLD"Try to upload again ..."$NORM$NOCOLOR -$PREFIX anastasis-reducer pay $TFILE $UFILE +echo -en "${COLOR}${BOLD}Try to upload again ...${NORM}${NOCOLOR}" +$PREFIX anastasis-reducer pay "$TFILE" "$UFILE" echo " OK" echo -n "Final checks ..." -STATE=`jq -r -e .backup_state < $UFILE` -if test "$STATE" != "BACKUP_FINISHED" +STATE=$(jq -r -e .backup_state < "$UFILE") +if [ "$STATE" != "BACKUP_FINISHED" ] then exit_fail "Expected new state to be BACKUP_FINISHED, got $STATE" fi -jq -r -e .core_secret < $UFILE > /dev/null && exit_fail "'core_secret' was not cleared upon success" +jq -r -e .core_secret \ + < "$UFILE" \ + > /dev/null \ + && exit_fail "'core_secret' was not cleared upon success" echo " OK" - exit 0 diff --git a/src/cli/test_anastasis_reducer_free_1.conf b/src/cli/test_anastasis_reducer_free_1.conf new file mode 100644 index 0000000..0e7ad9a --- /dev/null +++ b/src/cli/test_anastasis_reducer_free_1.conf @@ -0,0 +1,10 @@ +# This file is in the public domain. +@INLINE@ test_reducer_free.conf + +[anastasis] +PORT = 8086 +PROVIDER_SALT = AUfO1KGOKYIFlFQg +BUSINESS_NAME = "Data loss #1 Inc." + +[stasis-postgres] +CONFIG = postgres:///anastasischeck1 diff --git a/src/cli/test_anastasis_reducer_free_2.conf b/src/cli/test_anastasis_reducer_free_2.conf new file mode 100644 index 0000000..a628ff4 --- /dev/null +++ b/src/cli/test_anastasis_reducer_free_2.conf @@ -0,0 +1,10 @@ +# This file is in the public domain. +@INLINE@ test_reducer_free.conf + +[anastasis] +PORT = 8087 +PROVIDER_SALT = BUfO1KGOKYIFlFQg +BUSINESS_NAME = "Data loss #2 Inc." + +[stasis-postgres] +CONFIG = postgres:///anastasischeck2 diff --git a/src/cli/test_anastasis_reducer_free_3.conf b/src/cli/test_anastasis_reducer_free_3.conf new file mode 100644 index 0000000..adbe392 --- /dev/null +++ b/src/cli/test_anastasis_reducer_free_3.conf @@ -0,0 +1,10 @@ +# This file is in the public domain. +@INLINE@ test_reducer_free.conf + +[anastasis] +PORT = 8088 +PROVIDER_SALT = CUfO1KGOKYIFlFQg +BUSINESS_NAME = "Data loss #3 Inc." + +[stasis-postgres] +CONFIG = postgres:///anastasischeck3 diff --git a/src/cli/test_anastasis_reducer_free_4.conf b/src/cli/test_anastasis_reducer_free_4.conf new file mode 100644 index 0000000..cd0c701 --- /dev/null +++ b/src/cli/test_anastasis_reducer_free_4.conf @@ -0,0 +1,10 @@ +# This file is in the public domain. +@INLINE@ test_reducer_free.conf + +[anastasis] +PORT = 8089 +PROVIDER_SALT = DUfO1KGOKYIFlFQg +BUSINESS_NAME = "Data loss #4 Inc." + +[stasis-postgres] +CONFIG = postgres:///anastasischeck4 diff --git a/src/cli/test_anastasis_reducer_recovery_enter_user_attributes.sh b/src/cli/test_anastasis_reducer_recovery_enter_user_attributes.sh index d65020e..551ab36 100755 --- a/src/cli/test_anastasis_reducer_recovery_enter_user_attributes.sh +++ b/src/cli/test_anastasis_reducer_recovery_enter_user_attributes.sh @@ -1,52 +1,26 @@ #!/bin/bash # This file is in the public domain. -set -eu - -# Exit, with status code "skip" (no 'real' failure) -function exit_skip() { - echo " SKIP: $1" - exit 77 -} - -# Exit, with error message (hard failure) -function exit_fail() { - echo " FAIL: $1" - exit 1 -} - -# Cleanup to run whenever we exit -function cleanup() -{ - for n in `jobs -p` - do - kill $n 2> /dev/null || true - done - rm -rf $CONF $WALLET_DB $R1FILE $R2FILE $B1FILE $B2FILE $TMP_DIR - wait -} - +# shellcheck disable=SC2317 -CONF_1="test_anastasis_reducer_1.conf" -CONF_2="test_anastasis_reducer_2.conf" -CONF_3="test_anastasis_reducer_3.conf" -CONF_4="test_anastasis_reducer_4.conf" - - -# Configuration file will be edited, so we create one -# from the template. -CONF=`mktemp test_reducerXXXXXX.conf` -cp test_reducer.conf $CONF - -TMP_DIR=`mktemp -d keys-tmp-XXXXXX` -WALLET_DB=`mktemp test_reducer_walletXXXXXX.json` -B1FILE=`mktemp test_reducer_stateB1XXXXXX` -B2FILE=`mktemp test_reducer_stateB2XXXXXX` -R1FILE=`mktemp test_reducer_stateR1XXXXXX` -R2FILE=`mktemp test_reducer_stateR2XXXXXX` +set -eu -# Install cleanup handler (except for kill -9) -trap cleanup EXIT +# Replace with 0 for nexus... +USE_FAKEBANK=1 +if [ 1 = "$USE_FAKEBANK" ] +then + ACCOUNT="exchange-account-2" + WIRE_METHOD="x-taler-bank" + BANK_FLAGS="-f -d $WIRE_METHOD -u $ACCOUNT" + BANK_URL="http://localhost:18082/" + MERCHANT_PAYTO="payto://x-taler-bank/localhost/anastasis?receiver-name=anastasis" +else + ACCOUNT="exchange-account-1" + WIRE_METHOD="iban" + BANK_FLAGS="-ns -d $WIRE_METHOD -u $ACCOUNT" + BANK_URL="http://localhost:18082/" + MERCHANT_PAYTO="payto://iban/SANDBOXX/DE648226?receiver-name=anastasis" +fi # Check we can actually run echo -n "Testing for jq" @@ -61,9 +35,6 @@ taler-exchange-httpd -h > /dev/null || exit_skip " taler-exchange required" taler-merchant-httpd -h > /dev/null || exit_skip " taler-merchant required" echo " FOUND" -echo -n "Testing for taler-bank-manage" -taler-bank-manage --help >/dev/null </dev/null || exit_skip " MISSING" -echo " FOUND" echo -n "Testing for taler-wallet-cli" taler-wallet-cli -v >/dev/null </dev/null || exit_skip " MISSING" echo " FOUND" @@ -72,173 +43,117 @@ echo -n "Testing for anastasis-httpd" anastasis-httpd -h >/dev/null </dev/null || exit_skip " MISSING" echo " FOUND" -echo -n "Initialize anastasis database ..." -# Name of the Postgres database we will use for the script. -# Will be dropped, do NOT use anything that might be used -# elsewhere -TARGET_DB_1=`anastasis-config -c $CONF_1 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` -TARGET_DB_2=`anastasis-config -c $CONF_2 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` -TARGET_DB_3=`anastasis-config -c $CONF_3 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` -TARGET_DB_4=`anastasis-config -c $CONF_4 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` - -dropdb $TARGET_DB_1 >/dev/null 2>/dev/null || true -createdb $TARGET_DB_1 || exit_skip "Could not create database $TARGET_DB_1" -anastasis-dbinit -c $CONF_1 2> anastasis-dbinit_1.log -dropdb $TARGET_DB_2 >/dev/null 2>/dev/null || true -createdb $TARGET_DB_2 || exit_skip "Could not create database $TARGET_DB_2" -anastasis-dbinit -c $CONF_2 2> anastasis-dbinit_2.log -dropdb $TARGET_DB_3 >/dev/null 2>/dev/null || true -createdb $TARGET_DB_3 || exit_skip "Could not create database $TARGET_DB_3" -anastasis-dbinit -c $CONF_3 2> anastasis-dbinit_3.log -dropdb $TARGET_DB_4 >/dev/null 2>/dev/null || true -createdb $TARGET_DB_4 || exit_skip "Could not create database $TARGET_DB_4" -anastasis-dbinit -c $CONF_4 2> anastasis-dbinit_4.log +. setup.sh +# Launch exchange, merchant and bank. +# shellcheck disable=SC2086 +setup -c "test_reducer.conf" \ + -aemw \ + $BANK_FLAGS -echo " OK" +# Cleanup to run whenever we exit +function cleanup() +{ + exit_cleanup + for n in $(jobs -p) + do + kill "$n" 2> /dev/null || true + done + rm -rf "$CONF" "$WALLET_DB" "$R1FILE" "$R2FILE" "$B1FILE" "$B2FILE" "$TMP_DIR" + wait +} -echo -n "Generating Taler auditor, exchange and merchant configurations ..." - -DATA_DIR=`taler-config -f -c $CONF -s PATHS -o TALER_HOME` -rm -rf $DATA_DIR - -# obtain key configuration data -MASTER_PRIV_FILE=`taler-config -f -c $CONF -s "EXCHANGE-OFFLINE" -o "MASTER_PRIV_FILE"` -MASTER_PRIV_DIR=`dirname $MASTER_PRIV_FILE` -mkdir -p $MASTER_PRIV_DIR -gnunet-ecc -g1 $MASTER_PRIV_FILE > /dev/null 2> /dev/null -MASTER_PUB=`gnunet-ecc -p $MASTER_PRIV_FILE` -EXCHANGE_URL=`taler-config -c $CONF -s EXCHANGE -o BASE_URL` -MERCHANT_PORT=`taler-config -c $CONF -s MERCHANT -o PORT` -MERCHANT_URL=http://localhost:${MERCHANT_PORT}/ -BANK_PORT=`taler-config -c $CONF -s BANK -o HTTP_PORT` -BANK_URL=http://localhost:${BANK_PORT}/ -AUDITOR_URL=http://localhost:8083/ -AUDITOR_PRIV_FILE=`taler-config -f -c $CONF -s AUDITOR -o AUDITOR_PRIV_FILE` -AUDITOR_PRIV_DIR=`dirname $AUDITOR_PRIV_FILE` -mkdir -p $AUDITOR_PRIV_DIR -gnunet-ecc -g1 $AUDITOR_PRIV_FILE > /dev/null 2> /dev/null -AUDITOR_PUB=`gnunet-ecc -p $AUDITOR_PRIV_FILE` - -# patch configuration -TALER_DB=talercheck -taler-config -c $CONF -s exchange -o MASTER_PUBLIC_KEY -V $MASTER_PUB -taler-config -c $CONF -s merchant-exchange-default -o MASTER_KEY -V $MASTER_PUB -taler-config -c $CONF -s exchangedb-postgres -o CONFIG -V postgres:///$TALER_DB -taler-config -c $CONF -s auditordb-postgres -o CONFIG -V postgres:///$TALER_DB -taler-config -c $CONF -s merchantdb-postgres -o CONFIG -V postgres:///$TALER_DB -taler-config -c $CONF -s bank -o database -V postgres:///$TALER_DB -taler-config -c $CONF -s exchange -o KEYDIR -V "${TMP_DIR}/keydir/" -taler-config -c $CONF -s exchange -o REVOCATION_DIR -V "${TMP_DIR}/revdir/" +function sync_providers() { + infile=$1 + outfile=$2 + echo "Synchronizing providers" + # Sync with providers (up to 3 providers aren't synced here) + for x in 1 2 3; do + echo "Synchronizing providers (round $x)" + anastasis-reducer sync_providers < "$infile" > "$outfile" 2> /dev/null || true + CODE=$(jq -r -e ".code // 0" < "$outfile") + # ANASTASIS_REDUCER_PROVIDERS_ALREADY_SYNCED + # FIXME: Temporary workaround for C reducer. See #7227. + if [ "$CODE" = "8420" ] + then + # restore previous non-error state + cat "$infile" > "$outfile" + break + fi + # ANASTASIS_REDUCER_ACTION_INVALID + if [ "$CODE" = "8400" ] + then + # restore previous non-error state + cat "$infile" > "$outfile" + break + fi + if [ "$CODE" != "0" ] + then + exit_fail "Expected no error or 8420/8400, got $CODE" + fi + cat "$outfile" > "$infile" + done + echo "Providers synced." +} -echo " OK" -echo -n "Setting up exchange ..." +CONF_1="test_anastasis_reducer_1.conf" +CONF_2="test_anastasis_reducer_2.conf" +CONF_3="test_anastasis_reducer_3.conf" +CONF_4="test_anastasis_reducer_4.conf" -# reset database -dropdb $TALER_DB >/dev/null 2>/dev/null || true -createdb $TALER_DB || exit_skip "Could not create database $TALER_DB" -taler-exchange-dbinit -c $CONF -taler-merchant-dbinit -c $CONF -taler-auditor-dbinit -c $CONF -taler-auditor-exchange -c $CONF -m $MASTER_PUB -u $EXCHANGE_URL -echo " OK" +# Configuration file will be edited, so we create one +# from the template. +CONF="$(mktemp -p "${TMPDIR:-/tmp}" test_reducerXXXXXX.conf)" +cp test_reducer.conf "$CONF" -# Launch services -echo -n "Launching taler services ..." -taler-bank-manage-testing $CONF postgres:///$TALER_DB serve > taler-bank.log 2> taler-bank.err & -taler-exchange-secmod-eddsa -c $CONF 2> taler-exchange-secmod-eddsa.log & -taler-exchange-secmod-rsa -c $CONF 2> taler-exchange-secmod-rsa.log & -taler-exchange-httpd -c $CONF 2> taler-exchange-httpd.log & -taler-merchant-httpd -c $CONF -L INFO 2> taler-merchant-httpd.log & -taler-exchange-wirewatch -c $CONF 2> taler-exchange-wirewatch.log & -taler-auditor-httpd -L INFO -c $CONF 2> taler-auditor-httpd.log & +TMP_DIR=$(mktemp -p "${TMPDIR:-/tmp}" -d keys-tmp-XXXXXX) +WALLET_DB=$(mktemp -p "${TMPDIR:-/tmp}" test_reducer_walletXXXXXX.json) +B1FILE=$(mktemp -p "${TMPDIR:-/tmp}" test_reducer_stateB1XXXXXX) +B2FILE=$(mktemp -p "${TMPDIR:-/tmp}" test_reducer_stateB2XXXXXX) +R1FILE=$(mktemp -p "${TMPDIR:-/tmp}" test_reducer_stateR1XXXXXX) +R2FILE=$(mktemp -p "${TMPDIR:-/tmp}" test_reducer_stateR2XXXXXX) + +# Install cleanup handler (except for kill -9) +trap cleanup EXIT + +echo -n "Initialize anastasis database ..." +# Name of the Postgres database we will use for the script. +# Will be dropped, do NOT use anything that might be used +# elsewhere +TARGET_DB_1=$(anastasis-config -c $CONF_1 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///") +TARGET_DB_2=$(anastasis-config -c $CONF_2 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///") +TARGET_DB_3=$(anastasis-config -c $CONF_3 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///") +TARGET_DB_4=$(anastasis-config -c $CONF_4 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///") + +dropdb "$TARGET_DB_1" >/dev/null 2>/dev/null || true +createdb "$TARGET_DB_1" || exit_skip "Could not create database $TARGET_DB_1" +anastasis-dbinit -c "$CONF_1" 2> anastasis-dbinit_1.log +dropdb "$TARGET_DB_2" >/dev/null 2>/dev/null || true +createdb "$TARGET_DB_2" || exit_skip "Could not create database $TARGET_DB_2" +anastasis-dbinit -c "$CONF_2" 2> anastasis-dbinit_2.log +dropdb "$TARGET_DB_3" >/dev/null 2>/dev/null || true +createdb "$TARGET_DB_3" || exit_skip "Could not create database $TARGET_DB_3" +anastasis-dbinit -c "$CONF_3" 2> anastasis-dbinit_3.log +dropdb "$TARGET_DB_4" >/dev/null 2>/dev/null || true +createdb "$TARGET_DB_4" || exit_skip "Could not create database $TARGET_DB_4" +anastasis-dbinit -c "$CONF_4" 2> anastasis-dbinit_4.log echo " OK" echo -n "Launching anastasis services ..." PREFIX="" #valgrind -$PREFIX anastasis-httpd -c $CONF_1 2> anastasis-httpd_1.log & -$PREFIX anastasis-httpd -c $CONF_2 2> anastasis-httpd_2.log & -$PREFIX anastasis-httpd -c $CONF_3 2> anastasis-httpd_3.log & -$PREFIX anastasis-httpd -c $CONF_4 2> anastasis-httpd_4.log & - -# Wait for bank to be available (usually the slowest) -for n in `seq 1 50` -do - echo -n "." - sleep 0.2 - OK=0 - # bank - wget --tries=1 --timeout=1 http://localhost:8082/ -o /dev/null -O /dev/null >/dev/null || continue - OK=1 - break -done - -if [ 1 != $OK ] -then - exit_skip "Failed to launch services (bank)" -fi - -# Wait for all other taler services to be available -for n in `seq 1 50` -do - echo -n "." - sleep 0.1 - OK=0 - # exchange - wget --tries=1 --timeout=1 http://localhost:8081/seed -o /dev/null -O /dev/null >/dev/null || continue - # merchant - wget --tries=1 --timeout=1 http://localhost:9966/ -o /dev/null -O /dev/null >/dev/null || continue - # auditor - wget --tries=1 --timeout=1 http://localhost:8083/ -o /dev/null -O /dev/null >/dev/null || continue - OK=1 - break -done - -if [ 1 != $OK ] -then - exit_skip "Failed to launch taler services" -fi +$PREFIX anastasis-httpd -c "$CONF_1" 2> anastasis-httpd_1.log & +$PREFIX anastasis-httpd -c "$CONF_2" 2> anastasis-httpd_2.log & +$PREFIX anastasis-httpd -c "$CONF_3" 2> anastasis-httpd_3.log & +$PREFIX anastasis-httpd -c "$CONF_4" 2> anastasis-httpd_4.log & echo "OK" -echo -n "Setting up keys ..." -taler-exchange-offline -c $CONF \ - download \ - sign \ - enable-account payto://x-taler-bank/localhost/Exchange \ - enable-auditor $AUDITOR_PUB $AUDITOR_URL "TESTKUDOS Auditor" \ - wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 \ - upload &> taler-exchange-offline.log - -echo -n "." - -for n in `seq 1 3` -do - echo -n "." - OK=0 - wget --tries=1 --timeout=1 http://localhost:8081/keys -o /dev/null -O /dev/null >/dev/null || continue - OK=1 - break -done - -if [ 1 != $OK ] -then - exit_skip "Failed to setup keys" -fi - -echo " OK" - -echo -n "Setting up auditor signatures ..." -taler-auditor-offline -c $CONF \ - download sign upload &> taler-auditor-offline.log -echo " OK" - echo -n "Waiting for anastasis services ..." # Wait for anastasis services to be available -for n in `seq 1 50` +for n in $(seq 1 50) do echo -n "." sleep 0.1 @@ -255,7 +170,7 @@ do break done -if [ 1 != $OK ] +if [ 1 != "$OK" ] then exit_skip "Failed to launch anastasis services" fi @@ -264,29 +179,32 @@ echo "OK" echo -n "Configuring merchant instance ..." # Setup merchant -curl -H "Content-Type: application/json" -X POST -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_ms" : 3600000},"default_pay_delay":{"d_ms": 3600000}}' http://localhost:9966/management/instances +curl -H "Content-Type: application/json" -X POST -d '{"auth":{"method":"external"},"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' http://localhost:9966/management/instances +curl -H "Content-Type: application/json" -X POST -d '{"payto_uri":"'"$MERCHANT_PAYTO"'"}' http://localhost:9966/private/accounts echo " DONE" echo -n "Running backup logic ...," -anastasis-reducer -b > $B1FILE +anastasis-reducer -b > "$B1FILE" echo -n "." anastasis-reducer -a \ - '{"continent": "Testcontinent"}' \ - select_continent < $B1FILE > $B2FILE + '{"continent": "Demoworld"}' \ + select_continent < "$B1FILE" > "$B2FILE" echo -n "." anastasis-reducer -a \ - '{"country_code": "xx", - "currencies":["TESTKUDOS"]}' \ - select_country < $B2FILE > $B1FILE + '{"country_code": "xx"}' \ + select_country < "$B2FILE" > "$B1FILE" echo -n "." anastasis-reducer -a \ '{"identity_attributes": { "full_name": "Max Musterman", "sq_number": "4", "birthdate": "2000-01-01"}}' \ - enter_user_attributes < $B1FILE > $B2FILE + enter_user_attributes < "$B1FILE" > "$B2FILE" +cat "$B2FILE" > "$B1FILE" +echo -n "," +sync_providers "$B1FILE" "$B2FILE" echo -n "," # "91GPWWR" encodes "Hans" anastasis-reducer -a \ @@ -295,7 +213,7 @@ anastasis-reducer -a \ "instructions": "What is your name?", "challenge": "91GPWWR" } }' \ - add_authentication < $B2FILE > $B1FILE + add_authentication < "$B2FILE" > "$B1FILE" echo -n "." # "64S36" encodes "123" anastasis-reducer -a \ @@ -304,7 +222,7 @@ anastasis-reducer -a \ "instructions": "How old are you?", "challenge": "64S36" } }' \ - add_authentication < $B1FILE > $B2FILE + add_authentication < "$B1FILE" > "$B2FILE" echo -n "." # "9NGQ4WR" encodes "Mars" anastasis-reducer -a \ @@ -313,149 +231,177 @@ anastasis-reducer -a \ "instructions": "Where do you live?", "challenge": "9NGQ4WR" } }' \ - add_authentication < $B2FILE > $B1FILE + add_authentication < "$B2FILE" > "$B1FILE" echo -n "." # Finished adding authentication methods anastasis-reducer \ - next < $B1FILE > $B2FILE + next < "$B1FILE" > "$B2FILE" echo -n "," # Finished policy review anastasis-reducer \ - next < $B2FILE > $B1FILE + next < "$B2FILE" > "$B1FILE" echo -n "." # Note: 'secret' must here be a Crockford base32-encoded value anastasis-reducer -a \ '{"secret": { "value" : "VERYHARDT0GVESSSECRET", "mime" : "text/plain" }}' \ - enter_secret < $B1FILE > $B2FILE -mv $B2FILE $B1FILE -anastasis-reducer next $B1FILE $B2FILE + enter_secret < "$B1FILE" > "$B2FILE" +mv "$B2FILE" "$B1FILE" +anastasis-reducer next "$B1FILE" "$B2FILE" echo " OK" echo -n "Preparing wallet" -rm $WALLET_DB -taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api 'withdrawTestBalance' \ + +EXCHANGE_URL="$(taler-config -c "$CONF" -s exchange -o BASE_URL)" + +rm -f "$WALLET_DB" +taler-wallet-cli --no-throttle --wallet-db="$WALLET_DB" api --expect-success 'withdrawTestBalance' \ "$(jq -n ' { amount: "TESTKUDOS:100", - bankBaseUrl: $BANK_URL, + corebankApiBaseUrl: $BANK_URL, exchangeBaseUrl: $EXCHANGE_URL }' \ - --arg BANK_URL "$BANK_URL" \ + --arg BANK_URL "${BANK_URL}" \ --arg EXCHANGE_URL "$EXCHANGE_URL" - )" 2> /dev/null >/dev/null -taler-wallet-cli --wallet-db=$WALLET_DB run-until-done 2>/dev/null >/dev/null + )" 2> wallet-withdraw.err > wallet-withdraw.out +taler-wallet-cli \ + --wallet-db="$WALLET_DB" \ + run-until-done \ + 2>wallet-withdraw-finish.err \ + >wallet-withdraw-finish.out echo " OK" echo -en "Making payments for truth uploads ... " -OBJECT_SIZE=`jq -r -e '.payments | length' < $B2FILE` -for ((INDEX=0; INDEX < $OBJECT_SIZE; INDEX++)) +OBJECT_SIZE=$(jq -r -e '.payments | length' < "$B2FILE") +for ((INDEX=0; INDEX < "$OBJECT_SIZE"; INDEX++)) do - PAY_URI=`jq --argjson INDEX $INDEX -r -e '.payments[$INDEX]' < $B2FILE` + PAY_URI=$(jq --argjson INDEX $INDEX -r -e '.payments[$INDEX]' < "$B2FILE") # run wallet CLI echo -n "$INDEX" - taler-wallet-cli --wallet-db=$WALLET_DB handle-uri $PAY_URI -y 2>/dev/null >/dev/null + taler-wallet-cli \ + --wallet-db="$WALLET_DB" \ + handle-uri "$PAY_URI" \ + -y \ + 2>"wallet-pay-truth-$INDEX.err" \ + >"wallet-pay-truth-$INDEX.out" echo -n ", " done echo "OK" -echo -e "Running wallet run-pending..." -taler-wallet-cli --wallet-db=$WALLET_DB run-pending 2>/dev/null >/dev/null +echo -e "Running wallet run-until-done..." +taler-wallet-cli \ + --wallet-db="$WALLET_DB" \ + run-until-done \ + 2>"wallet-pay-truth-finish-$INDEX.err" \ + >"wallet-pay-truth-finish-$INDEX.out" echo -e "Payments done" -export B2FILE -export B1FILE - echo -en "Try to upload again ..." -$PREFIX anastasis-reducer pay $B2FILE $B1FILE -mv $B1FILE $B2FILE +$PREFIX anastasis-reducer pay "$B2FILE" "$B1FILE" +mv "$B1FILE" "$B2FILE" echo " OK" echo -en "Making payments for policy uploads ... " -OBJECT_SIZE=`jq -r -e '.policy_payment_requests | length' < $B2FILE` -for ((INDEX=0; INDEX < $OBJECT_SIZE; INDEX++)) +OBJECT_SIZE=$(jq -r -e '.policy_payment_requests | length' < "$B2FILE") +for ((INDEX=0; INDEX < "$OBJECT_SIZE"; INDEX++)) do - PAY_URI=`jq --argjson INDEX $INDEX -r -e '.policy_payment_requests[$INDEX].payto' < $B2FILE` + PAY_URI=$(jq --argjson INDEX $INDEX -r -e '.policy_payment_requests[$INDEX].payto' < "$B2FILE") # run wallet CLI echo -n "$INDEX" - taler-wallet-cli --wallet-db=$WALLET_DB handle-uri $PAY_URI -y 2>/dev/null >/dev/null + taler-wallet-cli \ + --wallet-db="$WALLET_DB" \ + handle-uri "$PAY_URI" \ + -y \ + 2>"wallet-pay-policy-$INDEX.err" \ + >"wallet-pay-policy-$INDEX.out" echo -n ", " done echo " OK" -echo -en "Running wallet run-pending..." -taler-wallet-cli --wallet-db=$WALLET_DB run-pending 2>/dev/null >/dev/null +echo -en "Running wallet run-until-done..." +taler-wallet-cli \ + --wallet-db="$WALLET_DB" \ + run-until-done \ + 2>wallet-pay-policy-finish.err \ + >wallet-pay-policy-finish.out echo -e " payments DONE" echo -en "Try to upload again ..." anastasis-reducer \ - pay < $B2FILE > $B1FILE + pay < "$B2FILE" > "$B1FILE" echo " OK: Backup finished" echo -n "Final backup checks ..." -STATE=`jq -r -e .backup_state < $B1FILE` -if test "$STATE" != "BACKUP_FINISHED" +STATE=$(jq -r -e .backup_state < "$B1FILE") +if [ "$STATE" != "BACKUP_FINISHED" ] then exit_fail "Expected new state to be 'BACKUP_FINISHED', got '$STATE'" fi -jq -r -e .core_secret < $B1FILE > /dev/null && exit_fail "'core_secret' was not cleared upon success" +jq -r -e .core_secret < "$B1FILE" > /dev/null && exit_fail "'core_secret' was not cleared upon success" echo " OK" echo -n "Running recovery basic logic ..." -anastasis-reducer -r > $R1FILE +anastasis-reducer -r > "$R1FILE" anastasis-reducer -a \ - '{"continent": "Testcontinent"}' \ - select_continent < $R1FILE > $R2FILE + '{"continent": "Demoworld"}' \ + select_continent < "$R1FILE" > "$R2FILE" anastasis-reducer -a \ - '{"country_code": "xx", - "currencies":["TESTKUDOS"]}' \ - select_country < $R2FILE > $R1FILE -anastasis-reducer -a '{"identity_attributes": { "full_name": "Max Musterman", "sq_number": "4", "birthdate": "2000-01-01" }}' enter_user_attributes < $R1FILE > $R2FILE + '{"country_code": "xx"}' \ + select_country < "$R2FILE" > "$R1FILE" +anastasis-reducer -a '{"identity_attributes": { "full_name": "Max Musterman", "sq_number": "4", "birthdate": "2000-01-01" }}' enter_user_attributes < "$R1FILE" > "$R2FILE" -STATE=`jq -r -e .recovery_state < $R2FILE` -if test "$STATE" != "SECRET_SELECTING" +STATE=$(jq -r -e .recovery_state < "$R2FILE") +if [ "$STATE" != "SECRET_SELECTING" ] then exit_fail "Expected new state to be 'SECRET_SELECTING', got '$STATE'" fi echo " OK" -echo -n "Selecting default secret" -mv $R2FILE $R1FILE -anastasis-reducer next < $R1FILE > $R2FILE +echo -n "Adding provider (to ensure it is loaded)" +anastasis-reducer -a '{"provider_url" : "http://localhost:8086/" }' add_provider < "$R2FILE" > "$R1FILE" +echo " OK" + +echo -n "Selecting secret to recover" +anastasis-reducer -a '{"attribute_mask": 0, "providers" : [ { "version": 1, "url" : "http://localhost:8086/" } ] }' select_version < "$R1FILE" > "$R2FILE" -STATE=`jq -r -e .recovery_state < $R2FILE` -if test "$STATE" != "CHALLENGE_SELECTING" +STATE=$(jq -r -e .recovery_state < "$R2FILE") +if [ "$STATE" != "CHALLENGE_SELECTING" ] then exit_fail "Expected new state to be 'CHALLENGE_SELECTING', got '$STATE'" fi echo " OK" +cat "$R2FILE" > "$R1FILE" + +sync_providers "$R1FILE" "$R2FILE" + echo -n "Running challenge logic ..." -UUID0=`jq -r -e .recovery_information.challenges[0].uuid < $R2FILE` -UUID1=`jq -r -e .recovery_information.challenges[1].uuid < $R2FILE` -UUID2=`jq -r -e .recovery_information.challenges[2].uuid < $R2FILE` -UUID0Q=`jq -r -e .recovery_information.challenges[0].instructions < $R2FILE` -UUID1Q=`jq -r -e .recovery_information.challenges[1].instructions < $R2FILE` -UUID2Q=`jq -r -e .recovery_information.challenges[2].instructions < $R2FILE` +UUID0=$(jq -r -e .recovery_information.challenges[0].uuid < "$R2FILE") +UUID1=$(jq -r -e .recovery_information.challenges[1].uuid < "$R2FILE") +UUID2=$(jq -r -e .recovery_information.challenges[2].uuid < "$R2FILE") +#UUID0Q=$(jq -r -e .recovery_information.challenges[0].instructions < "$R2FILE") +UUID1Q=$(jq -r -e .recovery_information.challenges[1].instructions < "$R2FILE") +UUID2Q=$(jq -r -e .recovery_information.challenges[2].instructions < "$R2FILE") -if test "$UUID2Q" = 'How old are you?' +if [ "$UUID2Q" = 'How old are you?' ] then AGE_UUID=$UUID2 -elif test "$UUID1Q" = 'How old are you?' +elif [ "$UUID1Q" = 'How old are you?' ] then AGE_UUID=$UUID1 else AGE_UUID=$UUID0 fi -if test "$UUID2Q" = 'What is your name?' +if [ "$UUID2Q" = 'What is your name?' ] then NAME_UUID=$UUID2 -elif test "$UUID1Q" = 'What is your name?' +elif [ "$UUID1Q" = 'What is your name?' ] then NAME_UUID=$UUID1 else @@ -469,10 +415,10 @@ anastasis-reducer -a \ }' \ --arg UUID "$NAME_UUID" )" \ - select_challenge < $R2FILE > $R1FILE + select_challenge < "$R2FILE" > "$R1FILE" anastasis-reducer -a '{"answer": "Hans"}' \ - solve_challenge < $R1FILE > $R2FILE + solve_challenge < "$R1FILE" > "$R2FILE" anastasis-reducer -a \ "$(jq -n ' @@ -481,34 +427,34 @@ anastasis-reducer -a \ }' \ --arg UUID "$AGE_UUID" )" \ - select_challenge < $R2FILE > $R1FILE + select_challenge < "$R2FILE" > "$R1FILE" anastasis-reducer -a '{"answer": "123"}' \ - solve_challenge < $R1FILE > $R2FILE + solve_challenge < "$R1FILE" > "$R2FILE" echo " OK" echo -n "Checking recovered secret ..." # finally: check here that we recovered the secret... -STATE=`jq -r -e .recovery_state < $R2FILE` -if test "$STATE" != "RECOVERY_FINISHED" +STATE=$(jq -r -e .recovery_state < "$R2FILE") +if [ "$STATE" != "RECOVERY_FINISHED" ] then - jq -e . $R2FILE + jq -e . "$R2FILE" exit_fail "Expected new state to be 'RECOVERY_FINISHED', got '$STATE'" fi -SECRET=`jq -r -e .core_secret.value < $R2FILE` -if test "$SECRET" != "VERYHARDT0GVESSSECRET" +SECRET=$(jq -r -e .core_secret.value < "$R2FILE") +if [ "$SECRET" != "VERYHARDT0GVESSSECRET" ] then - jq -e . $R2FILE + jq -e . "$R2FILE" exit_fail "Expected recovered secret to be 'VERYHARDT0GVESSSECRET', got '$SECRET'" fi -MIME=`jq -r -e .core_secret.mime < $R2FILE` -if test "$MIME" != "text/plain" +MIME=$(jq -r -e .core_secret.mime < "$R2FILE") +if [ "$MIME" != "text/plain" ] then - jq -e . $R2FILE + jq -e . "$R2FILE" exit_fail "Expected recovered mime to be 'text/plain', got '$MIME'" fi diff --git a/src/cli/test_anastasis_reducer_recovery_hanging.sh b/src/cli/test_anastasis_reducer_recovery_hanging.sh new file mode 100755 index 0000000..f67b850 --- /dev/null +++ b/src/cli/test_anastasis_reducer_recovery_hanging.sh @@ -0,0 +1,376 @@ +#!/bin/bash +# This file is in the public domain. +# Runs tests with a 'hanging' Anastasis provider. + +set -eu +#set -x + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: $1" + exit 77 +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " FAIL: $1" + exit 1 +} + +# Cleanup to run whenever we exit +function cleanup() +{ + for n in `jobs -p` + do + kill -SIGCONT $n # in case suspended... + kill $n 2> /dev/null || true + done + rm -rf $CONF $R1FILE $R2FILE $B1FILE $B2FILE $TMP_DIR + wait +} + +function sync_providers() { + infile=$1 + outfile=$2 + echo "Synchronizing providers" + # Sync with providers (up to 3 providers aren't synced here) + for x in 1 2 3; do + echo "Synchronizing providers (round $x)" + #anastasis-reducer sync_providers < $infile > $outfile 2> /dev/null || true + anastasis-reducer sync_providers < $infile > $outfile || true + CODE=$(jq -r -e ".code // 0" < $outfile) + # ANASTASIS_REDUCER_PROVIDERS_ALREADY_SYNCED + # FIXME: Temporary workaround for C reducer. See #7227. + if test "$CODE" = "8420"; then + # restore previous non-error state + cat $infile > $outfile + break + fi + # ANASTASIS_REDUCER_ACTION_INVALID + if test "$CODE" = "8400"; then + # restore previous non-error state + cat $infile > $outfile + break + fi + if test "$CODE" != "0"; then + exit_fail "Expected no error or 8420/8400, got $CODE" + fi + cat $outfile > $infile + done + echo "Providers synced." +} + + +CONF_1="test_anastasis_reducer_free_1.conf" +CONF_2="test_anastasis_reducer_free_2.conf" +CONF_3="test_anastasis_reducer_free_3.conf" +CONF_4="test_anastasis_reducer_free_4.conf" + + +# Configuration file will be edited, so we create one +# from the template. +CONF=`mktemp test_reducerXXXXXX.conf` +cp test_reducer.conf $CONF + +TMP_DIR=`mktemp -d keys-tmp-XXXXXX` +B1FILE=`mktemp test_reducer_stateB1XXXXXX` +B2FILE=`mktemp test_reducer_stateB2XXXXXX` +R1FILE=`mktemp test_reducer_stateR1XXXXXX` +R2FILE=`mktemp test_reducer_stateR2XXXXXX` +export B1FILE +export B2FILE +export R1FILE +export R2FILE + +# Install cleanup handler (except for kill -9) +trap cleanup EXIT + +# Check we can actually run +echo -n "Testing for jq" +jq -h > /dev/null || exit_skip "jq required" +echo " FOUND" +echo -n "Testing for timeout" +timeout --help > /dev/null || exit_skip "timeout required" +echo " FOUND" +echo -n "Testing for anastasis-reducer ..." +anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" +echo " FOUND" + +echo -n "Testing for anastasis-httpd" +anastasis-httpd -h >/dev/null </dev/null || exit_skip " MISSING" +echo " FOUND" + +echo -n "Initialize anastasis database ..." +# Name of the Postgres database we will use for the script. +# Will be dropped, do NOT use anything that might be used +# elsewhere +TARGET_DB_1=`anastasis-config -c $CONF_1 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` +TARGET_DB_2=`anastasis-config -c $CONF_2 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` +TARGET_DB_3=`anastasis-config -c $CONF_3 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` +TARGET_DB_4=`anastasis-config -c $CONF_4 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` + +dropdb $TARGET_DB_1 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_1 || exit_skip "Could not create database $TARGET_DB_1" +anastasis-dbinit -c $CONF_1 2> anastasis-dbinit_1.log +dropdb $TARGET_DB_2 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_2 || exit_skip "Could not create database $TARGET_DB_2" +anastasis-dbinit -c $CONF_2 2> anastasis-dbinit_2.log +dropdb $TARGET_DB_3 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_3 || exit_skip "Could not create database $TARGET_DB_3" +anastasis-dbinit -c $CONF_3 2> anastasis-dbinit_3.log +dropdb $TARGET_DB_4 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_4 || exit_skip "Could not create database $TARGET_DB_4" +anastasis-dbinit -c $CONF_4 2> anastasis-dbinit_4.log + +echo " OK" + +echo -n "Launching anastasis services ..." +PREFIX="" #valgrind +$PREFIX anastasis-httpd -c $CONF_1 2> anastasis-httpd_1.log & +PPID_1=$! +$PREFIX anastasis-httpd -c $CONF_2 2> anastasis-httpd_2.log & +PPID_2=$! +$PREFIX anastasis-httpd -c $CONF_3 2> anastasis-httpd_3.log & +PPID_3=$! +$PREFIX anastasis-httpd -c $CONF_4 2> anastasis-httpd_4.log & +PPID_4=$! +export PPID_1 +export PPID_2 +export PPID_3 +export PPID_4 + +echo -n "Waiting for anastasis services ..." + +# Wait for anastasis services to be available +for n in `seq 1 50` +do + echo -n "." + sleep 0.1 + OK=0 + # anastasis_01 + wget --tries=1 --timeout=1 http://localhost:8086/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_02 + wget --tries=1 --timeout=1 http://localhost:8087/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_03 + wget --tries=1 --timeout=1 http://localhost:8088/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_04 + wget --tries=1 --timeout=1 http://localhost:8089/ -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to launch anastasis services" +fi +echo "OK" + +echo -n "Running backup logic ...," +anastasis-reducer -b > $B1FILE +echo -n "." +anastasis-reducer -a \ + '{"continent": "Demoworld"}' \ + select_continent < $B1FILE > $B2FILE +echo -n "." +anastasis-reducer -a \ + '{"country_code": "xx"}' \ + select_country < $B2FILE > $B1FILE +echo -n "." + +kill -SIGSTOP $PPID_4 +START=`date '+%s'` +timeout 10 anastasis-reducer -L DEBUG -a \ + '{"identity_attributes": { + "full_name": "Max Musterman", + "sq_number": "4", + "birthdate": "2000-01-01"}}' \ + enter_user_attributes < $B1FILE > $B2FILE || true +END=`date '+%s'` +DELTA=`expr $END - $START` +kill -SIGCONT $PPID_4 + +if test $DELTA -ge 5 +then + exit_fail "Reducer hangs on suspended provider in 'enter_user_attributes'" +fi + +cat $B2FILE > $B1FILE +echo -n "," +sync_providers $B1FILE $B2FILE +echo -n "," +# "91GPWWR" encodes "Hans" +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "What is your name?", + "challenge": "91GPWWR" + } }' \ + add_authentication < $B2FILE > $B1FILE +echo -n "." +# "64S36" encodes "123" +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "How old are you?", + "challenge": "64S36" + } }' \ + add_authentication < $B1FILE > $B2FILE +echo -n "." +# "9NGQ4WR" encodes "Mars" +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "Where do you live?", + "challenge": "9NGQ4WR" + } }' \ + add_authentication < $B2FILE > $B1FILE +echo -n "." +# Finished adding authentication methods +anastasis-reducer \ + next < $B1FILE > $B2FILE + + +echo -n "," +# Finished policy review +anastasis-reducer \ + next < $B2FILE > $B1FILE +echo -n "." + +# Note: 'secret' must here be a Crockford base32-encoded value +anastasis-reducer -a \ + '{"secret": { "value" : "VERYHARDT0GVESSSECRET", "mime" : "text/plain" }}' \ + enter_secret < $B1FILE > $B2FILE +anastasis-reducer next $B2FILE $B1FILE +echo " OK" + +echo -n "Final backup checks ..." +STATE=`jq -r -e .backup_state < $B1FILE` +if test "$STATE" != "BACKUP_FINISHED" +then + exit_fail "Expected new state to be 'BACKUP_FINISHED', got '$STATE'" +fi + +jq -r -e .core_secret < $B1FILE > /dev/null && exit_fail "'core_secret' was not cleared upon success" + +echo " OK" + + +echo -n "Running recovery basic logic ..." +anastasis-reducer -r > $R1FILE +anastasis-reducer -a \ + '{"continent": "Demoworld"}' \ + select_continent < $R1FILE > $R2FILE +anastasis-reducer -a \ + '{"country_code": "xx" }' \ + select_country < $R2FILE > $R1FILE +anastasis-reducer -a '{"identity_attributes": { "full_name": "Max Musterman", "sq_number": "4", "birthdate": "2000-01-01" }}' enter_user_attributes < $R1FILE > $R2FILE + + +STATE=`jq -r -e .recovery_state < $R2FILE` +if test "$STATE" != "SECRET_SELECTING" +then + exit_fail "Expected new state to be 'SECRET_SELECTING', got '$STATE'" +fi +echo " OK" + +echo -n "Adding provider (to ensure it is loaded)" +anastasis-reducer -a '{"provider_url" : "http://localhost:8086/" }' add_provider < $R2FILE > $R1FILE +echo " OK" + +echo -n "Selecting secret to recover" +anastasis-reducer -a '{"attribute_mask": 0, "providers" : [ { "version": 1, "url" : "http://localhost:8086/" } ] }' select_version < $R1FILE > $R2FILE + +STATE=`jq -r -e .recovery_state < $R2FILE` +if test "$STATE" != "CHALLENGE_SELECTING" +then + exit_fail "Expected new state to be 'CHALLENGE_SELECTING', got '$STATE'" +fi +echo " OK" + +cat $R2FILE > $R1FILE +sync_providers $R1FILE $R2FILE + +echo -n "Running challenge logic ..." + +cat $R2FILE | jq . + +UUID0=`jq -r -e .recovery_information.challenges[0].uuid < $R2FILE` +UUID1=`jq -r -e .recovery_information.challenges[1].uuid < $R2FILE` +UUID2=`jq -r -e .recovery_information.challenges[2].uuid < $R2FILE` +UUID0Q=`jq -r -e .recovery_information.challenges[0].instructions < $R2FILE` +UUID1Q=`jq -r -e .recovery_information.challenges[1].instructions < $R2FILE` +UUID2Q=`jq -r -e .recovery_information.challenges[2].instructions < $R2FILE` + +if test "$UUID2Q" = 'How old are you?' +then + AGE_UUID=$UUID2 +elif test "$UUID1Q" = 'How old are you?' +then + AGE_UUID=$UUID1 +else + AGE_UUID=$UUID0 +fi + +if test "$UUID2Q" = 'What is your name?' +then + NAME_UUID=$UUID2 +elif test "$UUID1Q" = 'What is your name?' +then + NAME_UUID=$UUID1 +else + NAME_UUID=$UUID0 +fi + +anastasis-reducer -a \ + "$(jq -n ' + { + uuid: $UUID + }' \ + --arg UUID "$NAME_UUID" + )" \ + select_challenge < $R2FILE > $R1FILE + +anastasis-reducer -a '{"answer": "Hans"}' \ + solve_challenge < $R1FILE > $R2FILE + +anastasis-reducer -a \ + "$(jq -n ' + { + uuid: $UUID + }' \ + --arg UUID "$AGE_UUID" + )" \ + select_challenge < $R2FILE > $R1FILE + +anastasis-reducer -a '{"answer": "123"}' \ + solve_challenge < $R1FILE > $R2FILE + +echo " OK" + +echo -n "Checking recovered secret ..." +# finally: check here that we recovered the secret... + +STATE=`jq -r -e .recovery_state < $R2FILE` +if test "$STATE" != "RECOVERY_FINISHED" +then + jq -e . $R2FILE + exit_fail "Expected new state to be 'RECOVERY_FINISHED', got '$STATE'" +fi + +SECRET=`jq -r -e .core_secret.value < $R2FILE` +if test "$SECRET" != "VERYHARDT0GVESSSECRET" +then + jq -e . $R2FILE + exit_fail "Expected recovered secret to be 'VERYHARDT0GVESSSECRET', got '$SECRET'" +fi + +MIME=`jq -r -e .core_secret.mime < $R2FILE` +if test "$MIME" != "text/plain" +then + jq -e . $R2FILE + exit_fail "Expected recovered mime to be 'text/plain', got '$MIME'" +fi + +echo " OK" + +exit 0 diff --git a/src/cli/test_anastasis_reducer_recovery_no_pay.sh b/src/cli/test_anastasis_reducer_recovery_no_pay.sh new file mode 100755 index 0000000..42f5b0c --- /dev/null +++ b/src/cli/test_anastasis_reducer_recovery_no_pay.sh @@ -0,0 +1,351 @@ +#!/bin/bash +# This file is in the public domain. + +set -eu +set -x + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: $1" + exit 77 +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " FAIL: $1" + exit 1 +} + +# Cleanup to run whenever we exit +function cleanup() +{ + for n in `jobs -p` + do + kill $n 2> /dev/null || true + done + rm -rf $CONF $R1FILE $R2FILE $B1FILE $B2FILE $TMP_DIR + wait +} + +function sync_providers() { + infile=$1 + outfile=$2 + echo "Synchronizing providers" + # Sync with providers (up to 3 providers aren't synced here) + for x in 1 2 3; do + echo "Synchronizing providers (round $x)" + #anastasis-reducer sync_providers < $infile > $outfile 2> /dev/null || true + anastasis-reducer sync_providers < $infile > $outfile || true + CODE=$(jq -r -e ".code // 0" < $outfile) + # ANASTASIS_REDUCER_PROVIDERS_ALREADY_SYNCED + # FIXME: Temporary workaround for C reducer. See #7227. + if test "$CODE" = "8420"; then + # restore previous non-error state + cat $infile > $outfile + break + fi + # ANASTASIS_REDUCER_ACTION_INVALID + if test "$CODE" = "8400"; then + # restore previous non-error state + cat $infile > $outfile + break + fi + if test "$CODE" != "0"; then + exit_fail "Expected no error or 8420/8400, got $CODE" + fi + cat $outfile > $infile + done + echo "Providers synced." +} + + +CONF_1="test_anastasis_reducer_free_1.conf" +CONF_2="test_anastasis_reducer_free_2.conf" +CONF_3="test_anastasis_reducer_free_3.conf" +CONF_4="test_anastasis_reducer_free_4.conf" + + +# Configuration file will be edited, so we create one +# from the template. +CONF=$(mktemp test_reducerXXXXXX.conf) +cp test_reducer.conf "$CONF" + +TMP_DIR=`mktemp -d keys-tmp-XXXXXX` +B1FILE=`mktemp test_reducer_stateB1XXXXXX` +B2FILE=`mktemp test_reducer_stateB2XXXXXX` +R1FILE=`mktemp test_reducer_stateR1XXXXXX` +R2FILE=`mktemp test_reducer_stateR2XXXXXX` +export B1FILE +export B2FILE +export R1FILE +export R2FILE + +# Install cleanup handler (except for kill -9) +trap cleanup EXIT + +# Check we can actually run +echo -n "Testing for jq" +jq -h > /dev/null || exit_skip "jq required" +echo " FOUND" +echo -n "Testing for anastasis-reducer ..." +anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" +echo " FOUND" + +echo -n "Testing for anastasis-httpd" +anastasis-httpd -h >/dev/null </dev/null || exit_skip " MISSING" +echo " FOUND" + +echo -n "Initialize anastasis database ..." +# Name of the Postgres database we will use for the script. +# Will be dropped, do NOT use anything that might be used +# elsewhere +TARGET_DB_1=`anastasis-config -c $CONF_1 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` +TARGET_DB_2=`anastasis-config -c $CONF_2 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` +TARGET_DB_3=`anastasis-config -c $CONF_3 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` +TARGET_DB_4=`anastasis-config -c $CONF_4 -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` + +dropdb $TARGET_DB_1 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_1 || exit_skip "Could not create database $TARGET_DB_1" +anastasis-dbinit -c $CONF_1 2> anastasis-dbinit_1.log +dropdb $TARGET_DB_2 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_2 || exit_skip "Could not create database $TARGET_DB_2" +anastasis-dbinit -c $CONF_2 2> anastasis-dbinit_2.log +dropdb $TARGET_DB_3 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_3 || exit_skip "Could not create database $TARGET_DB_3" +anastasis-dbinit -c $CONF_3 2> anastasis-dbinit_3.log +dropdb $TARGET_DB_4 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_4 || exit_skip "Could not create database $TARGET_DB_4" +anastasis-dbinit -c $CONF_4 2> anastasis-dbinit_4.log + +echo " OK" + +echo -n "Launching anastasis services ..." +PREFIX="" #valgrind +$PREFIX anastasis-httpd -L DEBUG -c $CONF_1 2> anastasis-httpd_1.log & +$PREFIX anastasis-httpd -L DEBUG -c $CONF_2 2> anastasis-httpd_2.log & +$PREFIX anastasis-httpd -L DEBUG -c $CONF_3 2> anastasis-httpd_3.log & +$PREFIX anastasis-httpd -L DEBUG -c $CONF_4 2> anastasis-httpd_4.log & + +echo -n "Waiting for anastasis services ..." + +# Wait for anastasis services to be available +for n in `seq 1 50` +do + echo -n "." + sleep 0.1 + OK=0 + # anastasis_01 + wget --tries=1 --timeout=1 http://localhost:8086/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_02 + wget --tries=1 --timeout=1 http://localhost:8087/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_03 + wget --tries=1 --timeout=1 http://localhost:8088/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_04 + wget --tries=1 --timeout=1 http://localhost:8089/ -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to launch anastasis services" +fi +echo "OK" + +echo -n "Running backup logic ...," +anastasis-reducer -b > $B1FILE +echo -n "." +anastasis-reducer -a \ + '{"continent": "Demoworld"}' \ + select_continent < $B1FILE > $B2FILE +echo -n "." +anastasis-reducer -a \ + '{"country_code": "xx"}' \ + select_country < $B2FILE > $B1FILE +echo -n "." +anastasis-reducer -a \ + '{"identity_attributes": { + "full_name": "Max Musterman", + "sq_number": "4", + "birthdate": "2000-01-01"}}' \ + enter_user_attributes < $B1FILE > $B2FILE +cat $B2FILE > $B1FILE +echo -n "," +sync_providers $B1FILE $B2FILE +echo -n "," +# "91GPWWR" encodes "Hans" +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "What is your name?", + "challenge": "91GPWWR" + } }' \ + add_authentication < $B2FILE > $B1FILE +echo -n "." +# "64S36" encodes "123" +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "How old are you?", + "challenge": "64S36" + } }' \ + add_authentication < $B1FILE > $B2FILE +echo -n "." +# "9NGQ4WR" encodes "Mars" +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "Where do you live?", + "challenge": "9NGQ4WR" + } }' \ + add_authentication < $B2FILE > $B1FILE +echo -n "." +# Finished adding authentication methods +anastasis-reducer \ + next < $B1FILE > $B2FILE + + +echo -n "," +# Finished policy review +anastasis-reducer \ + next < $B2FILE > $B1FILE +echo -n "." + +# Note: 'secret' must here be a Crockford base32-encoded value +anastasis-reducer -a \ + '{"secret": { "value" : "VERYHARDT0GVESSSECRET", "mime" : "text/plain" }}' \ + enter_secret < $B1FILE > $B2FILE +anastasis-reducer next $B2FILE $B1FILE +echo " OK" + +echo -n "Final backup checks ..." +STATE=`jq -r -e .backup_state < $B1FILE` +if test "$STATE" != "BACKUP_FINISHED" +then + exit_fail "Expected new state to be 'BACKUP_FINISHED', got '$STATE'" +fi + +jq -r -e .core_secret < $B1FILE > /dev/null && exit_fail "'core_secret' was not cleared upon success" + +echo " OK" + + +echo -n "Running recovery basic logic ..." +anastasis-reducer -r > $R1FILE +anastasis-reducer -a \ + '{"continent": "Demoworld"}' \ + select_continent < $R1FILE > $R2FILE +anastasis-reducer -a \ + '{"country_code": "xx" }' \ + select_country < $R2FILE > $R1FILE +anastasis-reducer -a '{"identity_attributes": { "full_name": "Max Musterman", "sq_number": "4", "birthdate": "2000-01-01" }}' enter_user_attributes < $R1FILE > $R2FILE + + +STATE=`jq -r -e .recovery_state < $R2FILE` +if test "$STATE" != "SECRET_SELECTING" +then + exit_fail "Expected new state to be 'SECRET_SELECTING', got '$STATE'" +fi +echo " OK" + +echo -n "Adding provider (to ensure it is loaded)" +anastasis-reducer -a '{"provider_url" : "http://localhost:8086/" }' add_provider < $R2FILE > $R1FILE +echo " OK" + +echo -n "Selecting secret to recover" +anastasis-reducer -a '{"attribute_mask": 0, "providers" : [ { "version": 1, "url" : "http://localhost:8086/" } ] }' select_version < $R1FILE > $R2FILE + +STATE=`jq -r -e .recovery_state < $R2FILE` +if test "$STATE" != "CHALLENGE_SELECTING" +then + exit_fail "Expected new state to be 'CHALLENGE_SELECTING', got '$STATE'" +fi +echo " OK" + +cat $R2FILE > $R1FILE +sync_providers $R1FILE $R2FILE + +echo -n "Running challenge logic ..." + +cat $R2FILE | jq . + +UUID0=`jq -r -e .recovery_information.challenges[0].uuid < $R2FILE` +UUID1=`jq -r -e .recovery_information.challenges[1].uuid < $R2FILE` +UUID2=`jq -r -e .recovery_information.challenges[2].uuid < $R2FILE` +UUID0Q=`jq -r -e .recovery_information.challenges[0].instructions < $R2FILE` +UUID1Q=`jq -r -e .recovery_information.challenges[1].instructions < $R2FILE` +UUID2Q=`jq -r -e .recovery_information.challenges[2].instructions < $R2FILE` + +if test "$UUID2Q" = 'How old are you?' +then + AGE_UUID=$UUID2 +elif test "$UUID1Q" = 'How old are you?' +then + AGE_UUID=$UUID1 +else + AGE_UUID=$UUID0 +fi + +if test "$UUID2Q" = 'What is your name?' +then + NAME_UUID=$UUID2 +elif test "$UUID1Q" = 'What is your name?' +then + NAME_UUID=$UUID1 +else + NAME_UUID=$UUID0 +fi + +anastasis-reducer -a \ + "$(jq -n ' + { + uuid: $UUID + }' \ + --arg UUID "$NAME_UUID" + )" \ + select_challenge < $R2FILE > $R1FILE + +anastasis-reducer -a '{"answer": "Hans"}' \ + solve_challenge < $R1FILE > $R2FILE + +anastasis-reducer -a \ + "$(jq -n ' + { + uuid: $UUID + }' \ + --arg UUID "$AGE_UUID" + )" \ + select_challenge < $R2FILE > $R1FILE + +anastasis-reducer -a '{"answer": "123"}' \ + solve_challenge < $R1FILE > $R2FILE + +echo " OK" + +echo -n "Checking recovered secret ..." +# finally: check here that we recovered the secret... + +STATE=`jq -r -e .recovery_state < $R2FILE` +if test "$STATE" != "RECOVERY_FINISHED" +then + jq -e . $R2FILE + exit_fail "Expected new state to be 'RECOVERY_FINISHED', got '$STATE'" +fi + +SECRET=`jq -r -e .core_secret.value < $R2FILE` +if test "$SECRET" != "VERYHARDT0GVESSSECRET" +then + jq -e . $R2FILE + exit_fail "Expected recovered secret to be 'VERYHARDT0GVESSSECRET', got '$SECRET'" +fi + +MIME=`jq -r -e .core_secret.mime < $R2FILE` +if test "$MIME" != "text/plain" +then + jq -e . $R2FILE + exit_fail "Expected recovered mime to be 'text/plain', got '$MIME'" +fi + +echo " OK" + +exit 0 diff --git a/src/cli/test_anastasis_reducer_select_continent.sh b/src/cli/test_anastasis_reducer_select_continent.sh index 4cd8a84..bd1ce95 100755 --- a/src/cli/test_anastasis_reducer_select_continent.sh +++ b/src/cli/test_anastasis_reducer_select_continent.sh @@ -41,7 +41,7 @@ echo " FOUND" # Test continent selection in a backup state echo -n "Test continent selection in a backup state ..." -anastasis-reducer -a '{"continent": "Testcontinent"}' select_continent resources/00-backup.json $TFILE +anastasis-reducer -a '{"continent": "Demoworld"}' select_continent resources/00-backup.json $TFILE STATE=`jq -r -e .backup_state < $TFILE` if test "$STATE" != "COUNTRY_SELECTING" @@ -49,9 +49,9 @@ then exit_fail "Expected new state to be COUNTRY_SELECTING, got $STATE" fi SELECTED_CONTINENT=`jq -r -e .selected_continent < $TFILE` -if test "$SELECTED_CONTINENT" != "Testcontinent" +if test "$SELECTED_CONTINENT" != "Demoworld" then - exit_fail "Expected selected continent to be Testcontinent, got $SELECTED_CONTINENT" + exit_fail "Expected selected continent to be Demoworld, got $SELECTED_CONTINENT" fi COUNTRIES=`jq -r -e .countries < $TFILE` if test "$COUNTRIES" == NULL @@ -68,7 +68,7 @@ anastasis-reducer -a '{"continent": "Pangaia"}' select_continent resources/00-re echo " OK" echo -n "Test continent selection in a recovery state ..." -anastasis-reducer -a '{"continent": "Testcontinent"}' select_continent resources/00-recovery.json $TFILE +anastasis-reducer -a '{"continent": "Demoworld"}' select_continent resources/00-recovery.json $TFILE STATE=`jq -r -e .recovery_state < $TFILE` if test "$STATE" != "COUNTRY_SELECTING" @@ -79,12 +79,11 @@ jq -e .countries[0] < $TFILE > /dev/null || exit_fail "Expected new state to inc jq -e .countries[0].code < $TFILE > /dev/null || exit_fail "Expected new state to include countries with code" jq -e .countries[0].continent < $TFILE > /dev/null || exit_fail "Expected new state to include countries with continent" jq -e .countries[0].name < $TFILE > /dev/null || exit_fail "Expected new state to include countries with name" -jq -e .countries[0].currency < $TFILE > /dev/null || exit_fail "Expected new state to include countries with currency" SELECTED_CONTINENT=`jq -r -e .selected_continent < $TFILE` -if test "$SELECTED_CONTINENT" != "Testcontinent" +if test "$SELECTED_CONTINENT" != "Demoworld" then - exit_fail "Expected selected continent to be 'Testcontinent', got $SELECTED_CONTINENT" + exit_fail "Expected selected continent to be 'Demoworld', got $SELECTED_CONTINENT" fi COUNTRIES=`jq -r -e .countries < $TFILE` @@ -96,7 +95,6 @@ jq -e .countries[0] < $TFILE > /dev/null || exit_fail "Expected new state to inc jq -e .countries[0].code < $TFILE > /dev/null || exit_fail "Expected new state to include countries with code" jq -e .countries[0].continent < $TFILE > /dev/null || exit_fail "Expected new state to include countries with continent" jq -e .countries[0].name < $TFILE > /dev/null || exit_fail "Expected new state to include countries with name" -jq -e .countries[0].currency < $TFILE > /dev/null || exit_fail "Expected new state to include countries with currency" echo " OK" diff --git a/src/cli/test_anastasis_reducer_select_country.sh b/src/cli/test_anastasis_reducer_select_country.sh index c02f61f..2e18f44 100755 --- a/src/cli/test_anastasis_reducer_select_country.sh +++ b/src/cli/test_anastasis_reducer_select_country.sh @@ -63,12 +63,11 @@ jq -e .countries[0] < $TFILE > /dev/null || exit_fail "Expected new state to inc jq -e .countries[0].code < $TFILE > /dev/null || exit_fail "Expected new state to include countries with code" jq -e .countries[0].continent < $TFILE > /dev/null || exit_fail "Expected new state to include countries with continent" jq -e .countries[0].name < $TFILE > /dev/null || exit_fail "Expected new state to include countries with name" -jq -e .countries[0].currency < $TFILE > /dev/null || exit_fail "Expected new state to include countries with currency" SELECTED_CONTINENT=`jq -r -e .selected_continent < $TFILE` if test "$SELECTED_CONTINENT" != "Europe" then - exit_fail "Expected selected continent to be 'Testcontinent', got $SELECTED_CONTINENT" + exit_fail "Expected selected continent to be 'Europe', got $SELECTED_CONTINENT" fi echo " OK" @@ -84,8 +83,7 @@ echo " OK" echo -n "Test NX country selection ..." anastasis-reducer -a \ - '{"country_code": "zz", - "currencies": ["EUR" ]}' \ + '{"country_code": "zz"}' \ select_country \ resources/01-backup.json $TFILE 2> /dev/null \ && exit_fail "Expected selection to fail. Check '$TFILE'" @@ -95,8 +93,7 @@ echo " OK" echo -n "Test invalid country selection for continent ..." anastasis-reducer -a \ - '{"country_code": "de", - "currencies":["EUR"]}' \ + '{"country_code": "de"}' \ select_country \ resources/01-backup.json $TFILE 2> /dev/null \ && exit_fail "Expected selection to fail. Check '$TFILE'" @@ -106,8 +103,7 @@ echo " OK" echo -n "Test country selection ..." anastasis-reducer -a \ - '{"country_code": "xx", - "currencies":["TESTKUDOS"]}' \ + '{"country_code": "xx"}' \ select_country resources/01-backup.json $TFILE STATE=`jq -r -e .backup_state < $TFILE` @@ -122,12 +118,6 @@ then exit_fail "Expected selected country to be 'xx', got '$SELECTED_COUNTRY'" fi echo -n "." -SELECTED_CURRENCY=`jq -r -e .currencies[0] < $TFILE` -if test "$SELECTED_CURRENCY" != "TESTKUDOS" -then - exit_fail "Expected selected currency to be 'TESTKUDOS', got '$SELECTED_CURRENCY'" -fi -echo -n "." REQ_ATTRIBUTES=`jq -r -e .required_attributes < $TFILE` if test "$REQ_ATTRIBUTES" == NULL then diff --git a/src/cli/test_free_reducer.conf b/src/cli/test_free_reducer.conf index 74954cd..8308537 100644 --- a/src/cli/test_free_reducer.conf +++ b/src/cli/test_free_reducer.conf @@ -11,7 +11,7 @@ UPLOAD_LIMIT_MB = 1 ANNUAL_POLICY_UPLOAD_LIMIT = 128 INSURANCE = EUR:0 PORT = 8086 -SERVER_SALT = BUfO1KGOKYIFlFQg +PROVIDER_SALT = BUfO1KGOKYIFlFQg BUSINESS_NAME = "Data loss Inc." [stasis] diff --git a/src/cli/test_iban.sh b/src/cli/test_iban.sh index c3e858c..207d2d5 100755 --- a/src/cli/test_iban.sh +++ b/src/cli/test_iban.sh @@ -1,6 +1,8 @@ #!/bin/bash +# This file is in the public domain. set -eu +#set -x # Exit, with status code "skip" (no 'real' failure) function exit_skip() { @@ -17,38 +19,66 @@ function exit_fail() { # Cleanup to run whenever we exit function cleanup() { - for n in `jobs -p` + for n in $(jobs -p) do - kill $n 2> /dev/null || true + kill "$n" 2> /dev/null || true done - rm -rf $CONF $R1FILE $R2FILE $B1FILE $B2FILE + rm -rf "$CONF" "$R1FILE" "$R2FILE" "$B1FILE" "$B2FILE" wait } # $1=ebics username, $2=ebics partner name, $3=person name, $4=sandbox bank account name, $5=iban function prepare_sandbox_account() { - echo -n "Activating ebics subscriber $1 at the sandbox ..." - libeufin-cli \ - sandbox --sandbox-url=$SANDBOX_URL \ - ebicssubscriber create \ - --host-id=$EBICS_HOST \ - --partner-id=$2 \ - --user-id=$1 + echo -n "Registering $4 to the Sandbox..." + export LIBEUFIN_SANDBOX_USERNAME="$4" + export LIBEUFIN_SANDBOX_PASSWORD=unused + libeufin-cli sandbox --sandbox-url="$SANDBOX_URL" \ + demobank register --name "$3" --iban "$5" echo " OK" - echo -n "Giving a bank account ($4) to $1 ..." - libeufin-cli \ - sandbox --sandbox-url=$SANDBOX_URL \ - ebicsbankaccount create \ - --iban=$5 \ - --bic="BCMAESM1XXX"\ - --person-name="$3" \ - --account-name=$4 \ - --ebics-user-id=$1 \ - --ebics-host-id=$EBICS_HOST \ - --ebics-partner-id=$2 \ - --currency=$CURRENCY + echo -n "Associating a EBICS subscriber to $4..." + export LIBEUFIN_SANDBOX_USERNAME=admin + libeufin-cli sandbox --sandbox-url="$SANDBOX_URL" demobank new-ebicssubscriber \ + --host-id "$EBICS_HOST" \ + --user-id "$1" --partner-id "$2" \ + --bank-account "$4" # that's a username _and_ a bank account name echo " OK" + + unset LIBEUFIN_SANDBOX_USERNAME + unset LIBEUFIN_SANDBOX_PASSWORD +} + +function sync_providers() { + infile="$1" + outfile="$2" + echo "Synchronizing providers" + # Sync with providers (up to 3 providers aren't synced here) + for x in 1 2 3; do + echo "Synchronizing providers (round $x)" + anastasis-reducer sync_providers < "$infile" > "$outfile" 2> /dev/null || true + CODE=$(jq -r -e ".code // 0" < $outfile) + # ANASTASIS_REDUCER_PROVIDERS_ALREADY_SYNCED + # FIXME: Temporary workaround for C reducer. See #7227. + if [ "$CODE" = "8420" ] + then + # restore previous non-error state + cp "$infile" "$outfile" + break + fi + # ANASTASIS_REDUCER_ACTION_INVALID + if [ "$CODE" = "8400" ] + then + # restore previous non-error state + cp "$infile" "$outfile" + break + fi + if [ "$CODE" != "0" ] + then + exit_fail "Expected no error or 8420/8400, got $CODE" + fi + cp "$outfile" "$infile" + done + echo "Providers synced." } @@ -61,13 +91,19 @@ trap cleanup EXIT # to pass through the Nexus+Ebics layer to issue the payment # $1 = amount ($CURRENCY:X.Y), $2 = subject. function wire_transfer_to_anastasis() { + echo -n "Initiating wire transfer ..." libeufin-sandbox make-transaction \ --debit-account=sandbox-account-debit \ - --credit-account=sandbox-account-credit "$1" "$2" - # Sync nexus with sandbox - export LIBEUFIN_NEXUS_USERNAME=$CREDIT_USERNAME - export LIBEUFIN_NEXUS_PASSWORD=$CREDIT_PASSWORD - libeufin-cli accounts fetch-transactions nexus-bankaccount-credit > /dev/null + --credit-account=sandbox-account-credit "$1" "$2" &> libeufin-transfer-initiate.out + echo " OK" + # FIXME-MS: the following command reports that it did not + # sync any transactions, even though presumably we just + # made one in the one above (which succeeded...) + echo -n "Syncing nexus with sandbox ..." + export LIBEUFIN_NEXUS_USERNAME="$CREDIT_USERNAME" + export LIBEUFIN_NEXUS_PASSWORD="$CREDIT_PASSWORD" + libeufin-cli accounts fetch-transactions nexus-bankaccount-credit &> libeufin-transfer-fetch.out + echo " OK" } # $1 = facade base URL. Merely a debug utility. @@ -82,43 +118,33 @@ function prepare_nexus_account() { echo -n "Making bank connection $3 ..." libeufin-cli connections new-ebics-connection \ --ebics-url="${SANDBOX_URL}ebicsweb" \ - --host-id=$EBICS_HOST \ - --partner-id=$2 \ - --ebics-user-id=$1 \ + --host-id="$EBICS_HOST" \ + --partner-id="$2" \ + --ebics-user-id="$1" \ $3 > /dev/null echo " OK" echo -n "Connecting $3 ..." - libeufin-cli connections connect $3 > /dev/null + libeufin-cli connections connect "$3" > /dev/null echo " OK" echo -n "Importing Sandbox bank account ($5) to Nexus ($4) ..." - libeufin-cli connections download-bank-accounts $3 > /dev/null + libeufin-cli connections download-bank-accounts "$3" > /dev/null libeufin-cli connections import-bank-account \ - --offered-account-id=$5 --nexus-bank-account-id=$4 $3 > /dev/null + --offered-account-id="$5" --nexus-bank-account-id="$4" "$3" > /dev/null echo " OK" } -# $1 = facade name, $2 = bank connection to use, $3 = bank account name -# local to Nexus -function prepare_anastasis_facade() { - echo -n "Creating facade ..." - libeufin-cli facades new-anastasis-facade \ - --currency=$CURRENCY \ - --facade-name=$1 \ - $2 $3 - echo " OK" - # No need to setup facade permissions, as the anastasis client - # is superuser at Nexus. -} # Configuration file will be edited, so we create one # from the template. -CONF=`mktemp test_free_reducerXXXXXX.conf` -cp test_free_reducer.conf $CONF +CONF=$(mktemp test_free_reducerXXXXXX.conf) +cp test_free_reducer.conf "$CONF" -B1FILE=`mktemp test_reducer_stateB1XXXXXX` -B2FILE=`mktemp test_reducer_stateB2XXXXXX` -R1FILE=`mktemp test_reducer_stateR1XXXXXX` -R2FILE=`mktemp test_reducer_stateR2XXXXXX` + + +B1FILE=$(mktemp test_reducer_stateB1XXXXXX) +B2FILE=$(mktemp test_reducer_stateB2XXXXXX) +R1FILE=$(mktemp test_reducer_stateR1XXXXXX) +R2FILE=$(mktemp test_reducer_stateR2XXXXXX) export CONF export B2FILE @@ -146,23 +172,40 @@ echo -n "Testing for anastasis-reducer ..." anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" echo " FOUND" -export LIBEUFIN_NEXUS_DB_CONNECTION="jdbc:sqlite:$(mktemp -u /tmp/nexus-db-XXXXXX.sqlite)" -export LIBEUFIN_SANDBOX_DB_CONNECTION="jdbc:sqlite:$(mktemp -u /tmp/sandbox-db-XXXXXX.sqlite)" +echo -n "Initialize Anastasis database ..." +# Name of the Postgres database we will use for the script. +# Will be dropped, do NOT use anything that might be used +# elsewhere + +TARGET_DB=$(anastasis-config -c "$CONF" -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///") + +dropdb "$TARGET_DB" >/dev/null 2>/dev/null || true +createdb "$TARGET_DB" || exit_skip "Could not create database $TARGET_DB" +anastasis-dbinit -c "$CONF" 2> anastasis-dbinit.log + +echo " OK" + + +export LIBEUFIN_NEXUS_DB_CONNECTION="postgres:///anastasischeck" +export LIBEUFIN_SANDBOX_DB_CONNECTION="postgres:///anastasischeck" NEXUS_URL="http://localhost:5001/" SANDBOX_URL="http://localhost:5000/" echo -n "Starting Nexus ..." libeufin-nexus serve &> nexus.log & nexus_pid=$! -if ! curl -s --retry 5 --retry-connrefused $NEXUS_URL > /dev/null; then +if ! curl -s --retry 5 --retry-connrefused "$NEXUS_URL" > /dev/null; then exit_skip "Could not launch Nexus" fi echo " OK" +echo -n "Configuring Sandbox..." +libeufin-sandbox config default &> sandbox-config.log +echo " OK" echo -n "Starting Sandbox ..." -libeufin-sandbox serve &> sandbox.log & +libeufin-sandbox serve --no-auth &> sandbox-serve.log & sandbox_pid=$! -if ! curl -s --retry 5 --retry-connrefused $SANDBOX_URL > /dev/null; then +if ! curl -s --retry 5 --retry-connrefused "$SANDBOX_URL" > /dev/null; then exit_skip "Could not launch Sandbox" fi echo " OK" @@ -174,11 +217,11 @@ EBICS_HOST="ebicstesthost" export IBAN_CREDIT="DE89370400440532013000" export IBAN_DEBIT="FR1420041010050500013M02606" -echo -n "Preparing Sandbox ..." +echo -n "Preparing Sandbox (creating the EBICS host) ..." libeufin-cli \ - sandbox --sandbox-url=$SANDBOX_URL \ + sandbox --sandbox-url="$SANDBOX_URL" \ ebicshost create \ - --host-id=$EBICS_HOST + --host-id="$EBICS_HOST" echo " OK" PERSON_CREDIT_NAME="Person Credit" @@ -189,32 +232,32 @@ prepare_sandbox_account \ ebicspartnerCredit \ "${PERSON_CREDIT_NAME}" \ sandbox-account-credit \ - $IBAN_CREDIT + "$IBAN_CREDIT" prepare_sandbox_account \ ebicsuserDebit \ ebicspartnerDebit \ "Person Debit" \ sandbox-account-debit \ - $IBAN_DEBIT + "$IBAN_DEBIT" echo "Sandbox preparation done" echo -n "Preparing Nexus ..." -export LIBEUFIN_NEXUS_URL=$NEXUS_URL +export LIBEUFIN_NEXUS_URL="$NEXUS_URL" # Make debit user, will buy Anastasis services. DEBIT_USERNAME=anastasis-debit-user DEBIT_PASSWORD=anastasis-debit-password -libeufin-nexus superuser $DEBIT_USERNAME --password=$DEBIT_PASSWORD +libeufin-nexus superuser "$DEBIT_USERNAME" --password="$DEBIT_PASSWORD" echo " OK" -export LIBEUFIN_NEXUS_USERNAME=$DEBIT_USERNAME -export LIBEUFIN_NEXUS_PASSWORD=$DEBIT_PASSWORD +export LIBEUFIN_NEXUS_USERNAME="$DEBIT_USERNAME" +export LIBEUFIN_NEXUS_PASSWORD="$DEBIT_PASSWORD" # Make credit user, will be Anastasis client. CREDIT_USERNAME=anastasis-credit-user CREDIT_PASSWORD=anastasis-credit-password echo -n "Create credit user (for anastasis) at Nexus ..." -libeufin-nexus superuser $CREDIT_USERNAME --password=$CREDIT_PASSWORD +libeufin-nexus superuser "$CREDIT_USERNAME" --password="$CREDIT_PASSWORD" echo " OK" -export LIBEUFIN_NEXUS_USERNAME=$CREDIT_USERNAME -export LIBEUFIN_NEXUS_PASSWORD=$CREDIT_PASSWORD +export LIBEUFIN_NEXUS_USERNAME="$CREDIT_USERNAME" +export LIBEUFIN_NEXUS_PASSWORD="$CREDIT_PASSWORD" prepare_nexus_account \ ebicsuserCredit \ @@ -225,7 +268,7 @@ prepare_nexus_account \ echo -n "Create facade ..." libeufin-cli facades new-anastasis-facade \ - --currency=$CURRENCY \ + --currency="$CURRENCY" \ --facade-name=facade-credit \ bankconnection-credit nexus-bankaccount-credit echo " OK" @@ -233,41 +276,29 @@ FACADE_URL=$(libeufin-cli facades list | jq .facades[0].baseUrl | tr -d \") ## Reach facade with: $FACADE_URL + $CREDIT_USERNAME + $CREDIT_PASSWORD -echo -n "Initialize Anastasis database ..." -# Name of the Postgres database we will use for the script. -# Will be dropped, do NOT use anything that might be used -# elsewhere - -TARGET_DB=`anastasis-config -c $CONF -s stasis-postgres -o CONFIG | sed -e "s/^postgres:\/\/\///"` - -dropdb $TARGET_DB >/dev/null 2>/dev/null || true -createdb $TARGET_DB || exit_skip "Could not create database $TARGET_DB" -anastasis-dbinit -c $CONF 2> anastasis-dbinit.log - -echo " OK" echo -n "Configuring Anastasis IBAN account ..." -anastasis-config -c $CONF \ +anastasis-config -c "$CONF" \ -s authorization-iban \ -o CREDIT_IBAN \ -V "${IBAN_CREDIT}" -anastasis-config -c $CONF \ +anastasis-config -c "$CONF" \ -s authorization-iban \ -o BUSINESS_NAME \ -V "${PERSON_CREDIT_NAME}" -anastasis-config -c $CONF \ +anastasis-config -c "$CONF" \ -s authorization-iban \ -o WIRE_GATEWAY_URL \ -V "${FACADE_URL}" -anastasis-config -c $CONF \ +anastasis-config -c "$CONF" \ -s authorization-iban \ -o WIRE_GATEWAY_AUTH_METHOD \ -V "basic" -anastasis-config -c $CONF \ +anastasis-config -c "$CONF" \ -s authorization-iban \ -o USERNAME \ -V "${LIBEUFIN_NEXUS_USERNAME}" -anastasis-config -c $CONF \ +anastasis-config -c "$CONF" \ -s authorization-iban \ -o PASSWORD \ -V "${LIBEUFIN_NEXUS_PASSWORD}" @@ -275,12 +306,12 @@ echo " OK" echo -n "Launching Anastasis service ..." PREFIX="" #valgrind -$PREFIX anastasis-httpd -c $CONF -L INFO 2> anastasis-httpd_1.log & +$PREFIX anastasis-httpd -c "$CONF" -L INFO 2> anastasis-httpd_1.log & echo " OK" echo -n "Waiting for Anastasis service ..." # Wait for Anastasis service to be available -for n in `seq 1 50` +for n in $(seq 1 50) do echo -n "." sleep 0.1 @@ -297,16 +328,15 @@ fi echo "OK" echo -n "Running backup logic ...," -anastasis-reducer -b > $B1FILE +anastasis-reducer -b > "$B1FILE" echo -n "." anastasis-reducer -a \ - '{"continent": "Testcontinent"}' \ - select_continent < $B1FILE > $B2FILE + '{"continent": "Demoworld"}' \ + select_continent < "$B1FILE" > "$B2FILE" echo -n "." anastasis-reducer -a \ - '{"country_code": "xx", - "currencies":["TESTKUDOS"]}' \ - select_country < $B2FILE > $B1FILE 2>> test_reducer.err + '{"country_code": "xx" }' \ + select_country < "$B2FILE" > "$B1FILE" 2>> test_reducer.err echo -n "." anastasis-reducer -a \ @@ -314,9 +344,12 @@ anastasis-reducer -a \ "full_name": "Max Musterman", "sq_number": "4", "birthdate": "2000-01-01"}}' \ - enter_user_attributes < $B1FILE > $B2FILE 2>> test_reducer.err + enter_user_attributes < "$B1FILE" > "$B2FILE" 2>> test_reducer.err echo -n "," -BASEIBAN=`echo -n $IBAN_DEBIT | gnunet-base32` +cat "$B2FILE" > "$B1FILE" +sync_providers "$B1FILE" "$B2FILE" +echo -n "," +BASEIBAN=$(echo -n $IBAN_DEBIT | gnunet-base32) anastasis-reducer -a \ "$(jq -n '{ authentication_method: { type: "iban", @@ -325,67 +358,102 @@ anastasis-reducer -a \ } }' \ --arg CHALLENGE "$BASEIBAN" )" \ - add_authentication < $B2FILE > $B1FILE 2>> test_reducer.err + add_authentication < "$B2FILE" > "$B1FILE" 2>> test_reducer.err +echo -n "." + +# "91GPWWR" encodes "Hans" +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "What is your name?", + "challenge": "91GPWWR" + } }' \ + add_authentication < "$B1FILE" > "$B2FILE" 2>> test_reducer.err echo -n "." + +mv "$B2FILE" "$B1FILE" + # Finished adding authentication methods anastasis-reducer \ - next < $B1FILE > $B2FILE 2>> test_reducer.err + next < "$B1FILE" > "$B2FILE" 2>> test_reducer.err echo -n "," # Finished policy review anastasis-reducer \ - next < $B2FILE > $B1FILE 2>> test_reducer.err + next < "$B2FILE" > "$B1FILE" 2>> test_reducer.err echo -n "." # Note: 'secret' must here be a Crockford base32-encoded value anastasis-reducer -a \ '{"secret": { "value" : "VERYHARDT0GVESSSECRET", "mime" : "text/plain" }}' \ - enter_secret < $B1FILE > $B2FILE 2>> test_reducer.err -mv $B2FILE $B1FILE -anastasis-reducer next < $B1FILE > $B2FILE 2>> test_reducer.err + enter_secret < "$B1FILE" > "$B2FILE" 2>> test_reducer.err +mv "$B2FILE" "$B1FILE" +anastasis-reducer next < "$B1FILE" > "$B2FILE" 2>> test_reducer.err echo " OK" echo -n "Final backup checks ..." -STATE=`jq -r -e .backup_state < $B2FILE` -if test "$STATE" != "BACKUP_FINISHED" +STATE=$(jq -r -e .backup_state < "$B2FILE") +if [ "$STATE" != "BACKUP_FINISHED" ] then exit_fail "Expected new state to be 'BACKUP_FINISHED', got '$STATE'" fi -jq -r -e .core_secret < $B2FILE > /dev/null && exit_fail "'core_secret' was not cleared upon success" +jq -r -e .core_secret < "$B2FILE" > /dev/null && exit_fail "'core_secret' was not cleared upon success" echo " OK" echo -n "Running recovery basic logic ..." -anastasis-reducer -r > $R1FILE +anastasis-reducer -r > "$R1FILE" anastasis-reducer -a \ - '{"continent": "Testcontinent"}' \ - select_continent < $R1FILE > $R2FILE + '{"continent": "Demoworld"}' \ + select_continent < "$R1FILE" > "$R2FILE" anastasis-reducer -a \ '{"country_code": "xx", "currencies":["TESTKUDOS"]}' \ - select_country < $R2FILE > $R1FILE 2>> test_reducer.err -anastasis-reducer -a '{"identity_attributes": { "full_name": "Max Musterman", "sq_number": "4", "birthdate": "2000-01-01" }}' enter_user_attributes < $R1FILE > $R2FILE 2>> test_reducer.err + select_country < "$R2FILE" > "$R1FILE" 2>> test_reducer.err +anastasis-reducer -a '{"identity_attributes": { "full_name": "Max Musterman", "sq_number": "4", "birthdate": "2000-01-01" }}' enter_user_attributes < "$R1FILE" > "$R2FILE" 2>> test_reducer.err -STATE=`jq -r -e .recovery_state < $R2FILE` -if test "$STATE" != "SECRET_SELECTING" +STATE=$(jq -r -e .recovery_state < "$R2FILE") +if [ "$STATE" != "SECRET_SELECTING" ] then exit_fail "Expected new state to be 'SECRET_SELECTING', got '$STATE'" fi echo " OK" -echo -n "Selecting default secret" -mv $R2FILE $R1FILE -anastasis-reducer next < $R1FILE > $R2FILE 2>> test_reducer.err +echo -n "Adding provider (to ensure it is loaded)" +anastasis-reducer -a '{"provider_url" : "http://localhost:8086/" }' add_provider < "$R2FILE" > "$R1FILE" +echo " OK" + +echo -n "Selecting secret to recover" +anastasis-reducer -a '{"attribute_mask": 0, "providers" : [ { "version": 1, "url" : "http://localhost:8086/" } ] }' \ + select_version < "$R1FILE" > "$R2FILE" 2>> test_reducer.err -STATE=`jq -r -e .recovery_state < $R2FILE` -if test "$STATE" != "CHALLENGE_SELECTING" +STATE=$(jq -r -e .recovery_state < "$R2FILE") +if [ "$STATE" != "CHALLENGE_SELECTING" ] then exit_fail "Expected new state to be 'CHALLENGE_SELECTING', got '$STATE'" fi echo " OK" +cp "$R2FILE" "$R1FILE" +sync_providers "$R1FILE" "$R2FILE" + echo -n "Running challenge selection logic ..." -NAME_UUID=`jq -r -e .recovery_information.challenges[0].uuid < $R2FILE` +UUID0=$(jq -r -e .recovery_information.challenges[0].uuid < "$R2FILE") +UUID1=$(jq -r -e .recovery_information.challenges[1].uuid < "$R2FILE") +UUID0Q=$(jq -r -e .recovery_information.challenges[0].instructions < "$R2FILE") +UUID1Q=$(jq -r -e .recovery_information.challenges[1].instructions < "$R2FILE") + +if [ "$UUID1Q" = 'What is your name?' ] +then + NAME_UUID=$UUID1 + IBAN_UUID=$UUID0 +else + NAME_UUID=$UUID0 + IBAN_UUID=$UUID1 +fi + +echo "OK" +echo -n "Solving first challenge ..." anastasis-reducer -a \ "$(jq -n ' { @@ -393,64 +461,79 @@ anastasis-reducer -a \ }' \ --arg UUID "$NAME_UUID" )" \ - select_challenge < $R2FILE > $R1FILE 2>> test_reducer.err + select_challenge < "$R2FILE" > "$R1FILE" 2>> test_reducer.err + +anastasis-reducer -a '{"answer": "Hans"}' \ + solve_challenge < "$R1FILE" > "$R2FILE" echo "OK" +echo -n "Solving IBAN challenge ..." + +anastasis-reducer -a \ + "$(jq -n ' + { + uuid: $UUID + }' \ + --arg UUID "$IBAN_UUID" + )" \ + select_challenge < "$R2FILE" > "$R1FILE" 2>> test_reducer.err +echo "OK" + -METHOD=`jq -r -e .challenge_feedback.\"$NAME_UUID\".method < $R1FILE` -if test "$METHOD" != "iban" +METHOD=$(jq -r -e .challenge_feedback.\"$IBAN_UUID\".state < "$R1FILE") +if [ "$METHOD" != "iban-instructions" ] then - exit_fail "Expected method to be 'iban', got ${METHOD}" + exit_fail "Expected method to be 'iban-instructions', got ${METHOD}" fi -ACC=`jq -r -e .challenge_feedback.\"$NAME_UUID\".details.credit_iban < $R1FILE` -if test "$ACC" != ${IBAN_CREDIT} +ACC=$(jq -r -e .challenge_feedback.\"$IBAN_UUID\".target_iban < "$R1FILE") +if [ "$ACC" != "${IBAN_CREDIT}" ] then exit_fail "Expected account to be ${IBAN_CREDIT}, got ${ACC}" fi anastasis-reducer \ - back < $R1FILE > $R2FILE 2>> test_reducer.err + back < "$R1FILE" > "$R2FILE" 2>> test_reducer.err -AMOUNT=`jq -r -e .challenge_feedback.\"$NAME_UUID\".details.challenge_amount < $R1FILE` -SUBJECT=`jq -r -e .challenge_feedback.\"$NAME_UUID\".details.wire_transfer_subject < $R1FILE` +AMOUNT=$(jq -r -e .challenge_feedback.\"$IBAN_UUID\".challenge_amount < "$R1FILE") +SUBJECT=$(jq -r -e .challenge_feedback.\"$IBAN_UUID\".wire_transfer_subject < "$R1FILE") -echo -n "Performing authorization wire transfer ..." +echo -n "Performing authorization wire transfer ${SUBJECT} ..." wire_transfer_to_anastasis "${AMOUNT}" "${SUBJECT}" echo " OK" echo -n "Triggering inbound check ..." -anastasis-helper-authorization-iban -c $CONF -t +anastasis-helper-authorization-iban -c "$CONF" -t -L INFO echo " OK" # Now we should get the secret... echo -n "Polling for recovery ..." -anastasis-reducer poll < $R2FILE > $R1FILE +anastasis-reducer poll -L INFO < "$R2FILE" > "$R1FILE" echo " OK" echo -n "Checking recovered secret ..." # finally: check here that we recovered the secret... -STATE=`jq -r -e .recovery_state < $R1FILE` -if test "$STATE" != "RECOVERY_FINISHED" +STATE=$(jq -r -e .recovery_state < "$R1FILE") +if [ "$STATE" != "RECOVERY_FINISHED" ] then - jq -e . $R1FILE + jq -e . "$R1FILE" exit_fail "Expected new state to be 'RECOVERY_FINISHED', got '$STATE'" fi -SECRET=`jq -r -e .core_secret.value < $R1FILE` -if test "$SECRET" != "VERYHARDT0GVESSSECRET" +SECRET=$(jq -r -e .core_secret.value < "$R1FILE") +if [ "$SECRET" != "VERYHARDT0GVESSSECRET" ] then - jq -e . $R1FILE + jq -e . "$R1FILE" exit_fail "Expected recovered secret to be 'VERYHARDT0GVESSSECRET', got '$SECRET'" fi -MIME=`jq -r -e .core_secret.mime < $R1FILE` -if test "$MIME" != "text/plain" +MIME=$(jq -r -e .core_secret.mime < "$R1FILE") +if [ "$MIME" != "text/plain" ] then - jq -e . $R1FILE + jq -e . "$R1FILE" exit_fail "Expected recovered mime to be 'text/plain', got '$MIME'" fi diff --git a/src/cli/test_reducer.conf b/src/cli/test_reducer.conf index df68b14..4f26a79 100644 --- a/src/cli/test_reducer.conf +++ b/src/cli/test_reducer.conf @@ -26,9 +26,10 @@ COST = TESTKUDOS:0.0 [exchange] +MASTER_PUBLIC_KEY = 3NX5DJDBD8XVGZYHV3PBF8C3Z4GK48XD59YY5GF3CZE8AJM04WSG +AML_THRESHOLD = TESTKUDOS:1000000 MAX_KEYS_CACHING = forever DB = postgres -MASTER_PRIV_FILE = ${TALER_DATA_HOME}/exchange/offline-keys/master.priv SERVE = tcp UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http UNIXPATH_MODE = 660 @@ -39,26 +40,40 @@ SIGNKEY_LEGAL_DURATION = 2 years LEGAL_DURATION = 2 years LOOKAHEAD_SIGN = 3 weeks 1 day LOOKAHEAD_PROVIDE = 2 weeks 1 day -KEYDIR = ${TALER_DATA_HOME}/exchange/live-keys/ -REVOCATION_DIR = ${TALER_DATA_HOME}/exchange/revocations/ TERMS_ETAG = 0 PRIVACY_ETAG = 0 +STEFAN_ABS = "TESTKUDOS:5" + +# Account of the EXCHANGE +[exchange-account-1] +# What is the exchange's bank account (with the "Taler Bank" demo system)? +PAYTO_URI = payto://iban/SANDBOXX/DE989651?receiver-name=Exchange+Company +ENABLE_DEBIT = YES +ENABLE_CREDIT = YES + +[exchange-accountcredentials-1] +WIRE_GATEWAY_URL = http://localhost:18082/accounts/exchange/taler-wire-gateway/ +WIRE_GATEWAY_AUTH_METHOD = basic +USERNAME = exchange +PASSWORD = x + + +[exchange-account-2] +PAYTO_URI = "payto://x-taler-bank/localhost/exchange?receiver-name=exchange" +ENABLE_DEBIT = YES +ENABLE_CREDIT = YES + +[exchange-accountcredentials-2] +WIRE_GATEWAY_AUTH_METHOD = none +WIRE_GATEWAY_URL = "http://localhost:18082/accounts/exchange/taler-wire-gateway/" [merchant] SERVE = tcp PORT = 9966 UNIXPATH = ${TALER_RUNTIME_DIR}/merchant.http UNIXPATH_MODE = 660 -DEFAULT_WIRE_FEE_AMORTIZATION = 1 DB = postgres -WIREFORMAT = default -# Set very low, so we can be sure that the database generated -# will contain wire transfers "ready" for the aggregator. -WIRE_TRANSFER_DELAY = 1 minute -DEFAULT_PAY_DEADLINE = 1 day -DEFAULT_MAX_DEPOSIT_FEE = TESTKUDOS:0.1 KEYFILE = ${TALER_DATA_HOME}/merchant/merchant.priv -DEFAULT_MAX_WIRE_FEE = TESTKUDOS:0.10 # Ensure that merchant reports EVERY deposit confirmation to auditor FORCE_AUDIT = YES @@ -79,30 +94,41 @@ BASE_URL = "http://localhost:8083/" DATABASE = postgres:///taler-auditor-basedb MAX_DEBT = TESTKUDOS:50.0 MAX_DEBT_BANK = TESTKUDOS:100000.0 -HTTP_PORT = 8082 +HTTP_PORT = 18082 SUGGESTED_EXCHANGE = http://localhost:8081/ SUGGESTED_EXCHANGE_PAYTO = payto://x-taler-bank/localhost/2 ALLOW_REGISTRATIONS = YES SERVE = http +[libeufin-bank] +CURRENCY = TESTKUDOS +WIRE_TYPE = iban +IBAN_PAYTO_BIC = SANDBOXX +DEFAULT_CUSTOMER_DEBT_LIMIT = TESTKUDOS:200 +DEFAULT_ADMIN_DEBT_LIMIT = TESTKUDOS:2000 +REGISTRATION_BONUS_ENABLED = yes +REGISTRATION_BONUS = TESTKUDOS:100 +SUGGESTED_WITHDRAWAL_EXCHANGE = http://localhost:8081/ +SERVE = tcp +PORT = 18082 + [exchangedb] IDLE_RESERVE_EXPIRATION_TIME = 4 weeks LEGAL_RESERVE_EXPIRATION_TIME = 7 years -[exchange-account-1] -PAYTO_URI = payto://x-taler-bank/localhost/Exchange -enable_debit = yes -enable_credit = yes +[auditordb-postgres] +CONFIG = "postgres:///talercheck" -[exchange-accountcredentials-1] -WIRE_GATEWAY_URL = "http://localhost:8082/taler-wire-gateway/Exchange/" -WIRE_GATEWAY_AUTH_METHOD = basic -USERNAME = Exchange -PASSWORD = x +[exchangedb-postgres] +CONFIG = "postgres:///talercheck" + +[merchantdb-postgres] +CONFIG = "postgres:///talercheck" [merchant-exchange-default] EXCHANGE_BASE_URL = http://localhost:8081/ CURRENCY = TESTKUDOS +MASTER_KEY = 3NX5DJDBD8XVGZYHV3PBF8C3Z4GK48XD59YY5GF3CZE8AJM04WSG [payments-generator] currency = TESTKUDOS @@ -123,6 +149,7 @@ fee_deposit = TESTKUDOS:0.01 fee_refresh = TESTKUDOS:0.01 fee_refund = TESTKUDOS:0.01 rsa_keysize = 1024 +CIPHER = RSA [coin_kudos_ct_10] value = TESTKUDOS:0.10 @@ -134,6 +161,7 @@ fee_deposit = TESTKUDOS:0.01 fee_refresh = TESTKUDOS:0.03 fee_refund = TESTKUDOS:0.01 rsa_keysize = 1024 +CIPHER = RSA [coin_kudos_1] value = TESTKUDOS:1 @@ -145,6 +173,7 @@ fee_deposit = TESTKUDOS:0.02 fee_refresh = TESTKUDOS:0.03 fee_refund = TESTKUDOS:0.01 rsa_keysize = 1024 +CIPHER = RSA [coin_kudos_2] value = TESTKUDOS:2 @@ -156,6 +185,7 @@ fee_deposit = TESTKUDOS:0.03 fee_refresh = TESTKUDOS:0.04 fee_refund = TESTKUDOS:0.02 rsa_keysize = 1024 +CIPHER = RSA [coin_kudos_4] value = TESTKUDOS:4 @@ -167,6 +197,7 @@ fee_deposit = TESTKUDOS:0.03 fee_refresh = TESTKUDOS:0.04 fee_refund = TESTKUDOS:0.02 rsa_keysize = 1024 +CIPHER = RSA [coin_kudos_5] value = TESTKUDOS:5 @@ -178,6 +209,7 @@ fee_deposit = TESTKUDOS:0.01 fee_refresh = TESTKUDOS:0.03 fee_refund = TESTKUDOS:0.01 rsa_keysize = 1024 +CIPHER = RSA [coin_kudos_8] value = TESTKUDOS:8 @@ -189,6 +221,7 @@ fee_deposit = TESTKUDOS:0.02 fee_refresh = TESTKUDOS:0.03 fee_refund = TESTKUDOS:0.04 rsa_keysize = 1024 +CIPHER = RSA [coin_kudos_10] value = TESTKUDOS:10 @@ -200,3 +233,4 @@ fee_deposit = TESTKUDOS:0.01 fee_refresh = TESTKUDOS:0.03 fee_refund = TESTKUDOS:0.01 rsa_keysize = 1024 +CIPHER = RSA diff --git a/src/cli/test_reducer_free.conf b/src/cli/test_reducer_free.conf new file mode 100644 index 0000000..4e46929 --- /dev/null +++ b/src/cli/test_reducer_free.conf @@ -0,0 +1,210 @@ +# This file is in the public domain. +[PATHS] +TALER_HOME = ${PWD}/test_reducer_home/ +TALER_DATA_HOME = $TALER_HOME/.local/share/taler/ +TALER_CONFIG_HOME = $TALER_HOME/.config/taler/ +TALER_CACHE_HOME = $TALER_HOME/.cache/taler/ +TALER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/${USER:-}/taler-system-runtime/ + +[taler] +CURRENCY = TESTKUDOS +CURRENCY_ROUND_UNIT = TESTKUDOS:0.01 + +[anastasis] +DB = postgres +ANNUAL_FEE = TESTKUDOS:0 +TRUTH_UPLOAD_FEE = TESTKUDOS:0.0 +UPLOAD_LIMIT_MB = 1 +ANNUAL_POLICY_UPLOAD_LIMIT = 128 +INSURANCE = TESTKUDOS:0 + +[anastasis-merchant-backend] +PAYMENT_BACKEND_URL = http://localhost:9966/ + +[authorization-question] +COST = TESTKUDOS:0.0 + + +[exchange] +MAX_KEYS_CACHING = forever +DB = postgres +MASTER_PRIV_FILE = ${TALER_DATA_HOME}/exchange/offline-keys/master.priv +SERVE = tcp +UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http +UNIXPATH_MODE = 660 +PORT = 8081 +BASE_URL = http://localhost:8081/ +SIGNKEY_DURATION = 2 weeks +SIGNKEY_LEGAL_DURATION = 2 years +LEGAL_DURATION = 2 years +LOOKAHEAD_SIGN = 3 weeks 1 day +LOOKAHEAD_PROVIDE = 2 weeks 1 day +KEYDIR = ${TALER_DATA_HOME}/exchange/live-keys/ +REVOCATION_DIR = ${TALER_DATA_HOME}/exchange/revocations/ +TERMS_ETAG = 0 +PRIVACY_ETAG = 0 + +[merchant] +SERVE = tcp +PORT = 9966 +UNIXPATH = ${TALER_RUNTIME_DIR}/merchant.http +UNIXPATH_MODE = 660 +DEFAULT_WIRE_FEE_AMORTIZATION = 1 +DB = postgres +WIREFORMAT = default +# Set very low, so we can be sure that the database generated +# will contain wire transfers "ready" for the aggregator. +WIRE_TRANSFER_DELAY = 1 minute +DEFAULT_PAY_DEADLINE = 1 day +DEFAULT_MAX_DEPOSIT_FEE = TESTKUDOS:0.1 +KEYFILE = ${TALER_DATA_HOME}/merchant/merchant.priv +DEFAULT_MAX_WIRE_FEE = TESTKUDOS:0.10 + +# Ensure that merchant reports EVERY deposit confirmation to auditor +FORCE_AUDIT = YES + +[auditor] +DB = postgres +AUDITOR_PRIV_FILE = ${TALER_DATA_HOME}/auditor/offline-keys/auditor.priv +SERVE = tcp +UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http +UNIXPATH_MODE = 660 +PORT = 8083 +AUDITOR_URL = http://localhost:8083/ +TINY_AMOUNT = TESTKUDOS:0.01 +AUDITOR_PRIV_FILE = ${TALER_DATA_HOME}/auditor/offline-keys/auditor.priv +BASE_URL = "http://localhost:8083/" + +[bank] +DATABASE = postgres:///taler-auditor-basedb +MAX_DEBT = TESTKUDOS:50.0 +MAX_DEBT_BANK = TESTKUDOS:100000.0 +HTTP_PORT = 8082 +SUGGESTED_EXCHANGE = http://localhost:8081/ +SUGGESTED_EXCHANGE_PAYTO = payto://x-taler-bank/localhost/2 +ALLOW_REGISTRATIONS = YES +SERVE = http + +[exchangedb] +IDLE_RESERVE_EXPIRATION_TIME = 4 weeks +LEGAL_RESERVE_EXPIRATION_TIME = 7 years + +[exchange-account-1] +PAYTO_URI = payto://x-taler-bank/localhost/Exchange +enable_debit = yes +enable_credit = yes + +[exchange-accountcredentials-1] +WIRE_GATEWAY_URL = "http://localhost:8082/accounts/Exchange/taler-wire-gateway/" +WIRE_GATEWAY_AUTH_METHOD = basic +USERNAME = Exchange +PASSWORD = x + +[merchant-exchange-default] +EXCHANGE_BASE_URL = http://localhost:8081/ +CURRENCY = TESTKUDOS + +[payments-generator] +currency = TESTKUDOS +instance = default +bank = http://localhost:8082/ +merchant = http://localhost:9966/ +exchange_admin = http://localhost:18080/ +exchange-admin = http://localhost:18080/ +exchange = http://localhost:8081/ + +[coin_kudos_ct_1] +value = TESTKUDOS:0.01 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.01 +fee_deposit = TESTKUDOS:0.01 +fee_refresh = TESTKUDOS:0.01 +fee_refund = TESTKUDOS:0.01 +rsa_keysize = 1024 +CIPHER = RSA + +[coin_kudos_ct_10] +value = TESTKUDOS:0.10 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.01 +fee_deposit = TESTKUDOS:0.01 +fee_refresh = TESTKUDOS:0.03 +fee_refund = TESTKUDOS:0.01 +rsa_keysize = 1024 +CIPHER = RSA + +[coin_kudos_1] +value = TESTKUDOS:1 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.02 +fee_deposit = TESTKUDOS:0.02 +fee_refresh = TESTKUDOS:0.03 +fee_refund = TESTKUDOS:0.01 +rsa_keysize = 1024 +CIPHER = RSA + +[coin_kudos_2] +value = TESTKUDOS:2 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.03 +fee_deposit = TESTKUDOS:0.03 +fee_refresh = TESTKUDOS:0.04 +fee_refund = TESTKUDOS:0.02 +rsa_keysize = 1024 +CIPHER = RSA + +[coin_kudos_4] +value = TESTKUDOS:4 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.03 +fee_deposit = TESTKUDOS:0.03 +fee_refresh = TESTKUDOS:0.04 +fee_refund = TESTKUDOS:0.02 +rsa_keysize = 1024 +CIPHER = RSA + +[coin_kudos_5] +value = TESTKUDOS:5 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.01 +fee_deposit = TESTKUDOS:0.01 +fee_refresh = TESTKUDOS:0.03 +fee_refund = TESTKUDOS:0.01 +rsa_keysize = 1024 +CIPHER = RSA + +[coin_kudos_8] +value = TESTKUDOS:8 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.05 +fee_deposit = TESTKUDOS:0.02 +fee_refresh = TESTKUDOS:0.03 +fee_refund = TESTKUDOS:0.04 +rsa_keysize = 1024 +CIPHER = RSA + +[coin_kudos_10] +value = TESTKUDOS:10 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.01 +fee_deposit = TESTKUDOS:0.01 +fee_refresh = TESTKUDOS:0.03 +fee_refund = TESTKUDOS:0.01 +rsa_keysize = 1024 +CIPHER = RSA diff --git a/src/cli/test_reducer_home/.local/share/taler/exchange-offline/master.priv b/src/cli/test_reducer_home/.local/share/taler/exchange-offline/master.priv new file mode 100644 index 0000000..d990a05 --- /dev/null +++ b/src/cli/test_reducer_home/.local/share/taler/exchange-offline/master.priv @@ -0,0 +1 @@ +>en͙[z3pwTj?cn21
\ No newline at end of file |