fix(test): set use_ssl=1 on passthrough target HGs for mysql84-g* TAP groups

The six new Phase-1 pass-through auth TAP tests registered under the
mysql84-g4 (and mysql90-g4 / mysql95-g4) groups were failing in CI with
errno != 0 on every "success" path (first connect, cache hit, re-probe,
post-invalidation reconnect, etc.).

Root cause
----------
The pass-through backend probe lives in:

    MySQL_Session::handler_again___status_AUTHENTICATING_BACKEND_FOR_CLIENT

Right before the actual probe it does:

    MySrvC *mysrvc = myhgc->get_random_MySrvC(...);
    ...
    if (mysrvc->use_ssl && mysrvc->port) {
        probe_ssl_params = MyHGM->get_Server_SSL_Params(...);
        MySQL_Connection::set_ssl_params(probe, probe_ssl_params);
        ...
    }
    MYSQL *result = mysql_real_connect(probe, mysrvc->address, ...);

If MySrvC->use_ssl is false, the probe is a plaintext TCP connection.

The dbdeployer-based mysql84+ (and mysql90+/mysql95+) infras used by the
mysql84-g* groups (via TAP_MYSQL8_BACKEND_HG, defaulting to WHG=2900 etc.
from test/infra/infra-dbdeployer-mysql84/.env) seed mysql_servers rows
without use_ssl=1:

    test/infra/infra-dbdeployer-mysql84/bin/docker-proxy-post.bash
    test/infra/infra-dbdeployer-mysql84/conf/proxysql/infra-config.sql

As a result, every passthrough probe was plaintext. MySQL 8.4+ backends
(and the caching_sha2_password full-auth exchange the probe depends on)
typically reject or fail such connections, so all "success" scenarios in
the tests saw errno != 0 (commonly 1045) instead of 0.

This only affected the mysql84-g* groups (the ones actually running the
new passthrough tests). All other TAP groups, builds, unit tests, etc.
were green.

Fix
---
Right after each test's "pass-through configured" block (variables +
LOAD MYSQL VARIABLES TO RUNTIME) and before the first probe, we now do:

    UPDATE mysql_servers
       SET use_ssl=1
     WHERE hostgroup_id = <MYSQL8_HG>;
    LOAD MYSQL SERVERS TO RUNTIME;

This is applied in all six affected tests:

    test_passthrough_auth_e2e-t.cpp
    test_passthrough_auth_ratelimit-t.cpp
    test_passthrough_auth_security-t.cpp
    test_passthrough_auth_unknown_user-t.cpp
    test_passthrough_auth_invalidation-t.cpp
    test_passthrough_auth_metrics-t.cpp

The change only affects the probe->backend leg. The frontend TLS
requirement (spec §7.1) continues to be enforced by CLIENT_SSL +
mysql_ssl_set() in the tests' try_connect() helpers.

Documentation
-------------
- Each site has a detailed inline comment explaining:
  * the probe code path and the MySrvC->use_ssl gate
  * where the infra seeds the servers (WHG, docker-proxy-post.bash, etc.)
  * why plaintext probes fail on mysql84+ backends
  * why this has to be done before the first probe in that test
  * that it only affects the backend leg (frontend TLS is separate)

