diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/wsrep_sst_common.sh | 44 | ||||
-rw-r--r-- | scripts/wsrep_sst_mariabackup.sh | 138 |
2 files changed, 153 insertions, 29 deletions
diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index f5adf0b0fd8..a6f439b5348 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -25,6 +25,7 @@ WSREP_SST_OPT_DATA="" WSREP_SST_OPT_AUTH=${WSREP_SST_OPT_AUTH:-} WSREP_SST_OPT_USER=${WSREP_SST_OPT_USER:-} WSREP_SST_OPT_PSWD=${WSREP_SST_OPT_PSWD:-} +WSREP_SST_OPT_REMOTE_AUTH=${WSREP_SST_OPT_REMOTE_AUTH:-} WSREP_SST_OPT_DEFAULT="" WSREP_SST_OPT_EXTRA_DEFAULT="" WSREP_SST_OPT_SUFFIX_DEFAULT="" @@ -34,6 +35,7 @@ INNODB_DATA_HOME_DIR_ARG="" INNODB_LOG_GROUP_HOME_ARG="" INNODB_UNDO_DIR_ARG="" LOG_BIN_ARG="" +readonly WSREP_SST_OPT_REMOTE_AUTH while [ $# -gt 0 ]; do case "$1" in @@ -121,7 +123,8 @@ case "$1" in WSREP_SST_OPT_BYPASS=1 ;; '--datadir') - readonly WSREP_SST_OPT_DATA="$2" + # strip trailing '/' + readonly WSREP_SST_OPT_DATA="${2%/}" shift ;; '--innodb-data-home-dir') @@ -320,12 +323,22 @@ readonly WSREP_SST_OPT_AUTH # Splitting AUTH into potential user:password pair if ! wsrep_auth_not_set then - WSREP_SST_OPT_USER="${WSREP_SST_OPT_AUTH%%:*}" + WSREP_SST_OPT_USER="${WSREP_SST_OPT_AUTH%:*}" WSREP_SST_OPT_PSWD="${WSREP_SST_OPT_AUTH##*:}" fi readonly WSREP_SST_OPT_USER readonly WSREP_SST_OPT_PSWD +if [ -n "$WSREP_SST_OPT_REMOTE_AUTH" ] +then + # Split auth string at the last ':' + readonly WSREP_SST_OPT_REMOTE_USER="${WSREP_SST_OPT_REMOTE_AUTH%:*}" + readonly WSREP_SST_OPT_REMOTE_PSWD="${WSREP_SST_OPT_REMOTE_AUTH##*:}" +else + readonly WSREP_SST_OPT_REMOTE_USER= + readonly WSREP_SST_OPT_REMOTE_PSWD= +fi + if [ -n "${WSREP_SST_OPT_DATA:-}" ] then SST_PROGRESS_FILE="$WSREP_SST_OPT_DATA/sst_in_progress" @@ -385,6 +398,19 @@ wsrep_check_programs() return $ret } +# Generate a string equivalent to 16 random bytes +wsrep_gen_secret() +{ + if [ -x /usr/bin/openssl ] + then + echo `/usr/bin/openssl rand -hex 16` + else + printf "%04x%04x%04x%04x%04x%04x%04x%04x" \ + $RANDOM $RANDOM $RANDOM $RANDOM \ + $RANDOM $RANDOM $RANDOM $RANDOM + fi +} + # # user can specify mariabackup specific settings that will be used during sst # process like encryption, etc..... @@ -396,14 +422,22 @@ wsrep_check_programs() parse_cnf() { local group=$1 - local var=$2 + local var=${2//_/-} # normalize variable name by replacing all '_' with '-' local reval="" - # normalize the variable names specified in cnf file (user can use _ or - for example log-bin or log_bin) + # first normalize output variable names specified in cnf file: + # user can use _ or - (for example log-bin or log_bin) and/or prefix + # variable with --loose- # then search for needed variable # finally get the variable value (if variables has been specified multiple time use the last value only) - reval=$($MY_PRINT_DEFAULTS "${group}" | awk -v var="${var}" 'BEGIN { OFS=FS="=" } { gsub(/_/,"-",$1); if ( $1=="--"var) lastval=substr($0,length($1)+2) } END { print lastval}') + reval=$($MY_PRINT_DEFAULTS "${group}" | \ + awk -v var="${var}" 'BEGIN { OFS=FS="=" } \ + { sub(/^--loose/,"-",$0); \ + gsub(/_/,"-",$1); \ + if ( $1=="--"var) \ + lastval=substr($0,length($1)+2) } \ + END { print lastval}') # use default if we haven't found a value if [ -z "$reval" ]; then diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 231cf6e3702..f54afb878b5 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -37,6 +37,7 @@ REMOTEIP="" tcert="" tpem="" tkey="" +tmode="DISABLED" sockopt="" progress="" ttime=0 @@ -72,6 +73,8 @@ xtmpdir="" scomp="" sdecomp="" +readonly SECRET_TAG="secret" + # Required for backup locks # For backup locks it is 1 sent by joiner # 5.6.21 PXC and later can't donate to an older joiner @@ -264,24 +267,30 @@ get_transfer() exit 22 fi stagemsg+="-OpenSSL-Encrypted-3" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - if [[ -z $tcert ]];then + if [[ -z $tcert ]];then + # no verification + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then wsrep_log_info "Decrypting with cert=${tpem}, key=${tkey}, verify=0" tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tpem},key=${tkey},verify=0${sockopt} stdio" else - wsrep_log_info "Decrypting with cert=${tpem}, key=${tkey}, cafile=${tcert}" - tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tpem},key=${tkey},cafile=${tcert}${sockopt} stdio" - fi - else - if [[ -z $tcert ]];then wsrep_log_info "Encrypting with cert=${tpem}, key=${tkey}, verify=0" tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tpem},key=${tkey},verify=0${sockopt}" + fi + else + # CA verification + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + wsrep_log_info "Decrypting with cert=${tpem}, key=${tkey}, cafile=${tcert}" + tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tpem},key=${tkey},cafile=${tcert}${sockopt} stdio" else + if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then + CN_option=",commonname=$WSREP_SST_OPT_REMOTE_USER" + else + CN_option="" + fi wsrep_log_info "Encrypting with cert=${tpem}, key=${tkey}, cafile=${tcert}" - tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tpem},key=${tkey},cafile=${tcert}${sockopt}" + tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tpem},key=${tkey},cafile=${tcert}${CN_option}${sockopt}" fi fi - else if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio" @@ -290,7 +299,6 @@ get_transfer() fi fi fi - } parse_cnf() @@ -298,10 +306,17 @@ parse_cnf() local group=$1 local var=$2 # print the default settings for given group using my_print_default. + # remove possible 'loose' variable name prefix # normalize the variable names specified in cnf file (user can use _ or - for example log-bin or log_bin) # then grep for needed variable # finally get the variable value (if variables has been specified multiple time use the last value only) - reval=$($MY_PRINT_DEFAULTS $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2- | tail -1) + reval=$($MY_PRINT_DEFAULTS $group | \ + awk -F= '{ sub(/^--loose/,"-",$0); \ + if ($1 ~ /_/) \ + { gsub(/_/,"-",$1); print $1"="$2 } \ + else \ + { print $0 }}' | \ + grep -- "--$var=" | cut -d= -f2- | tail -1) if [[ -z $reval ]];then [[ -n $3 ]] && reval=$3 fi @@ -351,6 +366,24 @@ adjust_progress() fi } +check_server_ssl_config() +{ + local section=$1 + tcert=$(parse_cnf $section ssl-ca "") + tpem=$(parse_cnf $section ssl-cert "") + tkey=$(parse_cnf $section ssl-key "") + if [ 0 -eq $encrypt -a -n "$tpem" -a -n "$tkey" ] + then + encrypt=3 # enable cert/key SSL encyption + + # avoid CA verification if not set explicitly: + # nodes may happen to have different CA if self-generated + # zeroing up tcert does the trick + local mode=$(parse_cnf SST ssl-mode "") + [[ ${tmode} = *VERIFY* ]] || tcert="" + fi +} + read_cnf() { sfmt=$(parse_cnf sst streamfmt "xbstream") @@ -359,6 +392,26 @@ read_cnf() tpem=$(parse_cnf sst tcert "") tkey=$(parse_cnf sst tkey "") encrypt=$(parse_cnf sst encrypt 0) + tmode=$(parse_cnf sst ssl-mode "DISABLED" | tr [:lower:] [:upper:]) + + if [ -z "$tpem" -a -z "$tkey" -a -z "$tcert" ] + then # no old-style SSL config in [sst] + if [ "$tmode" != "DISABLED" ] + then # backward-incompatible behavior + check_server_ssl_config "sst" + if [ -z "$tpem" -a -z "$tkey" -a -z "$tcert" ] + then # no new-stype SSL config in [sst], try server-wide SSL config + check_server_ssl_config "mysqld.$WSREP_SST_OPT_SUFFIX_VALUE" + if [ -z "$tpem" -a -z "$tkey" -a -z "$tcert" ] + then + check_server_ssl_config "mysqld" + fi + fi + fi + fi + wsrep_log_info "SSL configuration: CA='"$tcert"', CERT='"$tpem"'," \ + "KEY='"$tkey"', MODE='"$tmode"', encrypt="$encrypt + sockopt=$(parse_cnf sst sockopt "") progress=$(parse_cnf sst progress "") rebuild=$(parse_cnf sst rebuild 0) @@ -404,7 +457,7 @@ read_cnf() if [[ $encrypt -eq 1 ]]; then wsrep_log_error "Xtrabackup-based encryption is currently not" \ - "supported with MariaBackup" + "supported with MariaBackup" exit 2 fi } @@ -631,8 +684,8 @@ recv_joiner() popd 1>/dev/null if [[ ${RC[0]} -eq 124 ]];then - wsrep_log_error "Possible timeout in receiving first data from " - "donor in gtid stage: exit codes: ${RC[@]}" + wsrep_log_error "Possible timeout in receiving first data from " \ + "donor in gtid stage: exit codes: ${RC[@]}" exit 32 fi @@ -644,12 +697,27 @@ recv_joiner() fi done - if [[ $checkf -eq 1 && ! -r "${MAGIC_FILE}" ]];then - # this message should cause joiner to abort - wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" - wsrep_log_info "Contents of datadir" - wsrep_log_info "$(ls -l ${dir}/*)" - exit 32 + if [[ $checkf -eq 1 ]]; then + if [[ ! -r "${MAGIC_FILE}" ]];then + # this message should cause joiner to abort + wsrep_log_error "receiving process ended without creating " \ + "'${MAGIC_FILE}'" + wsrep_log_info "Contents of datadir" + wsrep_log_info "$(ls -l ${dir}/*)" + exit 32 + fi + + # check donor supplied secret + SECRET=$(grep "$SECRET_TAG " ${MAGIC_FILE} 2>/dev/null | cut -d ' ' -f 2) + if [[ $SECRET != $MY_SECRET ]]; then + wsrep_log_error "Donor does not know my secret!" + wsrep_log_info "Donor:'$SECRET', my:'$MY_SECRET'" + exit 32 + fi + + # remove secret from magic file + grep -v "$SECRET_TAG " ${MAGIC_FILE} > ${MAGIC_FILE}.new + mv ${MAGIC_FILE}.new ${MAGIC_FILE} fi } @@ -665,10 +733,9 @@ send_donor() set -e popd 1>/dev/null - for ecode in "${RC[@]}";do if [[ $ecode -ne 0 ]];then - wsrep_log_error "Error while getting data from donor node: " \ + wsrep_log_error "Error while sending data to joiner node: " \ "exit codes: ${RC[@]}" exit 32 fi @@ -891,6 +958,11 @@ then # (separated by a space). echo "${WSREP_SST_OPT_GTID} ${WSREP_SST_OPT_GTID_DOMAIN_ID}" > "${MAGIC_FILE}" + if [[ -n ${WSREP_SST_OPT_REMOTE_PSWD} ]]; then + # Let joiner know that we know its secret + echo "$SECRET_TAG ${WSREP_SST_OPT_REMOTE_PSWD}" >> ${MAGIC_FILE} + fi + ttcmd="$tcmd" if [[ $encrypt -eq 1 ]];then @@ -1003,7 +1075,6 @@ then stagemsg="Joiner-Recv" - sencrypted=1 nthreads=1 @@ -1025,7 +1096,26 @@ then fi fi - wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} & + if [[ "$tmode" = *"VERIFY"* ]] + then # backward-incompatible behavior + if [ -n "$tpem" ] + then + # find out my Common Name + wsrep_check_programs openssl + CN=$(openssl x509 -noout -subject -in $tpem | \ + tr "," "\n" | grep "CN =" | cut -d= -f2 | sed s/^\ // | \ + sed s/\ %//) + else + CN="" + fi + MY_SECRET=$(wsrep_gen_secret) + # Add authentication data to address + ADDR="$CN:$MY_SECRET@$ADDR" + else + MY_SECRET="" # for check down in recv_joiner() + fi # tmode == *VERIFY* + + wait_for_listen ${SST_PORT} "${ADDR}" ${MODULE} & trap sig_joiner_cleanup HUP PIPE INT TERM trap cleanup_joiner EXIT |