Skip to content

Commit db0a211

Browse files
authored
Merge pull request #5991 from sysown/fix/5363-monitor-caching-sha2
fix(auth): allow mysql-monitor_* to authenticate under caching_sha2_password
2 parents 3849dec + d768c6e commit db0a211

5 files changed

Lines changed: 167 additions & 105 deletions

lib/MySQL_Protocol.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1709,7 +1709,7 @@ int MySQL_Protocol::PPHR_1(unsigned char *pkt, unsigned int len, bool& ret, MyPr
17091709
if ((*myds)->switching_auth_stage == 5 && *pkt == 2) {
17101710
proxy_debug(PROXY_DEBUG_MYSQL_AUTH, 5,
17111711
"Session=%p , DS=%p , user='%s' . Client requested the caching_sha2_password RSA public key\n",
1712-
(*myds), (*myds)->sess, vars1.user);
1712+
(*myds)->sess, (*myds), vars1.user);
17131713
proxy_error(
17141714
"User '%s'@'%s' requested the caching_sha2_password RSA public key, which ProxySQL does not"
17151715
" serve. Connect using TLS instead.\n",

test/repro/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ needs debug-only admin commands.
3636

3737
## COLD_START
3838

39-
```
39+
```text
4040
COLD_START=0 (default) use the existing ProxySQL instance
4141
COLD_START=1 destroy and recreate it first
4242
```

test/repro/reg_test_5363_admin_monitor_caching_sha2.bash

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -66,36 +66,45 @@ set -uo pipefail
6666
WORKSPACE="${WORKSPACE:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
6767
INFRA_ID="${INFRA_ID:-dev-$USER}"
6868
TAP_GROUP="${TAP_GROUP:-no-infra-g1}"
69-
COLD_START="${COLD_START:-0}"
69+
COLD_START="-e"
70+
export WORKSPACE INFRA_ID TAP_GROUP
7071

7172
CTR="proxysql.${INFRA_ID}"
7273
DATADIR="${WORKSPACE}/ci_infra_logs/${INFRA_ID}/proxysql"
7374
MON_USER='monitor'
7475
MON_PASS='monitorpass'
75-
BASE_CREDS='admin:admin;radmin:radmin;cluster1:secret1pass'
76+
LOAD_MYSQL_VARS='LOAD MYSQL VARIABLES TO RUNTIME;'
7677

7778
PASS=0; FAIL=0; BUGS=0
78-
ok() { PASS=$((PASS+1)); printf ' ok %d - %s\n' "$((PASS+FAIL))" "$1"; }
79-
nok() { FAIL=$((FAIL+1)); printf ' NOT OK %d - %s\n' "$((PASS+FAIL))" "$1"; }
80-
bug() { FAIL=$((FAIL+1)); BUGS=$((BUGS+1)); printf ' NOT OK %d - [BUG #5363] %s\n' "$((PASS+FAIL))" "$1"; }
81-
hdr() { printf '\n== %s ==\n' "$1"; }
82-
die() { printf '\nFATAL: %s\n' "$1" >&2; exit 2; }
79+
ok() { local msg="$1"; PASS=$((PASS+1)); printf ' ok %d - %s\n' "$((PASS+FAIL))" "$msg"; return 0; }
80+
nok() { local msg="$1"; FAIL=$((FAIL+1)); printf ' NOT OK %d - %s\n' "$((PASS+FAIL))" "$msg"; return 0; }
81+
bug() { local msg="$1"; FAIL=$((FAIL+1)); BUGS=$((BUGS+1)); printf ' NOT OK %d - [BUG #5363] %s\n' "$((PASS+FAIL))" "$msg"; return 0; }
82+
hdr() { local msg="$1"; printf '\n== %s ==\n' "$msg"; return 0; }
83+
die() { local msg="$1"; printf '\nFATAL: %s\n' "$msg" >&2; exit 2; }
8384

8485
IP=''
85-
adm() { mysql -h"$IP" -P6032 -uradmin -pradmin --protocol=TCP -NBe "$1" 2>/dev/null; }
86+
adm() {
87+
local sql="$1"
88+
mysql -h"$IP" -P6032 -uradmin -pradmin --protocol=TCP -NBe "$sql" 2>/dev/null
89+
return $?
90+
}
8691
setvar() { # setvar <variable_name> <value> <LOAD statement>
87-
adm "UPDATE global_variables SET variable_value='$2' WHERE variable_name='$1'; $3" >/dev/null
92+
local name="$1" value="$2" load_stmt="$3"
93+
adm "UPDATE global_variables SET variable_value='$value' WHERE variable_name='$name'; $load_stmt" >/dev/null
94+
return $?
8895
}
8996
# login_local <user> <pass> <ssl-mode> -- runs the client INSIDE the container
9097
login_local() {
91-
docker exec "$CTR" mysql -h127.0.0.1 -P6032 -u"$1" -p"$2" \
92-
--protocol=TCP --ssl-mode="$3" -NBe "SELECT 1;" >/dev/null 2>&1
98+
local user="$1" pass="$2" ssl_mode="$3"
99+
docker exec "$CTR" mysql -h127.0.0.1 -P6032 -u"$user" -p"$pass" \
100+
--protocol=TCP --ssl-mode="$ssl_mode" -NBe "SELECT 1;" >/dev/null 2>&1
101+
return $?
93102
}
94103

95104
# ------------------------------------------------------------- preflight ---
96105
command -v docker >/dev/null || die "docker not found"
97106
command -v mysql >/dev/null || die "mysql client not found"
98-
[ -x "${WORKSPACE}/src/proxysql" ] || die "no binary at ${WORKSPACE}/src/proxysql -- build it first"
107+
[[ -x "${WORKSPACE}/src/proxysql" ]] || die "no binary at ${WORKSPACE}/src/proxysql -- build it first"
99108
"${WORKSPACE}/src/proxysql" --version 2>&1 | grep -q '_DEBUG' \
100109
|| die "${WORKSPACE}/src/proxysql is not a DEBUG build"
101110

@@ -104,24 +113,21 @@ command -v mysql >/dev/null || die "mysql client not found"
104113
# PPHR_5passwordFalse_0(), which never calls set_clear_text_password(), so the
105114
# caching_sha2 cleartext cache plays no part in the result. COLD_START is offered
106115
# only for symmetry with the #5985 companion and for a guaranteed-clean run.
107-
if [ "$COLD_START" = "1" ]; then
116+
if [[ "$COLD_START" = "1" ]]; then
108117
hdr "Cold start: destroying and recreating ProxySQL for INFRA_ID=${INFRA_ID}"
109-
WORKSPACE="$WORKSPACE" INFRA_ID="$INFRA_ID" TAP_GROUP="$TAP_GROUP" \
110-
"${WORKSPACE}/test/infra/control/stop-proxysql-isolated.bash" >/dev/null 2>&1
118+
"${WORKSPACE}/test/infra/control/stop-proxysql-isolated.bash" >/dev/null 2>&1
111119
rm -f "${DATADIR}"/proxysql.db "${DATADIR}"/proxysql_debug.db \
112120
"${DATADIR}"/proxysql_stats.db "${DATADIR}"/sqlite3server.db 2>/dev/null
113-
WORKSPACE="$WORKSPACE" INFRA_ID="$INFRA_ID" TAP_GROUP="$TAP_GROUP" \
114-
"${WORKSPACE}/test/infra/control/start-proxysql-isolated.bash" >/dev/null 2>&1 \
121+
"${WORKSPACE}/test/infra/control/start-proxysql-isolated.bash" >/dev/null 2>&1 \
115122
|| die "start-proxysql-isolated.bash failed"
116123
else
117124
hdr "Using the existing ProxySQL instance (set COLD_START=1 to recreate it)"
118-
WORKSPACE="$WORKSPACE" INFRA_ID="$INFRA_ID" TAP_GROUP="$TAP_GROUP" \
119-
"${WORKSPACE}/test/infra/control/ensure-infras.bash" >/dev/null 2>&1 \
125+
"${WORKSPACE}/test/infra/control/ensure-infras.bash" >/dev/null 2>&1 \
120126
|| die "ensure-infras.bash failed"
121127
fi
122128

123129
IP="$(docker inspect "$CTR" --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 2>/dev/null)"
124-
[ -n "$IP" ] || die "could not determine IP of ${CTR}"
130+
[[ -n "$IP" ]] || die "could not determine IP of ${CTR}"
125131
docker exec "$CTR" which mysql >/dev/null 2>&1 || die "no mysql client inside ${CTR}"
126132

127133
# Guard against testing a STALE binary. The container bind-mounts
@@ -134,7 +140,7 @@ docker exec "$CTR" which mysql >/dev/null 2>&1 || die "no mysql client inside ${
134140
BIN_MTIME="$(stat -c %Y "${WORKSPACE}/src/proxysql" 2>/dev/null || echo 0)"
135141
CTR_STARTED="$(docker inspect -f '{{.State.StartedAt}}' "$CTR" 2>/dev/null)"
136142
CTR_EPOCH="$(date -d "$CTR_STARTED" +%s 2>/dev/null || echo 0)"
137-
if [ "$BIN_MTIME" -gt "$CTR_EPOCH" ] 2>/dev/null; then
143+
if [[ "$BIN_MTIME" -gt "$CTR_EPOCH" ]] 2>/dev/null; then
138144
die "the running ProxySQL container predates ${WORKSPACE}/src/proxysql, so it is
139145
NOT running the binary you just built. Re-run with COLD_START=1, or refresh
140146
the container with:
@@ -143,32 +149,42 @@ if [ "$BIN_MTIME" -gt "$CTR_EPOCH" ] 2>/dev/null; then
143149
fi
144150
echo " ${CTR} at ${IP} -- $(adm 'SELECT @@admin-version;')"
145151

152+
# Capture the instance's ACTUAL pre-existing values so the EXIT handler can put
153+
# back exactly what was there. Restoring hardcoded defaults instead would
154+
# silently rewrite the configuration of a shared instance -- see the "Restore any
155+
# global state that was changed" rule in test/repro/README.md. Note this script
156+
# never modifies 'admin-admin_credentials', so it must not reset it either.
157+
ORIG_AUTH_PLUGIN="$(adm 'SELECT @@mysql-default_authentication_plugin;')"
158+
ORIG_MON_USER="$(adm 'SELECT @@mysql-monitor_username;')"
159+
ORIG_MON_PASS="$(adm 'SELECT @@mysql-monitor_password;')"
160+
146161
restore() {
147-
setvar 'admin-admin_credentials' "$BASE_CREDS" 'LOAD ADMIN VARIABLES TO RUNTIME;'
148-
setvar 'mysql-default_authentication_plugin' 'mysql_native_password' 'LOAD MYSQL VARIABLES TO RUNTIME;'
149-
setvar 'mysql-monitor_password' 'monitor' 'LOAD MYSQL VARIABLES TO RUNTIME;'
162+
setvar 'mysql-default_authentication_plugin' "$ORIG_AUTH_PLUGIN" "$LOAD_MYSQL_VARS"
163+
setvar 'mysql-monitor_username' "$ORIG_MON_USER" "$LOAD_MYSQL_VARS"
164+
setvar 'mysql-monitor_password' "$ORIG_MON_PASS" "$LOAD_MYSQL_VARS"
165+
return 0
150166
}
151167
trap restore EXIT
152168

153169
# ----------------------------------------------------------- preconditions ---
154170
hdr "Preconditions"
155-
[ "$(adm 'SELECT count(*) FROM runtime_mysql_users;')" = "0" ] \
171+
[[ "$(adm 'SELECT count(*) FROM runtime_mysql_users;')" = "0" ]] \
156172
&& ok "no mysql_users rows (nothing can shadow the monitor credential)" \
157173
|| nok "mysql_users is not empty -- result would be confounded"
158174
adm "SELECT @@admin-admin_credentials;" | grep -q "${MON_USER}:" \
159175
&& nok "an admin credential named '${MON_USER}' exists -- wrong code path" \
160176
|| ok "no admin credential named '${MON_USER}' (PPHR_5passwordFalse_0 is the path)"
161177

162-
setvar 'mysql-monitor_username' "$MON_USER" 'LOAD MYSQL VARIABLES TO RUNTIME;'
163-
setvar 'mysql-monitor_password' "$MON_PASS" 'LOAD MYSQL VARIABLES TO RUNTIME;'
164-
[ "$(adm 'SELECT @@mysql-monitor_username;')" = "$MON_USER" ] &&
165-
[ "$(adm 'SELECT @@mysql-monitor_password;')" = "$MON_PASS" ] \
178+
setvar 'mysql-monitor_username' "$MON_USER" "$LOAD_MYSQL_VARS"
179+
setvar 'mysql-monitor_password' "$MON_PASS" "$LOAD_MYSQL_VARS"
180+
[[ "$(adm 'SELECT @@mysql-monitor_username;')" = "$MON_USER" ]] &&
181+
[[ "$(adm 'SELECT @@mysql-monitor_password;')" = "$MON_PASS" ]] \
166182
&& ok "mysql-monitor_username/password set to ${MON_USER}/${MON_PASS} (cleartext, as documented)" \
167183
|| nok "failed to set mysql-monitor_* variables"
168184

169185
# ------------------------------------------------- baseline: native works ---
170186
hdr "Baseline: mysql_native_password"
171-
setvar 'mysql-default_authentication_plugin' 'mysql_native_password' 'LOAD MYSQL VARIABLES TO RUNTIME;'
187+
setvar 'mysql-default_authentication_plugin' 'mysql_native_password' "$LOAD_MYSQL_VARS"
172188
login_local "$MON_USER" "$MON_PASS" DISABLED \
173189
&& ok "${MON_USER} authenticates on :6032 over plaintext" \
174190
|| nok "${MON_USER} FAILED under native/plaintext -- baseline broken, investigate before trusting the rest"
@@ -178,8 +194,8 @@ login_local "$MON_USER" "$MON_PASS" REQUIRED \
178194

179195
# ------------------------------------------------------------- the bug ---
180196
hdr "caching_sha2_password"
181-
setvar 'mysql-default_authentication_plugin' 'caching_sha2_password' 'LOAD MYSQL VARIABLES TO RUNTIME;'
182-
[ "$(adm 'SELECT @@mysql-default_authentication_plugin;')" = "caching_sha2_password" ] \
197+
setvar 'mysql-default_authentication_plugin' 'caching_sha2_password' "$LOAD_MYSQL_VARS"
198+
[[ "$(adm 'SELECT @@mysql-default_authentication_plugin;')" = "caching_sha2_password" ]] \
183199
&& ok "mysql-default_authentication_plugin = caching_sha2_password" \
184200
|| nok "failed to switch the default authentication plugin"
185201

@@ -204,12 +220,12 @@ login_local "$MON_USER" "WRONGPASS" DISABLED \
204220
# --------------------------------------------------------------- summary ---
205221
hdr "Summary"
206222
printf ' passed: %d\n failed: %d (of which %d are the reported bug)\n' "$PASS" "$FAIL" "$BUGS"
207-
if [ "$FAIL" -eq 0 ]; then
223+
if [[ "$FAIL" -eq 0 ]]; then
208224
echo
209225
echo " All assertions pass: #5363 appears FIXED on this build."
210226
exit 0
211227
fi
212-
if [ "$FAIL" -eq "$BUGS" ]; then
228+
if [[ "$FAIL" -eq "$BUGS" ]]; then
213229
cat <<'EOS'
214230
215231
REPRODUCED. Every failure is a [BUG #5363] assertion:

0 commit comments

Comments
 (0)