Skip to content

Commit dfd330e

Browse files
author
Marek Młynarski
committed
WL#15973 Upgrade Checker should report users using deprecated authentication methods
This worklog is about adding checks to Upgrade Checker for deprecated authentication methods (sha256_password, mysql_native_password, mysql_native_password) checks report which users and system variables use those methods and presents them as warnings or error depending on target upgrade version. Change-Id: I6fb9b3814ac6ae0b0e22a6b0bee54c7b9b06f4aa Signed-off-by: Marek Młynarski <[email protected]>
1 parent f0d95af commit dfd330e

File tree

6 files changed

+903
-7
lines changed

6 files changed

+903
-7
lines changed

modules/util/upgrade_check.cc

Lines changed: 208 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,7 @@ std::vector<Upgrade_issue> Sql_upgrade_check::run(
263263
auto result = session->query(query);
264264
const mysqlshdk::db::IRow *row = nullptr;
265265
while ((row = result->fetch_one()) != nullptr) {
266-
Upgrade_issue issue = parse_row(row);
267-
if (!issue.empty()) issues.emplace_back(std::move(issue));
266+
add_issue(row, &issues);
268267
}
269268
}
270269

@@ -273,6 +272,12 @@ std::vector<Upgrade_issue> Sql_upgrade_check::run(
273272
return issues;
274273
}
275274

275+
void Sql_upgrade_check::add_issue(const mysqlshdk::db::IRow *row,
276+
std::vector<Upgrade_issue> *issues) {
277+
Upgrade_issue issue = parse_row(row);
278+
if (!issue.empty()) issues->emplace_back(std::move(issue));
279+
}
280+
276281
const char *Sql_upgrade_check::get_description_internal() const {
277282
if (m_advice.empty()) return nullptr;
278283
return m_advice.c_str();
@@ -1954,6 +1959,205 @@ bool UNUSED_VARIABLE(register_get_invalid_engine_foreign_key_check) =
19541959
Upgrade_check::Target::OBJECT_DEFINITIONS, "8.0.0");
19551960
}
19561961

