From 8bae0955e0bfb5fd3f27f7b40bec359b4f30fd30 Mon Sep 17 00:00:00 2001 From: Danyal-Faheem Date: Tue, 30 Jul 2024 17:04:46 +0500 Subject: [PATCH] fix: convert upgrade steps to do command --- tutor/commands/jobs.py | 23 +++++++++++++++++++++- tutor/utils.py | 43 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/tutor/commands/jobs.py b/tutor/commands/jobs.py index 7510a83b31..de240dd1df 100644 --- a/tutor/commands/jobs.py +++ b/tutor/commands/jobs.py @@ -14,7 +14,7 @@ from tutor import config as tutor_config from tutor import env, fmt, hooks from tutor.hooks import priorities - +from tutor.utils import get_mysql_change_authentication_plugin_query class DoGroup(click.Group): """ @@ -314,6 +314,26 @@ def sqlshell(args: list[str]) -> t.Iterable[tuple[str, str]]: command += " " + shlex.join(args) # pylint: disable=protected-access yield ("lms", command) +@click.command(context_settings={"ignore_unknown_options": True}) +def update_mysql_authentication_plugin( +) -> t.Iterable[tuple[str, str]]: + """ + Update the authentication plugin of MySQL users from mysql_native_password to caching_sha2_password + Handy command used when upgrading to v8.4 of MySQL which deprecates mysql_native_password + """ + + context = click.get_current_context().obj + config = tutor_config.load(context.root) + + query = get_mysql_change_authentication_plugin_query(config) + + mysql_command = ( + "mysql --user={{ MYSQL_ROOT_USERNAME }} --password={{ MYSQL_ROOT_PASSWORD }} --host={{ MYSQL_HOST }} --port={{ MYSQL_PORT }}" + + shlex.join([f"--database={{ OPENEDX_MYSQL_DATABASE }}", "-e", query]) + ) + + yield ("lms", mysql_command) + def add_job_commands(do_command_group: click.Group) -> None: """ @@ -397,5 +417,6 @@ def do_callback(service_commands: t.Iterable[tuple[str, str]]) -> None: print_edx_platform_setting, settheme, sqlshell, + update_mysql_authentication_plugin, ] ) diff --git a/tutor/utils.py b/tutor/utils.py index cdb082f38a..bc05e0adf6 100644 --- a/tutor/utils.py +++ b/tutor/utils.py @@ -19,7 +19,8 @@ from Crypto.PublicKey import RSA from Crypto.PublicKey.RSA import RsaKey -from . import exceptions, fmt +from . import exceptions, fmt, plugins +from tutor.types import Config, ConfigValue def encrypt(text: str) -> str: @@ -366,3 +367,43 @@ def format_table(rows: List[Tuple[str, ...]], separator: str = "\t") -> str: # Append EOL at all lines but the last one formatted += "\n" return formatted + + +def get_mysql_change_authentication_plugin_query(config: Config) -> str: + """ + Helper function to generate queries to upgrade the authentication plugin of MySQL users + By default, only the ROOT and OPENEDX users are upgraded + If any loaded plugins have database user configurations defined in the format: + _MYSQL_USERNAME + _MYSQL_PASSWORD + These users are also upgraded + """ + loaded_plugins = list(plugins.iter_loaded()) + + def generate_mysql_authentication_plugin_update_query( + username: ConfigValue, password: ConfigValue, host: str + ) -> str: + return f"ALTER USER '{username}'@'{host}' IDENTIFIED with caching_sha2_password BY '{password}';" + + host = "%" + query = "" + query += generate_mysql_authentication_plugin_update_query( + config["MYSQL_ROOT_USERNAME"], config["MYSQL_ROOT_PASSWORD"], host + ) + query += generate_mysql_authentication_plugin_update_query( + config["OPENEDX_MYSQL_USERNAME"], config["OPENEDX_MYSQL_PASSWORD"], host + ) + + for plugin in loaded_plugins: + plugin_uppercase = plugin.upper() + if ( + f"{plugin_uppercase}_MYSQL_USERNAME" in config + and f"{plugin_uppercase}_MYSQL_PASSWORD" in config + ): + query += generate_mysql_authentication_plugin_update_query( + config[f"{plugin_uppercase}_MYSQL_USERNAME"], + config[f"{plugin_uppercase}_MYSQL_PASSWORD"], + host, + ) + + return query