diff --git a/debian/mariadb-server.lintian-overrides b/debian/mariadb-server.lintian-overrides index c790a6ed22f..31363e5f414 100644 --- a/debian/mariadb-server.lintian-overrides +++ b/debian/mariadb-server.lintian-overrides @@ -1,5 +1,5 @@ # Used to check if running in Bash -bash-term-in-posix-shell '${BASH_VERSION' [usr/share/mysql/wsrep_notify:86] +bash-term-in-posix-shell '${BASH_VERSION' [usr/share/mysql/wsrep_notify:94] bash-term-in-posix-shell '[ "$url" ==' [usr/bin/mariadbd-safe:216] # In comment so false-positive bash-term-in-posix-shell 'let' [usr/bin/mariadbd-safe:41] diff --git a/debian/mariadb-test-data.lintian-overrides b/debian/mariadb-test-data.lintian-overrides index 025ff5f6caf..cb231d514f9 100644 --- a/debian/mariadb-test-data.lintian-overrides +++ b/debian/mariadb-test-data.lintian-overrides @@ -5,9 +5,6 @@ incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mys incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/funcs_1/lib/DataGen_modify.pl] incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/funcs_2/lib/gen_charset_utf8.pl] incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/rpl/extension/checksum.pl] -# This is used to check if we are running under Bash -bash-term-in-posix-shell '${BASH_VERSION' [usr/share/mysql/mysql-test/std_data/wsrep_notify.sh:87] -bash-term-in-posix-shell '${BASH_VERSION' [usr/share/mysql/mysql-test/std_data/wsrep_notify_ssl.sh:87] # These files are result files and they are supposed to be # Natial encoded (ISO/IEC 8859-1) not UTF-8 national-encoding [usr/share/mysql/mysql-test/include/ctype_E05C.inc] diff --git a/mysql-test/mariadb-test-run.pl b/mysql-test/mariadb-test-run.pl index 1d0c00195eb..a720924a75b 100755 --- a/mysql-test/mariadb-test-run.pl +++ b/mysql-test/mariadb-test-run.pl @@ -2306,6 +2306,19 @@ sub environment_setup { $ENV{'MYSQLHOTCOPY'}= $mysqlhotcopy; } + # ---------------------------------------------------- + # wsrep_notify (shipped example wsrep_notify_cmd script; tests point + # wsrep_notify_cmd at this instead of keeping a private std_data copy) + # ---------------------------------------------------- + my $wsrep_notify= + mtr_pl_maybe_exists("$bindir/support-files/wsrep_notify") || + mtr_pl_maybe_exists("$bindir/share/mariadb/wsrep_notify") || + mtr_pl_maybe_exists("$bindir/share/mysql/wsrep_notify"); + if ($wsrep_notify) + { + $ENV{'WSREP_NOTIFY_CMD'}= $wsrep_notify; + } + # ---------------------------------------------------- # perror # ---------------------------------------------------- diff --git a/mysql-test/std_data/wsrep_notify.sh b/mysql-test/std_data/wsrep_notify.sh deleted file mode 100755 index 828d5cf99da..00000000000 --- a/mysql-test/std_data/wsrep_notify.sh +++ /dev/null @@ -1,203 +0,0 @@ -#!/bin/sh -eu - -# This is a simple example of wsrep notification script (wsrep_notify_cmd). -# It will create 'wsrep' schema and two tables in it: 'membeship' and 'status' -# and fill them on every membership or node status change. -# -# Edit parameters below to specify the address and login to server: -# -USER='root' -PSWD='' -# -# If these parameters are not set, then the values -# passed by the server are taken: -# -HOST="127.0.0.1" -PORT=$NODE_MYPORT_1 -# -# Edit parameters below to specify SSL parameters: -# -ssl_cert="" -ssl_key="" -ssl_ca="" -ssl_capath="" -ssl_cipher="" -ssl_crl="" -ssl_crlpath="" -ssl_verify_server_cert=0 -# -# Client executable path: -# -CLIENT="$EXE_MYSQL" -# -# Name of schema and tables: -# -SCHEMA="mtr_wsrep_notify" -MEMB_TABLE="$SCHEMA.membership" -STATUS_TABLE="$SCHEMA.status" - -WSREP_ON='SET wsrep_on=ON' -WSREP_OFF='SET wsrep_on=OFF' - -BEGIN="$WSREP_OFF; -CREATE SCHEMA IF NOT EXISTS $SCHEMA; -CREATE TABLE IF NOT EXISTS $MEMB_TABLE ( - idx INT, - uuid CHAR(40), /* node UUID */ - name VARCHAR(32), /* node name */ - addr VARCHAR(256) /* node address */ -) ENGINE=MEMORY; -CREATE TABLE IF NOT EXISTS $STATUS_TABLE ( - size INT, /* component size */ - idx INT, /* this node index */ - status CHAR(16), /* this node status */ - uuid CHAR(40), /* cluster UUID */ - prim BOOLEAN /* if component is primary */ -) ENGINE=MEMORY; -BEGIN" -END="COMMIT; $WSREP_ON" - -configuration_change() -{ - echo "$BEGIN;" - - local idx=0 - - for NODE in $(echo "$MEMBERS" | sed s/,/\ /g) - do - echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, " - # Don't forget to properly quote string values - echo "'$NODE'" | sed s/\\//\',\'/g - echo ");" - idx=$(( $idx+1 )) - done - - echo "INSERT INTO $STATUS_TABLE VALUES($idx, $INDEX, '$STATUS', '$CLUSTER_UUID', $PRIMARY);" - - echo "$END;" -} - -status_update() -{ - echo "$BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; $END;" -} - -trim_string() -{ - if [ -n "${BASH_VERSION:-}" ]; then - local pattern="[![:space:]${2:-}]" - local x="${1#*$pattern}" - local z=${#1} - x=${#x} - if [ $x -ne $z ]; then - local y="${1%$pattern*}" - y=${#y} - x=$(( z-x-1 )) - y=$(( y-x+1 )) - printf '%s' "${1:$x:$y}" - else - printf '' - fi - else - local pattern="[[:space:]${2:-}]" - echo "$1" | sed -E "s/^$pattern+|$pattern+\$//g" - fi -} - -COM='status_update' # not a configuration change by default - -STATUS="" -CLUSTER_UUID="" -PRIMARY=0 -INDEX="" -MEMBERS="" - -while [ $# -gt 0 ]; do - case $1 in - '--status') - STATUS=$(trim_string "$2") - shift - ;; - '--uuid') - CLUSTER_UUID=$(trim_string "$2") - shift - ;; - '--primary') - arg=$(trim_string "$2") - [ "$arg" = 'yes' ] && PRIMARY=1 || PRIMARY=0 - COM='configuration_change' - shift - ;; - '--index') - INDEX=$(trim_string "$2") - shift - ;; - '--members') - MEMBERS=$(trim_string "$2") - shift - ;; - esac - shift -done - -USER=$(trim_string "$USER") -PSWD=$(trim_string "$PSWD") - -HOST=$(trim_string "$HOST") -PORT=$(trim_string "$PORT") - -case "$HOST" in -\[*) - HOST="${HOST##\[}" - HOST=$(trim_string "${HOST%%\]}") - ;; -esac - -if [ -z "$HOST" ]; then - HOST="${NOTIFY_HOST:-}" -fi -if [ -z "$PORT" ]; then - PORT="${NOTIFY_PORT:-}" -fi - -ssl_key=$(trim_string "$ssl_key"); -ssl_cert=$(trim_string "$ssl_cert"); -ssl_ca=$(trim_string "$ssl_ca"); -ssl_capath=$(trim_string "$ssl_capath"); -ssl_cipher=$(trim_string "$ssl_cipher"); -ssl_crl=$(trim_string "$ssl_crl"); -ssl_crlpath=$(trim_string "$ssl_crlpath"); -ssl_verify_server_cert=$(trim_string "$ssl_verify_server_cert"); - -SSL_PARAM="" - -if [ -n "$ssl_key$ssl_cert$ssl_ca$ssl_capath$ssl_cipher$ssl_crl$ssl_crlpath" ] -then - SSL_PARAM=' --ssl' - [ -n "$ssl_key" ] && SSL_PARAM="$SSL_PARAM --ssl-key='$ssl_key'" - [ -n "$ssl_cert" ] && SSL_PARAM="$SSL_PARAM --ssl-cert='$ssl_cert'" - [ -n "$ssl_ca" ] && SSL_PARAM="$SSL_PARAM --ssl-ca='$ssl_ca'" - [ -n "$ssl_capath" ] && SSL_PARAM="$SSL_PARAM --ssl-capath='$ssl_capath'" - [ -n "$ssl_cipher" ] && SSL_PARAM="$SSL_PARAM --ssl-cipher='$ssl_cipher'" - [ -n "$ssl_crl" ] && SSL_PARAM="$SSL_PARAM --ssl-crl='$ssl_crl'" - [ -n "$ssl_crlpath" ] && SSL_PARAM="$SSL_PARAM --ssl-crlpath='$ssl_crlpath'" - if [ -n "$ssl_verify_server_cert" ]; then - if [ "$ssl_verify_server_cert" != "0" -o \ - "$ssl_verify_server_cert" = "on" ] - then - SSL_PARAM="$SSL_PARAM --ssl-verify-server-cert" - fi - fi -fi - -case "$STATUS" in - 'joined' | 'donor' | 'synced') - "$COM" | eval "$CLIENT" -B "-u'$USER'"${PSWD:+" -p'$PSWD'"}\ - "-h'$HOST'" "-P$PORT"$SSL_PARAM - ;; - *) - # The node might be shutting down or not initialized - ;; -esac - -exit 0 diff --git a/mysql-test/std_data/wsrep_notify_argv_recorder.sh b/mysql-test/std_data/wsrep_notify_argv_recorder.sh new file mode 100755 index 00000000000..df7507d5609 --- /dev/null +++ b/mysql-test/std_data/wsrep_notify_argv_recorder.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +# Fake mysql client for the galera_wsrep_notify_pwd_injection test. +# Records argv and MYSQL_PWD instead of connecting anywhere, and drops +# the SQL the wsrep_notify script pipes into stdin. + +: > "$MYSQLTEST_VARDIR/tmp/wsrep_notify_pwd_injection.argv" +for arg in "$@"; do + printf '%s\n' "$arg" >> "$MYSQLTEST_VARDIR/tmp/wsrep_notify_pwd_injection.argv" +done +printf 'MYSQL_PWD=%s\n' "${MYSQL_PWD-}" > "$MYSQLTEST_VARDIR/tmp/wsrep_notify_pwd_injection.env" +cat >/dev/null +exit 0 diff --git a/mysql-test/std_data/wsrep_notify_ssl.sh b/mysql-test/std_data/wsrep_notify_ssl.sh deleted file mode 100755 index 12dc939e689..00000000000 --- a/mysql-test/std_data/wsrep_notify_ssl.sh +++ /dev/null @@ -1,203 +0,0 @@ -#!/bin/sh -eu - -# This is a simple example of wsrep notification script (wsrep_notify_cmd). -# It will create 'wsrep' schema and two tables in it: 'membeship' and 'status' -# and fill them on every membership or node status change. -# -# Edit parameters below to specify the address and login to server: -# -USER='root' -PSWD='' -# -# If these parameters are not set, then the values -# passed by the server are taken: -# -HOST="::1" -PORT=$NODE_MYPORT_1 -# -# Edit parameters below to specify SSL parameters: -# -ssl_cert="$MYSQL_TEST_DIR/std_data/client-cert.pem" -ssl_key="$MYSQL_TEST_DIR/std_data/client-key.pem" -ssl_ca="$MYSQL_TEST_DIR/std_data/cacert.pem" -ssl_capath="" -ssl_cipher="" -ssl_crl="" -ssl_crlpath="" -ssl_verify_server_cert=0 -# -# Client executable path: -# -CLIENT="$EXE_MYSQL" -# -# Name of schema and tables: -# -SCHEMA="mtr_wsrep_notify" -MEMB_TABLE="$SCHEMA.membership" -STATUS_TABLE="$SCHEMA.status" - -WSREP_ON='SET wsrep_on=ON' -WSREP_OFF='SET wsrep_on=OFF' - -BEGIN="$WSREP_OFF; -CREATE SCHEMA IF NOT EXISTS $SCHEMA; -CREATE TABLE IF NOT EXISTS $MEMB_TABLE ( - idx INT, - uuid CHAR(40), /* node UUID */ - name VARCHAR(32), /* node name */ - addr VARCHAR(256) /* node address */ -) ENGINE=MEMORY; -CREATE TABLE IF NOT EXISTS $STATUS_TABLE ( - size INT, /* component size */ - idx INT, /* this node index */ - status CHAR(16), /* this node status */ - uuid CHAR(40), /* cluster UUID */ - prim BOOLEAN /* if component is primary */ -) ENGINE=MEMORY; -BEGIN" -END="COMMIT; $WSREP_ON" - -configuration_change() -{ - echo "$BEGIN;" - - local idx=0 - - for NODE in $(echo "$MEMBERS" | sed s/,/\ /g) - do - echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, " - # Don't forget to properly quote string values - echo "'$NODE'" | sed s/\\//\',\'/g - echo ");" - idx=$(( $idx+1 )) - done - - echo "INSERT INTO $STATUS_TABLE VALUES($idx, $INDEX, '$STATUS', '$CLUSTER_UUID', $PRIMARY);" - - echo "$END;" -} - -status_update() -{ - echo "$BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; $END;" -} - -trim_string() -{ - if [ -n "${BASH_VERSION:-}" ]; then - local pattern="[![:space:]${2:-}]" - local x="${1#*$pattern}" - local z=${#1} - x=${#x} - if [ $x -ne $z ]; then - local y="${1%$pattern*}" - y=${#y} - x=$(( z-x-1 )) - y=$(( y-x+1 )) - printf '%s' "${1:$x:$y}" - else - printf '' - fi - else - local pattern="[[:space:]${2:-}]" - echo "$1" | sed -E "s/^$pattern+|$pattern+\$//g" - fi -} - -COM='status_update' # not a configuration change by default - -STATUS="" -CLUSTER_UUID="" -PRIMARY=0 -INDEX="" -MEMBERS="" - -while [ $# -gt 0 ]; do - case $1 in - '--status') - STATUS=$(trim_string "$2") - shift - ;; - '--uuid') - CLUSTER_UUID=$(trim_string "$2") - shift - ;; - '--primary') - arg=$(trim_string "$2") - [ "$arg" = 'yes' ] && PRIMARY=1 || PRIMARY=0 - COM='configuration_change' - shift - ;; - '--index') - INDEX=$(trim_string "$2") - shift - ;; - '--members') - MEMBERS=$(trim_string "$2") - shift - ;; - esac - shift -done - -USER=$(trim_string "$USER") -PSWD=$(trim_string "$PSWD") - -HOST=$(trim_string "$HOST") -PORT=$(trim_string "$PORT") - -case "$HOST" in -\[*) - HOST="${HOST##\[}" - HOST=$(trim_string "${HOST%%\]}") - ;; -esac - -if [ -z "$HOST" ]; then - HOST="${NOTIFY_HOST:-}" -fi -if [ -z "$PORT" ]; then - PORT="${NOTIFY_PORT:-}" -fi - -ssl_key=$(trim_string "$ssl_key"); -ssl_cert=$(trim_string "$ssl_cert"); -ssl_ca=$(trim_string "$ssl_ca"); -ssl_capath=$(trim_string "$ssl_capath"); -ssl_cipher=$(trim_string "$ssl_cipher"); -ssl_crl=$(trim_string "$ssl_crl"); -ssl_crlpath=$(trim_string "$ssl_crlpath"); -ssl_verify_server_cert=$(trim_string "$ssl_verify_server_cert"); - -SSL_PARAM="" - -if [ -n "$ssl_key$ssl_cert$ssl_ca$ssl_capath$ssl_cipher$ssl_crl$ssl_crlpath" ] -then - SSL_PARAM=' --ssl' - [ -n "$ssl_key" ] && SSL_PARAM="$SSL_PARAM --ssl-key='$ssl_key'" - [ -n "$ssl_cert" ] && SSL_PARAM="$SSL_PARAM --ssl-cert='$ssl_cert'" - [ -n "$ssl_ca" ] && SSL_PARAM="$SSL_PARAM --ssl-ca='$ssl_ca'" - [ -n "$ssl_capath" ] && SSL_PARAM="$SSL_PARAM --ssl-capath='$ssl_capath'" - [ -n "$ssl_cipher" ] && SSL_PARAM="$SSL_PARAM --ssl-cipher='$ssl_cipher'" - [ -n "$ssl_crl" ] && SSL_PARAM="$SSL_PARAM --ssl-crl='$ssl_crl'" - [ -n "$ssl_crlpath" ] && SSL_PARAM="$SSL_PARAM --ssl-crlpath='$ssl_crlpath'" - if [ -n "$ssl_verify_server_cert" ]; then - if [ "$ssl_verify_server_cert" != "0" -o \ - "$ssl_verify_server_cert" = "on" ] - then - SSL_PARAM="$SSL_PARAM --ssl-verify-server-cert" - fi - fi -fi - -case "$STATUS" in - 'joined' | 'donor' | 'synced') - "$COM" | eval "$CLIENT" -B "-u'$USER'"${PSWD:+" -p'$PSWD'"}\ - "-h'$HOST'" "-P$PORT"$SSL_PARAM - ;; - *) - # The node might be shutting down or not initialized - ;; -esac - -exit 0 diff --git a/mysql-test/suite/galera/r/galera_var_notify_cmd.result b/mysql-test/suite/galera/r/galera_var_notify_cmd.result index 432d6c0adbd..60c0bc700fa 100644 --- a/mysql-test/suite/galera/r/galera_var_notify_cmd.result +++ b/mysql-test/suite/galera/r/galera_var_notify_cmd.result @@ -7,7 +7,7 @@ EXPECT_2 SELECT MAX(size) AS EXPECT_2 FROM mtr_wsrep_notify.status; EXPECT_2 2 -SELECT COUNT(DISTINCT idx) AS EXPECT_2 FROM mtr_wsrep_notify.status; -EXPECT_2 -2 +SELECT COUNT(*) AS EXPECT_1 FROM mtr_wsrep_notify.status, INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'WSREP_LOCAL_INDEX' AND idx = VARIABLE_VALUE; +EXPECT_1 +1 DROP SCHEMA mtr_wsrep_notify; diff --git a/mysql-test/suite/galera/r/galera_var_notify_ssl_ipv6.result b/mysql-test/suite/galera/r/galera_var_notify_ssl_ipv6.result index 432d6c0adbd..60c0bc700fa 100644 --- a/mysql-test/suite/galera/r/galera_var_notify_ssl_ipv6.result +++ b/mysql-test/suite/galera/r/galera_var_notify_ssl_ipv6.result @@ -7,7 +7,7 @@ EXPECT_2 SELECT MAX(size) AS EXPECT_2 FROM mtr_wsrep_notify.status; EXPECT_2 2 -SELECT COUNT(DISTINCT idx) AS EXPECT_2 FROM mtr_wsrep_notify.status; -EXPECT_2 -2 +SELECT COUNT(*) AS EXPECT_1 FROM mtr_wsrep_notify.status, INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'WSREP_LOCAL_INDEX' AND idx = VARIABLE_VALUE; +EXPECT_1 +1 DROP SCHEMA mtr_wsrep_notify; diff --git a/mysql-test/suite/galera/r/galera_wsrep_notify_pwd_injection.result b/mysql-test/suite/galera/r/galera_wsrep_notify_pwd_injection.result new file mode 100644 index 00000000000..c571d6010fd --- /dev/null +++ b/mysql-test/suite/galera/r/galera_wsrep_notify_pwd_injection.result @@ -0,0 +1,11 @@ +connection node_2; +connection node_1; +connection node_1; +SELECT 1; +1 +1 +-B +-uroot +-h127.0.0.1 +-P3306 +MYSQL_PWD=x' y='z diff --git a/mysql-test/suite/galera/t/galera_var_notify_cmd-master.opt b/mysql-test/suite/galera/t/galera_var_notify_cmd-master.opt index 70dfc98736b..4d11610bff5 100644 --- a/mysql-test/suite/galera/t/galera_var_notify_cmd-master.opt +++ b/mysql-test/suite/galera/t/galera_var_notify_cmd-master.opt @@ -1 +1 @@ ---wsrep_notify_cmd=$MYSQL_TEST_DIR/std_data/wsrep_notify.sh --wsrep-sync-wait=0 +--wsrep-sync-wait=0 diff --git a/mysql-test/suite/galera/t/galera_var_notify_cmd.cnf b/mysql-test/suite/galera/t/galera_var_notify_cmd.cnf new file mode 100644 index 00000000000..ee15122f4af --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_notify_cmd.cnf @@ -0,0 +1,11 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep_notify_cmd=@ENV.WSREP_NOTIFY_CMD + +[ENV] +WSREP_NOTIFY_CLIENT= @ENV.EXE_MYSQL +WSREP_NOTIFY_SCHEMA= mtr_wsrep_notify +WSREP_NOTIFY_PSWD= +WSREP_NOTIFY_HOST= 127.0.0.1 +WSREP_NOTIFY_PORT= @mysqld.1.port diff --git a/mysql-test/suite/galera/t/galera_var_notify_cmd.test b/mysql-test/suite/galera/t/galera_var_notify_cmd.test index fda61bf2914..acdc5255a77 100644 --- a/mysql-test/suite/galera/t/galera_var_notify_cmd.test +++ b/mysql-test/suite/galera/t/galera_var_notify_cmd.test @@ -1,8 +1,13 @@ # -# Test wsrep_notify_cmd. We use a version of the support-files/wsrep_notify.sh script that writes -# notifications into a table. +# Test wsrep_notify_cmd. We use the support-files/wsrep_notify.sh script, which writes +# the current view into a table. # +if (!$WSREP_NOTIFY_CMD) +{ + --skip Needs the shipped wsrep_notify script +} + --source include/galera_cluster.inc --source include/force_restart.inc @@ -12,7 +17,7 @@ SELECT COUNT(DISTINCT uuid) AS EXPECT_2 FROM mtr_wsrep_notify.membership; SELECT MAX(size) AS EXPECT_2 FROM mtr_wsrep_notify.status; -SELECT COUNT(DISTINCT idx) AS EXPECT_2 FROM mtr_wsrep_notify.status; +SELECT COUNT(*) AS EXPECT_1 FROM mtr_wsrep_notify.status, INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'WSREP_LOCAL_INDEX' AND idx = VARIABLE_VALUE; # CLEANUP DROP SCHEMA mtr_wsrep_notify; diff --git a/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6-master.opt b/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6-master.opt index 99c5889916b..4d11610bff5 100644 --- a/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6-master.opt +++ b/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6-master.opt @@ -1 +1 @@ ---wsrep_notify_cmd=$MYSQL_TEST_DIR/std_data/wsrep_notify_ssl.sh --wsrep-sync-wait=0 +--wsrep-sync-wait=0 diff --git a/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6.cnf b/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6.cnf index a8c2826ad0d..901d22045ec 100644 --- a/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6.cnf +++ b/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6.cnf @@ -11,6 +11,7 @@ wsrep_node_incoming_address='[::1]:@mysqld.1.port' wsrep_node_address=[::1]:@mysqld.1.#galera_port wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port' bind-address=:: +wsrep_notify_cmd=@ENV.WSREP_NOTIFY_CMD [mysqld.2] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' @@ -19,3 +20,13 @@ wsrep_node_incoming_address='[::1]:@mysqld.2.port' wsrep_node_address=[::1]:@mysqld.2.#galera_port wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port' bind-address=:: + +[ENV] +WSREP_NOTIFY_CLIENT= @ENV.EXE_MYSQL +WSREP_NOTIFY_SCHEMA= mtr_wsrep_notify +WSREP_NOTIFY_PSWD= +WSREP_NOTIFY_HOST= ::1 +WSREP_NOTIFY_PORT= @mysqld.1.port +WSREP_NOTIFY_SSL_CERT= @ENV.MYSQL_TEST_DIR/std_data/client-cert.pem +WSREP_NOTIFY_SSL_KEY= @ENV.MYSQL_TEST_DIR/std_data/client-key.pem +WSREP_NOTIFY_SSL_CA= @ENV.MYSQL_TEST_DIR/std_data/cacert.pem diff --git a/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6.test b/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6.test index eaef34cce32..4abe916f8e4 100644 --- a/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6.test +++ b/mysql-test/suite/galera/t/galera_var_notify_ssl_ipv6.test @@ -1,8 +1,13 @@ # -# Test wsrep_notify_cmd. We use a version of the support-files/wsrep_notify.sh script that writes -# notifications into a table. +# Test wsrep_notify_cmd. We use the support-files/wsrep_notify.sh script, which writes +# the current view into a table. # +if (!$WSREP_NOTIFY_CMD) +{ + --skip Needs the shipped wsrep_notify script +} + --let galera_connection_address=::1 --source include/galera_cluster.inc --source include/have_ssl_communication.inc @@ -15,7 +20,7 @@ SELECT COUNT(DISTINCT uuid) AS EXPECT_2 FROM mtr_wsrep_notify.membership; SELECT MAX(size) AS EXPECT_2 FROM mtr_wsrep_notify.status; -SELECT COUNT(DISTINCT idx) AS EXPECT_2 FROM mtr_wsrep_notify.status; +SELECT COUNT(*) AS EXPECT_1 FROM mtr_wsrep_notify.status, INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'WSREP_LOCAL_INDEX' AND idx = VARIABLE_VALUE; # CLEANUP DROP SCHEMA mtr_wsrep_notify; diff --git a/mysql-test/suite/galera/t/galera_wsrep_notify_pwd_injection.cnf b/mysql-test/suite/galera/t/galera_wsrep_notify_pwd_injection.cnf new file mode 100644 index 00000000000..ca6a0f2b4fd --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wsrep_notify_pwd_injection.cnf @@ -0,0 +1,8 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep_notify_cmd=@ENV.WSREP_NOTIFY_CMD + +[ENV] +WSREP_NOTIFY_CLIENT= @ENV.MYSQL_TEST_DIR/std_data/wsrep_notify_argv_recorder.sh +WSREP_NOTIFY_PSWD=x' y='z diff --git a/mysql-test/suite/galera/t/galera_wsrep_notify_pwd_injection.test b/mysql-test/suite/galera/t/galera_wsrep_notify_pwd_injection.test new file mode 100644 index 00000000000..59a9ff409d8 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wsrep_notify_pwd_injection.test @@ -0,0 +1,38 @@ +# +# A configured wsrep_notify_cmd password containing an apostrophe and a +# space must reach the client intact, as a single value, not split into +# two arguments or otherwise reinterpreted. +# +# STEPS: +# - node 1's wsrep_notify_cmd is configured with such a password, and a +# fake argv-recording client instead of a real mysql client +# - wait for the 2-node cluster to fully form (node 1 reaches Synced) +# - check that the notify script passes the password intact via +# MYSQL_PWD, and that it never appears in argv at all +# + +if (!$WSREP_NOTIFY_CMD) +{ + --skip Needs the shipped wsrep_notify script +} + +--source include/galera_cluster.inc +--source include/force_restart.inc + +--connection node_1 +SELECT 1; + +--let $wait_condition = SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'WSREP_LOCAL_STATE_COMMENT' +--source include/wait_condition.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--sleep 2 + +--let $argv_file = $MYSQLTEST_VARDIR/tmp/wsrep_notify_pwd_injection.argv +--let $env_file = $MYSQLTEST_VARDIR/tmp/wsrep_notify_pwd_injection.env +cat_file $argv_file; +cat_file $env_file; +--remove_file $argv_file +--remove_file $env_file diff --git a/support-files/wsrep_notify.sh b/support-files/wsrep_notify.sh index 4070ec920f8..961b6049783 100755 --- a/support-files/wsrep_notify.sh +++ b/support-files/wsrep_notify.sh @@ -4,40 +4,44 @@ # It will create 'wsrep' schema and two tables in it: 'membeship' and 'status' # and fill them on every membership or node status change. # -# Edit parameters below to specify the address and login to server: +# Edit parameters below to specify the address and login to server. +# Each can also be set via a WSREP_NOTIFY_* environment variable (used by +# the test suite so it can drive this same script instead of a copy of it). # -USER='root' -PSWD='rootpass' +USER="${WSREP_NOTIFY_USER-root}" +PSWD="${WSREP_NOTIFY_PSWD-rootpass}" # # If these parameters are not set, then the values # passed by the server are taken: # -HOST="127.0.0.1" -PORT=3306 +HOST="${WSREP_NOTIFY_HOST-127.0.0.1}" +PORT="${WSREP_NOTIFY_PORT-3306}" # # Edit parameters below to specify SSL parameters: # -ssl_cert="" -ssl_key="" -ssl_ca="" -ssl_capath="" -ssl_cipher="" -ssl_crl="" -ssl_crlpath="" -ssl_verify_server_cert=0 +ssl_cert="${WSREP_NOTIFY_SSL_CERT-}" +ssl_key="${WSREP_NOTIFY_SSL_KEY-}" +ssl_ca="${WSREP_NOTIFY_SSL_CA-}" +ssl_capath="${WSREP_NOTIFY_SSL_CAPATH-}" +ssl_cipher="${WSREP_NOTIFY_SSL_CIPHER-}" +ssl_crl="${WSREP_NOTIFY_SSL_CRL-}" +ssl_crlpath="${WSREP_NOTIFY_SSL_CRLPATH-}" +ssl_verify_server_cert="${WSREP_NOTIFY_SSL_VERIFY_SERVER_CERT-0}" # # Client executable path: # -CLIENT="mysql" +CLIENT="${WSREP_NOTIFY_CLIENT-mysql}" # # Name of schema and tables: # -SCHEMA="wsrep" +SCHEMA="${WSREP_NOTIFY_SCHEMA-wsrep}" MEMB_TABLE="$SCHEMA.membership" STATUS_TABLE="$SCHEMA.status" WSREP_ON='SET wsrep_on=ON' WSREP_OFF='SET wsrep_on=OFF' +# quote_sql() output relies on backslash escapes being honoured +SQL_MODE="SET SESSION sql_mode=REPLACE(@@sql_mode,'NO_BACKSLASH_ESCAPES','')" BEGIN="CREATE SCHEMA IF NOT EXISTS $SCHEMA; CREATE TABLE IF NOT EXISTS $MEMB_TABLE ( @@ -58,27 +62,31 @@ END="COMMIT; $WSREP_ON" configuration_change() { - echo "$WSREP_OFF; DROP SCHEMA IF EXISTS $SCHEMA; $BEGIN;" + printf '%s\n' "$SQL_MODE; $WSREP_OFF; DROP SCHEMA IF EXISTS $SCHEMA; $BEGIN;" - local idx=0 + local idx=0 id rest name addr IFS=',' - for NODE in $(echo "$MEMBERS" | sed s/,/\ /g) + # MEMBERS is "id/name/addr,..."; addr may itself contain '/' or '[]' + set -f + for NODE in $MEMBERS do - echo "INSERT INTO $MEMB_TABLE VALUES ( $idx, " - # Don't forget to properly quote string values - echo "'$NODE'" | sed s/\\//\',\'/g - echo ");" + id=${NODE%%/*} + rest=${NODE#*/} + name=${rest%%/*} + addr=${rest#*/} + printf '%s\n' "INSERT INTO $MEMB_TABLE VALUES ($idx, '$(quote_sql "$id")', '$(quote_sql "$name")', '$(quote_sql "$addr")');" idx=$(( $idx+1 )) done + set +f - echo "INSERT INTO $STATUS_TABLE VALUES($idx, $INDEX, '$STATUS', '$CLUSTER_UUID', $PRIMARY);" + printf '%s\n' "INSERT INTO $STATUS_TABLE VALUES($idx, $INDEX, '$(quote_sql "$STATUS")', '$(quote_sql "$CLUSTER_UUID")', $PRIMARY);" - echo "$END;" + printf '%s\n' "$END;" } status_update() { - echo "$WSREP_OFF; $BEGIN; UPDATE $STATUS_TABLE SET status='$STATUS'; $END;" + printf '%s\n' "$SQL_MODE; $WSREP_OFF; $BEGIN; UPDATE $STATUS_TABLE SET status='$(quote_sql "$STATUS")'; $END;" } trim_string() @@ -99,10 +107,19 @@ trim_string() fi else local pattern="[[:space:]${2:-}]" - echo "$1" | sed -E "s/^$pattern+|$pattern+\$//g" + printf '%s\n' "$1" | sed -E "s/^$pattern+|$pattern+\$//g" fi } +# Escape a value for embedding in a single-quoted SQL string literal. +# Backslash must be escaped first, or a trailing backslash would swallow +# the closing quote. Quotes are doubled so even with NO_BACKSLASH_ESCAPES +# they can't end the literal early. +quote_sql() +{ + printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e "s/'/''/g" +} + COM='status_update' # not a configuration change by default STATUS="" @@ -168,31 +185,30 @@ ssl_crl=$(trim_string "$ssl_crl"); ssl_crlpath=$(trim_string "$ssl_crlpath"); ssl_verify_server_cert=$(trim_string "$ssl_verify_server_cert"); -SSL_PARAM="" - -if [ -n "$ssl_key$ssl_cert$ssl_ca$ssl_capath$ssl_cipher$ssl_crl$ssl_crlpath" ] -then - SSL_PARAM=' --ssl' - [ -n "$ssl_key" ] && SSL_PARAM="$SSL_PARAM --ssl-key='$ssl_key'" - [ -n "$ssl_cert" ] && SSL_PARAM="$SSL_PARAM --ssl-cert='$ssl_cert'" - [ -n "$ssl_ca" ] && SSL_PARAM="$SSL_PARAM --ssl-ca='$ssl_ca'" - [ -n "$ssl_capath" ] && SSL_PARAM="$SSL_PARAM --ssl-capath='$ssl_capath'" - [ -n "$ssl_cipher" ] && SSL_PARAM="$SSL_PARAM --ssl-cipher='$ssl_cipher'" - [ -n "$ssl_crl" ] && SSL_PARAM="$SSL_PARAM --ssl-crl='$ssl_crl'" - [ -n "$ssl_crlpath" ] && SSL_PARAM="$SSL_PARAM --ssl-crlpath='$ssl_crlpath'" - if [ -n "$ssl_verify_server_cert" ]; then - if [ "$ssl_verify_server_cert" != "0" -o \ - "$ssl_verify_server_cert" = "on" ] - then - SSL_PARAM="$SSL_PARAM --ssl-verify-server-cert" - fi - fi -fi - case "$STATUS" in 'joined' | 'donor' | 'synced') - "$COM" | eval "$CLIENT" -B "-u'$USER'"${PSWD:+" -p'$PSWD'"}\ - "-h'$HOST'" "-P$PORT"$SSL_PARAM + set -- -B -u"$USER" -h"$HOST" -P"$PORT" + + if [ -n "$ssl_key$ssl_cert$ssl_ca$ssl_capath$ssl_cipher$ssl_crl$ssl_crlpath" ] + then + set -- "$@" --ssl + [ -n "$ssl_key" ] && set -- "$@" --ssl-key="$ssl_key" + [ -n "$ssl_cert" ] && set -- "$@" --ssl-cert="$ssl_cert" + [ -n "$ssl_ca" ] && set -- "$@" --ssl-ca="$ssl_ca" + [ -n "$ssl_capath" ] && set -- "$@" --ssl-capath="$ssl_capath" + [ -n "$ssl_cipher" ] && set -- "$@" --ssl-cipher="$ssl_cipher" + [ -n "$ssl_crl" ] && set -- "$@" --ssl-crl="$ssl_crl" + [ -n "$ssl_crlpath" ] && set -- "$@" --ssl-crlpath="$ssl_crlpath" + if [ -n "$ssl_verify_server_cert" ]; then + if [ "$ssl_verify_server_cert" != "0" -o \ + "$ssl_verify_server_cert" = "on" ] + then + set -- "$@" --ssl-verify-server-cert + fi + fi + fi + + "$COM" | MYSQL_PWD="$PSWD" exec "$CLIENT" "$@" ;; *) # The node might be shutting down or not initialized