1962+
namespace {
1963+
namespace deprecated_auth_funcs {
1964+
constexpr std::array<std::string_view, 3> k_auth_list = {
1965+
"sha256_password", "mysql_native_password", "authentication_fido"};
1966+
1967+
std::string get_auth_list() {
1968+
return shcore::str_join(k_auth_list, ", ", [](const auto &item) {
1969+
return shcore::sqlformat("?", item);
1970+
});
1971+
}
1972+
1973+
std::string get_auth_or_like_list(const std::string &value_name) {
1974+
return shcore::str_join(k_auth_list, " OR ", [&](const auto &item) {
1975+
return value_name + " LIKE '%" + std::string(item) + "%'";
1976+
});
1977+
}
1978+
1979+
bool is_auth_method(const std::string &auth) {
1980+
return std::find(k_auth_list.begin(), k_auth_list.end(), auth) !=
1981+
k_auth_list.end();
1982+
}
1983+
1984+
void setup_fido(const Version &target_version, Upgrade_issue *problem) {
1985+
if (target_version < Version(8, 0, 27)) {
1986+
problem->description =
1987+
"authentication_fido was introduced in 8.0.27 release and is not "
1988+
"supported in lower versions - this must be corrected.";
1989+
problem->level = Upgrade_issue::ERROR;
1990+
} else if (target_version < Version(8, 2, 0)) {
1991+
problem->description =
1992+
"authentication_fido is deprecated as of MySQL 8.2 and will be removed "
1993+
"in a future release. Consider using authentication_webauthn instead.";
1994+
problem->level = Upgrade_issue::NOTICE;
1995+
} else if (target_version < Version(8, 4, 0)) {
1996+
problem->description =
1997+
"authentication_fido is deprecated as of MySQL 8.2 and will be removed "
1998+
"in a future release. Use authentication_webauthn instead.";
1999+
problem->level = Upgrade_issue::WARNING;
2000+
} else {
2001+
problem->description =
2002+
"authentication_fido was replaced by authentication_webauthn as of "
2003+
"8.4.0 release - this must be corrected.";
2004+
problem->level = Upgrade_issue::ERROR;
2005+
}
2006+
}
2007+
2008+
void setup_other(const std::string &plugin, const Version &target_version,
2009+
Upgrade_issue *problem) {
2010+
if (target_version < Version(8, 4, 0)) {
2011+
problem->description =
2012+
plugin +
2013+
" authentication method is deprecated and it should be considered to "
2014+
"correct this before upgrading to 8.4.0 release.";
2015+
problem->level = Upgrade_issue::WARNING;
2016+
} else {
2017+
problem->description =
2018+
plugin +
2019+
" authentication method was removed and it must be corrected before "
2020+
"upgrading to 8.4.0 release.";
2021+
problem->level = Upgrade_issue::ERROR;
2022+
}
2023+
}
2024+
2025+
Upgrade_issue parse_fido(const std::string &item,
2026+
const Version &target_version) {
2027+
Upgrade_issue problem;
2028+
problem.schema = item;
2029+
2030+
setup_fido(target_version, &problem);
2031+
2032+
return problem;
2033+
}
2034+
2035+
Upgrade_issue parse_other(const std::string &item, const std::string &plugin,
2036+
const Version &target_version) {
2037+
Upgrade_issue problem;
2038+
problem.schema = item;
2039+
2040+
setup_other(plugin, target_version, &problem);
2041+
2042+
return problem;
2043+
}
2044+
2045+
Upgrade_issue parse_item(const std::string &item, const std::string &auth,
2046+
const Version &target_version) {
2047+
if (auth == "authentication_fido") {
2048+
return parse_fido(item, target_version);
2049+
} else {
2050+
return parse_other(item, auth, target_version);
2051+
}
2052+
}
2053+
} // namespace deprecated_auth_funcs
2054+
2055+
class Deprecated_auth_method_check : public Sql_upgrade_check {
2056+
public:
2057+
Deprecated_auth_method_check(mysqlshdk::utils::Version target_ver)
2058+
: Sql_upgrade_check(
2059+
"mysqlDeprecatedAuthMethodCheck",
2060+
"Check for deprecated or invalid user authentication methods.",
2061+
std::vector<std::string>{
2062+
"SELECT CONCAT(user, '@', host), plugin FROM "
2063+
"mysql.user WHERE plugin IN (" +
2064+
deprecated_auth_funcs::get_auth_list() + ");"},
2065+
Upgrade_issue::WARNING),
2066+
m_target_version(target_ver) {
2067+
m_advice =
2068+
"The following users are using a deprecated authentication method:\n";
2069+
}
2070+
2071+
~Deprecated_auth_method_check() = default;
2072+
2073+
bool is_multi_lvl_check() const override { return true; }
2074+
2075+
protected:
2076+
Upgrade_issue parse_row(const mysqlshdk::db::IRow *row) override {
2077+
auto item = row->get_as_string(0);
2078+
auto auth = row->get_as_string(1);
2079+
2080+
return deprecated_auth_funcs::parse_item(item, auth, m_target_version);
2081+
}
2082+
2083+
private:
2084+
const mysqlshdk::utils::Version m_target_version;
2085+
};
2086+
} // namespace
2087+
2088+
Deprecated_default_auth_check::Deprecated_default_auth_check(
2089+
mysqlshdk::utils::Version target_ver)
2090+
: Sql_upgrade_check(
2091+
"mysqlDeprecatedDefaultAuthCheck",
2092+
"Check for deprecated or invalid default authentication methods in "
2093+
"system variables.",
2094+
std::vector<std::string>{
2095+
"show variables where variable_name = "
2096+
"'default_authentication_plugin' AND value IN (" +
2097+
deprecated_auth_funcs::get_auth_list() + ");",
2098+
"show variables where variable_name = 'authentication_policy' "
2099+
"AND (" +
2100+
deprecated_auth_funcs::get_auth_or_like_list("value") + ");"},
2101+
Upgrade_issue::WARNING),
2102+
m_target_version(target_ver) {
2103+
m_advice =
2104+
"The following variables have problems with their set "
2105+
"authentication method:\n";
2106+
}
2107+
2108+
Deprecated_default_auth_check::~Deprecated_default_auth_check() = default;
2109+
2110+
void Deprecated_default_auth_check::add_issue(
2111+
const mysqlshdk::db::IRow *row, std::vector<Upgrade_issue> *issues) {
2112+
auto item = row->get_as_string(0);
2113+
auto auth = row->get_as_string(1);
2114+
2115+
parse_var(item, auth, issues);
2116+
}
2117+
2118+
void Deprecated_default_auth_check::parse_var(
2119+
const std::string &item, const std::string &auth,
2120+
std::vector<Upgrade_issue> *issues) {
2121+
auto list = shcore::split_string(auth, ",", true);
2122+
if (list.empty()) return;
2123+
2124+
for (auto &list_item : list) {
2125+
auto value = shcore::str_strip(list_item);
2126+
if (!deprecated_auth_funcs::is_auth_method(value)) continue;
2127+
2128+
auto issue =
2129+
deprecated_auth_funcs::parse_item(item, value, m_target_version);
2130+
if (!issue.empty()) issues->emplace_back(std::move(issue));
2131+
}
2132+
}
2133+
2134+
std::unique_ptr<Sql_upgrade_check>
2135+
Sql_upgrade_check::get_deprecated_auth_method_check(
2136+
const Upgrade_check::Upgrade_info &info) {
2137+
return std::make_unique<Deprecated_auth_method_check>(info.target_version);
2138+
}
2139+
2140+
namespace {
2141+
bool UNUSED_VARIABLE(register_get_deprecated_auth_method_check) =
2142+
Upgrade_check::register_check(
2143+
&Sql_upgrade_check::get_deprecated_auth_method_check,
2144+
Upgrade_check::Target::AUTHENTICATION_PLUGINS, "8.0.0", "8.1.0",
2145+
"8.2.0");
2146+
}
2147+
2148+
std::unique_ptr<Sql_upgrade_check>
2149+
Sql_upgrade_check::get_deprecated_default_auth_check(
2150+
const Upgrade_check::Upgrade_info &info) {
2151+
return std::make_unique<Deprecated_default_auth_check>(info.target_version);
2152+
}
2153+
2154+
namespace {
2155+
bool UNUSED_VARIABLE(register_get_deprecated_default_auth_check) =
2156+
Upgrade_check::register_check(
2157+
&Sql_upgrade_check::get_deprecated_default_auth_check,
2158+
Upgrade_check::Target::SYSTEM_VARIABLES, "8.0.0", "8.1.0", "8.2.0");
2159+
}
2160+
19572161
Upgrade_check_config::Upgrade_check_config(const Upgrade_check_options &options)
19582162
: m_output_format(options.output_format) {
19592163
m_upgrade_info.target_version = options.target_version;
@@ -2048,8 +2252,8 @@ bool check_for_upgrade(const Upgrade_check_config &config) {
20482252
}
20492253
};
20502254

