From deb0722d924bc78ad96eb8e4f5b059b30fea49e4 Mon Sep 17 00:00:00 2001 From: Rene Cannao Date: Thu, 13 Aug 2026 16:04:49 +0000 Subject: [PATCH] fix(mysql): require TLS for SPIFFE users (#5929) --- lib/MySQL_Authentication.cpp | 15 ++++- test/tap/tests/unit/auth_unit-t.cpp | 99 ++++++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 2 deletions(-) diff --git a/lib/MySQL_Authentication.cpp b/lib/MySQL_Authentication.cpp index 220487259a..58ae1ceb4d 100644 --- a/lib/MySQL_Authentication.cpp +++ b/lib/MySQL_Authentication.cpp @@ -178,6 +178,7 @@ bool MySQL_Authentication::add(char * username, char * password, enum cred_usern } #endif uint64_t hash1, hash2; + bool effective_use_ssl = use_ssl; SpookyHash myhash; myhash.Init(1,2); myhash.Update(username,strlen(username)); @@ -306,7 +307,19 @@ bool MySQL_Authentication::add(char * username, char * password, enum cred_usern // FIXME: if the password is a clear text password, automatically generate sha1_pass and clear_text_password } - ad->use_ssl=use_ssl; + if (ad->attributes && strlen(ad->attributes)) { + try { + nlohmann::json valid=nlohmann::json::parse(ad->attributes); + if (valid.find("spiffe_id") != valid.end()) { + effective_use_ssl = true; + } + } + catch(nlohmann::json::exception&) { + // Invalid attributes do not require TLS. + } + } + + ad->use_ssl=effective_use_ssl; ad->default_hostgroup=default_hostgroup; ad->schema_locked=schema_locked; ad->transaction_persistent=transaction_persistent; diff --git a/test/tap/tests/unit/auth_unit-t.cpp b/test/tap/tests/unit/auth_unit-t.cpp index 89ceef1ee3..6f3c058b6f 100644 --- a/test/tap/tests/unit/auth_unit-t.cpp +++ b/test/tap/tests/unit/auth_unit-t.cpp @@ -52,6 +52,15 @@ static bool mysql_add_frontend(MySQL_Authentication *auth, ); } +static bool mysql_add_frontend_with_attributes(MySQL_Authentication *auth, + const char *user, bool use_ssl, const char *attributes) +{ + return auth->add( + (char *)user, (char *)"pass", USERNAME_FRONTEND, + use_ssl, 0, (char *)"", false, false, false, + 100, (char *)attributes, (char *)""); +} + // ============================================================================ // Helper: add a MySQL backend user // ============================================================================ @@ -449,6 +458,90 @@ static void test_mysql_frontend_backend_separation() { free_account_details(be); } +static void test_mysql_spiffe_requires_ssl() { + GloMyAuth->reset(); + + mysql_add_frontend_with_attributes( + GloMyAuth, "spiffe-user", false, + R"({"spiffe_id":"spiffe://example.org/ns/default/sa/client"})"); + account_details_t account = GloMyAuth->lookup( + (char *)"spiffe-user", USERNAME_FRONTEND, { false, false, false }); + ok(account.use_ssl, "MySQL: SPIFFE user requires TLS"); + free_account_details(account); + + mysql_add_frontend_with_attributes( + GloMyAuth, "spiffe-user", false, + R"({"spiffe_id":"spiffe://example.org/ns/default/sa/client"})"); + account = GloMyAuth->lookup( + (char *)"spiffe-user", USERNAME_FRONTEND, { false, false, false }); + ok(account.use_ssl, "MySQL: SPIFFE user remains TLS-required on update"); + free_account_details(account); + + mysql_add_frontend_with_attributes( + GloMyAuth, "plain-user", false, R"({"role":"client"})"); + account = GloMyAuth->lookup( + (char *)"plain-user", USERNAME_FRONTEND, { false, false, false }); + ok(!account.use_ssl, "MySQL: non-SPIFFE user preserves explicit TLS setting"); + free_account_details(account); +} + +static void test_mysql_invalid_spiffe_attributes_do_not_require_ssl() { + GloMyAuth->reset(); + + mysql_add_frontend_with_attributes( + GloMyAuth, "invalid-spiffe-user", false, R"({"role":"client"})"); + mysql_add_frontend_with_attributes( + GloMyAuth, "invalid-spiffe-user", false, + R"({"spiffe_id":"spiffe://example.org/ns/default/sa/client","default-transaction_isolation":123})"); + account_details_t account = GloMyAuth->lookup( + (char *)"invalid-spiffe-user", USERNAME_FRONTEND, { false, false, true }); + ok(!account.use_ssl, "MySQL: invalid SPIFFE attributes preserve explicit TLS setting"); + ok(account.attributes != nullptr && account.attributes[0] == '\0', + "MySQL: invalid SPIFFE attributes are cleared"); + free_account_details(account); +} + +static void test_mysql_spiffe_attributes_case_variant_requires_ssl() { + GloMyAuth->reset(); + + mysql_add_frontend_with_attributes( + GloMyAuth, "case-variant-spiffe-user", false, + R"({"spiffe_id":"spiffe://example.org/ns/default/sa/client"})"); + mysql_add_frontend_with_attributes( + GloMyAuth, "case-variant-spiffe-user", false, + R"({"SPIFFE_ID":"spiffe://example.org/ns/default/sa/client"})"); + account_details_t account = GloMyAuth->lookup( + (char *)"case-variant-spiffe-user", USERNAME_FRONTEND, + { false, false, true }); + ok(account.use_ssl, "MySQL: retained SPIFFE attributes require TLS"); + ok(account.attributes != nullptr && + strcmp(account.attributes, + R"({"spiffe_id":"spiffe://example.org/ns/default/sa/client"})") == 0, + "MySQL: case-variant update retains recognized SPIFFE attributes"); + free_account_details(account); +} + +static void test_mysql_spiffe_changed_attributes_toggle_ssl() { + GloMyAuth->reset(); + + mysql_add_frontend_with_attributes( + GloMyAuth, "changed-spiffe-user", false, R"({"role":"client"})"); + mysql_add_frontend_with_attributes( + GloMyAuth, "changed-spiffe-user", false, + R"({"spiffe_id":"spiffe://example.org/ns/default/sa/client","role":"client"})"); + account_details_t account = GloMyAuth->lookup( + (char *)"changed-spiffe-user", USERNAME_FRONTEND, { false, false, false }); + ok(account.use_ssl, "MySQL: changed SPIFFE attributes require TLS"); + free_account_details(account); + + mysql_add_frontend_with_attributes( + GloMyAuth, "changed-spiffe-user", false, R"({"role":"updated"})"); + account = GloMyAuth->lookup( + (char *)"changed-spiffe-user", USERNAME_FRONTEND, { false, false, false }); + ok(!account.use_ssl, "MySQL: changed non-SPIFFE attributes clear TLS requirement"); + free_account_details(account); +} + // ============================================================================ // 8. PgSQL_Authentication: Core CRUD // ============================================================================ @@ -558,7 +651,7 @@ static void test_pgsql_inactive_pattern() { // ============================================================================ int main() { - plan(60); + plan(69); test_init_minimal(); test_init_auth(); @@ -577,6 +670,10 @@ int main() { test_mysql_checksums(); // 4 tests test_mysql_memory(); // 3 tests test_mysql_frontend_backend_separation();// 4 tests + test_mysql_spiffe_requires_ssl(); // 3 tests + test_mysql_invalid_spiffe_attributes_do_not_require_ssl(); // 2 tests + test_mysql_spiffe_attributes_case_variant_requires_ssl(); // 2 tests + test_mysql_spiffe_changed_attributes_toggle_ssl(); // 2 tests // PgSQL tests test_pgsql_add_exists_lookup(); // 5 tests