- This commit message is intentionally long and self-contained so that
  future readers (and the agents that will be asked to "explain why
  mysql84-g4 was red") do not have to reconstruct the context from
  partial logs and cross-PR archaeology.

No changes to core logic, only test fixtures to match documented
behavior and the reality of the test infrastructure.

This makes the mysql84-g* passthrough tests (and therefore the
mysql84-g4 CI job) pass again.
docs/passthrough-auth-spec
René Cannaò 3 days ago
parent dc74d241c6
commit ac3c68aa21

@ -296,6 +296,46 @@ int main() {
}
ok(cfg_ok, "Pass-through enabled, TLS gate on (client connects with CLIENT_SSL), default_auth=caching_sha2_password");
/*
* Ensure the target hostgroup's servers are marked use_ssl=1 so the
* passthrough backend probe (mysql_real_connect inside
* handler_again___status_AUTHENTICATING_BACKEND_FOR_CLIENT) will
* establish a TLS connection to the backend.
*
* The probe path is:
* handler_again___status_AUTHENTICATING_BACKEND_FOR_CLIENT
* ...
* if (mysrvc->use_ssl && mysrvc->port) {
* probe_ssl_params = MyHGM->get_Server_SSL_Params(...);
* MySQL_Connection::set_ssl_params(probe, probe_ssl_params);
* ...
* }
* MYSQL *result = mysql_real_connect(probe, mysrvc->address, ...);
*
* If MySrvC->use_ssl is false, the probe is plaintext. The mysql84+
* (and mysql90+/mysql95+) dbdeployer infras used by the mysql84-g4
* group (see test/infra/infra-dbdeployer-mysql84/.env exporting
* TAP_MYSQL8_BACKEND_HG=${WHG}, and the post hook in
* test/infra/infra-dbdeployer-mysql84/bin/docker-proxy-post.bash)
* seed mysql_servers rows without use_ssl=1.
*
* Without this UPDATE+LOAD, every probe in this test is plaintext.
* MySQL 8.4+ backends commonly reject plaintext connections or the
* caching_sha2_password full-auth exchange fails, so all success
* scenarios (first connect, reconnect, re-probe after flush) see
* errno != 0 instead of 0, and the TAP plan fails.
*
* We do the UPDATE+LOAD right after the test's passthrough
* configuration block and before the first try_connect, so it is
* live for the entire test. This only affects the probe->backend
* leg; the frontend TLS requirement (spec §7.1) is enforced by
* CLIENT_SSL + mysql_ssl_set in try_connect().
*/
do_query(admin,
string("UPDATE mysql_servers SET use_ssl=1 WHERE hostgroup_id=")
+ std::to_string(MYSQL8_HG));
do_query(admin, "LOAD MYSQL SERVERS TO RUNTIME");
/* -------- verify gate state -------- */
{
const int set_ok = mysql_query(admin,

@ -219,6 +219,36 @@ int main() {
cfg_ok &= (do_query(admin, "LOAD MYSQL VARIABLES TO RUNTIME") == EXIT_SUCCESS);
ok(cfg_ok, "Pass-through configured (failure caps raised for test isolation)");
/*
* Ensure the target hostgroup has use_ssl=1 so the passthrough probe
* negotiates TLS to the backend.
*
* The pass-through probe path (handler_again___status_AUTHENTICATING_BACKEND_FOR_CLIENT)
* only enables TLS for the backend leg if the selected MySrvC has use_ssl set:
*
* if (mysrvc->use_ssl && mysrvc->port) {
* probe_ssl_params = MyHGM->get_Server_SSL_Params(...);
* MySQL_Connection::set_ssl_params(probe, probe_ssl_params);
* }
* MYSQL *result = mysql_real_connect(probe, ...);
*
* The dbdeployer-mysql84 (and mysql90/mysql95) infras used by the
* mysql84-g4 group (via TAP_MYSQL8_BACKEND_HG) seed mysql_servers rows
* without use_ssl=1. Without this UPDATE+LOAD, every probe is plaintext.
* MySQL 8.4+ backends (and the caching_sha2_password full-auth exchange
* that the probe relies on) typically fail or reject in that case, so
* "success" scenarios see errno != 0 and the TAP assertions fail.
*
* We do this once, right after the test's passthrough configuration
* block and before the first connect_and_query / try_connect, so the
* setting is live for all probes in the test (including the post-ALTER
* re-probe in the invalidation scenario).
*/
do_query(admin,
string("UPDATE mysql_servers SET use_ssl=1 WHERE hostgroup_id=")
+ std::to_string(MYSQL8_HG));
do_query(admin, "LOAD MYSQL SERVERS TO RUNTIME");
/* ============================================================
* Step 1 -- first connect probes & caches OLD password.
* ============================================================ */

@ -177,6 +177,35 @@ int main() {
cfg_ok &= (do_query(admin, "LOAD MYSQL VARIABLES TO RUNTIME") == EXIT_SUCCESS);
ok(cfg_ok, "Pass-through configured with tight lockout bypassed (caps set high)");
/*
* Ensure the target hostgroup has use_ssl=1 so the passthrough probe
* negotiates TLS to the backend.
*
* The pass-through probe path (handler_again___status_AUTHENTICATING_BACKEND_FOR_CLIENT)
* only enables TLS for the backend leg if the selected MySrvC has use_ssl set:
*
* if (mysrvc->use_ssl && mysrvc->port) {
* probe_ssl_params = MyHGM->get_Server_SSL_Params(...);
* MySQL_Connection::set_ssl_params(probe, probe_ssl_params);
* }
* MYSQL *result = mysql_real_connect(probe, ...);
*
* The dbdeployer-mysql84 (and mysql90/mysql95) infras used by the
* mysql84-g4 group (via TAP_MYSQL8_BACKEND_HG) seed mysql_servers rows
* without use_ssl=1. Without this UPDATE+LOAD, every probe is plaintext.
* MySQL 8.4+ backends (and the caching_sha2_password full-auth exchange
* that the probe relies on) typically fail or reject in that case, so
* "success" scenarios see errno != 0 and the TAP assertions fail.
*
* We do this once, right after the test's passthrough configuration
* block and before the first probe, so the setting is live for the
* entire test (including the observability counter scenarios).
*/
do_query(admin,
string("UPDATE mysql_servers SET use_ssl=1 WHERE hostgroup_id=")
+ std::to_string(MYSQL8_HG));
do_query(admin, "LOAD MYSQL SERVERS TO RUNTIME");
/* ============================================================
* Scenario 1: successful probe bumps probes_attempted and
* probes_ok.

@ -190,6 +190,48 @@ int main() {
ok(cfg_ok, "Pass-through configured (per-user cap=%d, window=%ds)",
TEST_MAX_FAILURES_PER_USER, TEST_FAILURE_WINDOW_S);
/*
* Ensure the target hostgroup's servers have use_ssl=1 so the
* passthrough probe (backend leg) negotiates TLS.
*
* The pass-through probe path lives in:
* MySQL_Session::handler_again___status_AUTHENTICATING_BACKEND_FOR_CLIENT
*
* Right before the actual backend connect it does:
*
* MySrvC *mysrvc = myhgc->get_random_MySrvC(...);
* ...
* if (mysrvc->use_ssl && mysrvc->port) {
* probe_ssl_params = MyHGM->get_Server_SSL_Params(...);
* MySQL_Connection::set_ssl_params(probe, probe_ssl_params);
* ...
* }
* MYSQL *result = mysql_real_connect(probe, mysrvc->address, ...);
*
* If MySrvC->use_ssl is false, the probe is a plaintext TCP connection.
* On the mysql84+ dbdeployer infras used by the mysql84-g4 group
* (WHG comes from TAP_MYSQL8_BACKEND_HG, default 2900 in
* test/infra/infra-dbdeployer-mysql84/.env), the servers are seeded
* by docker-proxy-post.bash + infra-config.sql without use_ssl=1.
*
* Without this UPDATE+LOAD, every passthrough probe is plaintext.
* MySQL 8.4+ backends (and the caching_sha2_password full-auth
* exchange the probe depends on) typically reject or fail the
* handshake, so all "success" scenarios in this test (baseline,
* Phase C after window expiry) return errno != 0 (usually 1045)
* instead of 0, and the TAP assertions fail.
*
* We apply this right after the test's passthrough configuration
* block (variables + LOAD VARIABLES) and before the first
* try_connect, so it is live for the baseline and all subsequent
* probes. This only affects the probe->backend leg; the frontend
* TLS requirement is handled separately by CLIENT_SSL in try_connect.
*/
do_query(admin,
string("UPDATE mysql_servers SET use_ssl=1 WHERE hostgroup_id=")
+ std::to_string(MYSQL8_HG));
do_query(admin, "LOAD MYSQL SERVERS TO RUNTIME");
/* -------- baseline: a correct connect succeeds before priming -------- */
{
const unsigned int err = try_connect(cl, TEST_USER, TEST_BACKEND_PW);

@ -225,6 +225,28 @@ int main() {
}
ok(cfg_ok, "Base passthrough configuration applied");
/*
* Ensure the target hostgroup has use_ssl=1 so the passthrough probe
* (backend leg) negotiates TLS.
*
* See the long-form comment in test_passthrough_auth_e2e-t.cpp for the
* full rationale. In short:
*
* handler_again___status_AUTHENTICATING_BACKEND_FOR_CLIENT only
* does TLS for the probe if MySrvC->use_ssl is set. The dbdeployer
* mysql84+ infras used by mysql84-g4 seed servers with use_ssl=0,
* so without this UPDATE+LOAD every probe is plaintext and the
* positive-path scenarios (matching username_pattern, TLS-positive,
* etc.) would all fail.
*
* We apply this right after the base passthrough configuration block
* and before any of the gate-specific scenarios.
*/
do_query(admin,
string("UPDATE mysql_servers SET use_ssl=1 WHERE hostgroup_id=")
+ std::to_string(MYSQL8_HG));
do_query(admin, "LOAD MYSQL SERVERS TO RUNTIME");
/* ============================================================
* TLS gate: with require_tls=true, the gate must reject a non-TLS
* client AND accept a TLS one. The differential is what proves the

@ -303,6 +303,25 @@ int main() {
}
ok(cfg_ok, "unknown_users=true, default_hg=%u, TLS gate off", MYSQL8_HG);
/*
* Ensure the target hostgroup (passthrough_default_hg) has use_ssl=1
* so the passthrough probe negotiates TLS to the backend.
*
* Same root cause as the other mysql84-g4 passthrough tests:
* the probe path only does TLS if MySrvC->use_ssl is true. The
* dbdeployer mysql84+ infras used by this group do not set it by
* default. Without this, the "first connect for unknown user" and
* the cache-hit SELECT 1 scenarios would see probe failures instead
* of success.
*
* We apply this right after setting passthrough_default_hg and
* before the first probe.
*/
do_query(admin,
string("UPDATE mysql_servers SET use_ssl=1 WHERE hostgroup_id=")
+ std::to_string(MYSQL8_HG));
do_query(admin, "LOAD MYSQL SERVERS TO RUNTIME");
/* Confirm the routing default we just set is what we expect to see in
* stats_mysql_passthrough_auth_cache.hostgroup_probed below. */
{

Loading…
Cancel
Save