2051-
// Workaround for 5.7 "No database selected/Corrupted" UPGRADE bug present up
2052-
// to 5.7.39
2255+
// Workaround for 5.7 "No database selected/Corrupted" UPGRADE bug present
2256+
// up to 5.7.39
20532257
config.session()->execute("USE mysql;");
20542258

20552259
for (const auto &check : checklist)

modules/util/upgrade_check.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ struct Upgrade_issue {
5959
std::string description;
6060
Level level = ERROR;
6161

62-
bool empty() const { return schema.empty(); }
62+
bool empty() const {
63+
return schema.empty() && table.empty() && column.empty() &&
64+
description.empty();
65+
}
6366
std::string get_db_object() const;
6467
};
6568

@@ -155,6 +158,7 @@ class Upgrade_check {
155158
virtual const char *get_doc_link() const;
156159
virtual Upgrade_issue::Level get_level() const = 0;
157160
virtual bool is_runnable() const { return true; }
161+
virtual bool is_multi_lvl_check() const { return false; }
158162

159163
virtual std::vector<Upgrade_issue> run(
160164
const std::shared_ptr<mysqlshdk::db::ISession> &session,
@@ -216,6 +220,10 @@ class Sql_upgrade_check : public Upgrade_check {
216220
static std::unique_ptr<Sql_upgrade_check> get_empty_dot_table_syntax_check();
217221
static std::unique_ptr<Sql_upgrade_check>
218222
get_invalid_engine_foreign_key_check();
223+
static std::unique_ptr<Sql_upgrade_check> get_deprecated_auth_method_check(
224+
const Upgrade_check::Upgrade_info &info);
225+
static std::unique_ptr<Sql_upgrade_check> get_deprecated_default_auth_check(
226+
const Upgrade_check::Upgrade_info &info);
219227

220228
Sql_upgrade_check(const char *name, const char *title,
221229
std::vector<std::string> &&queries,
@@ -235,6 +243,8 @@ class Sql_upgrade_check : public Upgrade_check {
235243

236244
protected:
237245
virtual Upgrade_issue parse_row(const mysqlshdk::db::IRow *row);
246+
virtual void add_issue(const mysqlshdk::db::IRow *row,
247+
std::vector<Upgrade_issue> *issues);
238248
const char *get_description_internal() const override;
239249
const char *get_title_internal() const override;
240250
Upgrade_issue::Level get_level() const override { return m_level; }
@@ -324,6 +334,24 @@ class Manual_check : public Upgrade_check {
324334
Upgrade_issue::Level m_level;
325335
};
326336

337+
class Deprecated_default_auth_check : public Sql_upgrade_check {
338+
public:
339+
Deprecated_default_auth_check(mysqlshdk::utils::Version target_ver);
340+
~Deprecated_default_auth_check();
341+
342+
void parse_var(const std::string &item, const std::string &auth,
343+
std::vector<Upgrade_issue> *issues);
344+
345+
bool is_multi_lvl_check() const override { return true; }
346+
347+
protected:
348+
void add_issue(const mysqlshdk::db::IRow *row,
349+
std::vector<Upgrade_issue> *issues) override;
350+
351+
private:
352+
const mysqlshdk::utils::Version m_target_version;
353+
};
354+
327355
class Upgrade_check_config final {
328356
public:
329357
using Include_issue = std::function<bool(const Upgrade_issue &)>;

modules/util/upgrade_check_formatter.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, Oracle and/or its affiliates.
2+
* Copyright (c) 2022, 2023, Oracle and/or its affiliates.
33
*
44
* This program is free software; you can redistribute it and/or modify
55
* it under the terms of the GNU General Public License, version 2.0,
@@ -55,6 +55,12 @@ std::string format_upgrade_issue(const Upgrade_issue &problem) {
5555
ss.str().c_str(), problem.description.c_str());
5656
}
5757

58+
std::string multi_lvl_format_issue(const Upgrade_issue &problem) {
59+
return shcore::str_format("%s: %s",
60+
Upgrade_issue::level_to_string(problem.level),
61+
upgrade_issue_to_string(problem).c_str());
62+
}
63+
5864
} // namespace
5965

6066
class Text_upgrade_checker_output : public Upgrade_check_output_formatter {
@@ -85,6 +91,8 @@ class Text_upgrade_checker_output : public Upgrade_check_output_formatter {
8591
print_paragraph(check.get_description());
8692
print_doc_links(check.get_doc_link());
8793
m_console->println();
94+
95+
if (check.is_multi_lvl_check()) issue_formater = multi_lvl_format_issue;
8896
} else {
8997
issue_formater = format_upgrade_issue;
9098
}

res/upgrade_checker/upgrade_checker.msg

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,3 +441,19 @@ https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html#mysql-nutshell-remov
441441

442442
* mysqlInvalidEngineForeignKeyCheck.docLink
443443

444+
* mysqlDeprecatedAuthMethodCheck.title
445+
# Check for deprecated or invalid user authentication methods.
446+
447+
* mysqlDeprecatedAuthMethodCheck.description
448+
# The following user have problems with their assigned authentication method:\n
449+
450+
* mysqlDeprecatedAuthMethodCheck.docLink
451+
452+
* mysqlDeprecatedDefaultAuthCheck.title
453+
# Check for deprecated or invalid default authentication methods in system variables.
454+
455+
* mysqlDeprecatedDefaultAuthCheck.description
456+
# The following variables have problems with their set authentication method:\n
457+
458+
* mysqlDeprecatedDefaultAuthCheck.docLink
459+

0 commit comments

Comments
 (0)