From 0ce1fa1634eab1152c7bb442ca7ee82935081e05 Mon Sep 17 00:00:00 2001 From: "R.Sicart" Date: Thu, 23 Sep 2021 11:53:37 +0200 Subject: [PATCH] mysql_user: replace VALID_PRIVS by get_valid_privs() function (#217) * mysql_user: replace VALID_PRIVS by get_valid_privs() function * Add EXTRA_PRIVS in case we need to add more privs in the future * Add changelog fragment --- ...-get-valid-privs-from-show-privilegees.yml | 2 + plugins/module_utils/user.py | 49 +++++-------------- plugins/modules/mysql_role.py | 4 +- plugins/modules/mysql_user.py | 4 +- 4 files changed, 19 insertions(+), 40 deletions(-) create mode 100644 changelogs/fragments/217-mysql-user-replace-get-valid-privs-from-show-privilegees.yml diff --git a/changelogs/fragments/217-mysql-user-replace-get-valid-privs-from-show-privilegees.yml b/changelogs/fragments/217-mysql-user-replace-get-valid-privs-from-show-privilegees.yml new file mode 100644 index 00000000..60cd451b --- /dev/null +++ b/changelogs/fragments/217-mysql-user-replace-get-valid-privs-from-show-privilegees.yml @@ -0,0 +1,2 @@ +minor_changes: + - mysql_user - replace VALID_PRIVS constant by get_valid_privs() function (https://github.com/ansible-collections/community.mysql/pull/217). diff --git a/plugins/module_utils/user.py b/plugins/module_utils/user.py index c475c19d..2ba60f27 100644 --- a/plugins/module_utils/user.py +++ b/plugins/module_utils/user.py @@ -19,41 +19,7 @@ ) -VALID_PRIVS = frozenset(('CREATE', 'DROP', 'GRANT', 'GRANT OPTION', - 'LOCK TABLES', 'REFERENCES', 'EVENT', 'ALTER', - 'DELETE', 'INDEX', 'INSERT', 'SELECT', 'UPDATE', - 'CREATE TEMPORARY TABLES', 'TRIGGER', 'CREATE VIEW', - 'SHOW VIEW', 'ALTER ROUTINE', 'CREATE ROUTINE', - 'EXECUTE', 'FILE', 'CREATE TABLESPACE', 'CREATE USER', - 'PROCESS', 'PROXY', 'RELOAD', 'REPLICATION CLIENT', - 'REPLICATION SLAVE', 'SHOW DATABASES', 'SHUTDOWN', - 'SUPER', 'ALL', 'ALL PRIVILEGES', 'USAGE', - 'REQUIRESSL', # Deprecated, to be removed in version 3.0.0 - 'CREATE ROLE', 'DROP ROLE', 'APPLICATION_PASSWORD_ADMIN', - 'AUDIT_ADMIN', 'BACKUP_ADMIN', 'BINLOG_ADMIN', - 'BINLOG_ENCRYPTION_ADMIN', 'CLONE_ADMIN', 'CONNECTION_ADMIN', - 'ENCRYPTION_KEY_ADMIN', 'FIREWALL_ADMIN', 'FIREWALL_USER', - 'GROUP_REPLICATION_ADMIN', 'INNODB_REDO_LOG_ARCHIVE', - 'NDB_STORED_USER', 'PERSIST_RO_VARIABLES_ADMIN', - 'REPLICATION_APPLIER', 'REPLICATION_SLAVE_ADMIN', - 'RESOURCE_GROUP_ADMIN', 'RESOURCE_GROUP_USER', - 'ROLE_ADMIN', 'SESSION_VARIABLES_ADMIN', 'SET_USER_ID', - 'SYSTEM_USER', 'SYSTEM_VARIABLES_ADMIN', 'SYSTEM_USER', - 'TABLE_ENCRYPTION_ADMIN', 'VERSION_TOKEN_ADMIN', - 'XA_RECOVER_ADMIN', 'LOAD FROM S3', 'SELECT INTO S3', - 'INVOKE LAMBDA', - 'ALTER ROUTINE', - 'BINLOG ADMIN', - 'BINLOG MONITOR', - 'BINLOG REPLAY', - 'CONNECTION ADMIN', - 'READ_ONLY ADMIN', - 'REPLICATION MASTER ADMIN', - 'REPLICATION SLAVE ADMIN', - 'SET USER', - 'SHOW_ROUTINE', - 'SLAVE MONITOR', - 'REPLICA MONITOR',)) +EXTRA_PRIVS = ['ALL', 'ALL PRIVILEGES', 'GRANT', 'REQUIRESSL'] class InvalidPrivsError(Exception): @@ -141,6 +107,13 @@ def get_tls_requires(cursor, user, host): return requires or None +def get_valid_privs(cursor): + cursor.execute("SHOW PRIVILEGES") + show_privs = [priv[0].upper() for priv in cursor.fetchall()] + all_privs = show_privs + EXTRA_PRIVS + return frozenset(all_privs) + + def get_grants(cursor, user, host): cursor.execute("SHOW GRANTS FOR %s@%s", (user, host)) grants_line = list(filter(lambda x: "ON *.*" in x[0], cursor.fetchall()))[0] @@ -583,7 +556,7 @@ def sort_column_order(statement): return '%s(%s)' % (priv_name, ', '.join(columns)) -def privileges_unpack(priv, mode): +def privileges_unpack(priv, mode, valid_privs): """ Take a privileges string, typically passed as a parameter, and unserialize it into a dictionary, the same format as privileges_get() above. We have this custom format to avoid using YAML/JSON strings inside YAML playbooks. Example @@ -630,8 +603,8 @@ def privileges_unpack(priv, mode): output[pieces[0]] = normalize_col_grants(output[pieces[0]]) new_privs = frozenset(privs) - if not new_privs.issubset(VALID_PRIVS): - raise InvalidPrivsError('Invalid privileges specified: %s' % new_privs.difference(VALID_PRIVS)) + if not new_privs.issubset(valid_privs): + raise InvalidPrivsError('Invalid privileges specified: %s' % new_privs.difference(valid_privs)) if '*.*' not in output: output['*.*'] = ['USAGE'] diff --git a/plugins/modules/mysql_role.py b/plugins/modules/mysql_role.py index 80d01445..47b0b581 100644 --- a/plugins/modules/mysql_role.py +++ b/plugins/modules/mysql_role.py @@ -250,6 +250,7 @@ get_mode, user_mod, privileges_grant, + get_valid_privs, privileges_unpack, ) from ansible.module_utils._text import to_native @@ -1013,7 +1014,8 @@ def main(): module.fail_json(msg=to_native(e)) try: - priv = privileges_unpack(priv, mode) + valid_privs = get_valid_privs(cursor) + priv = privileges_unpack(priv, mode, valid_privs) except Exception as e: module.fail_json(msg='Invalid privileges string: %s' % to_native(e)) diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index 3172553f..9c043cca 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -318,6 +318,7 @@ handle_requiressl_in_priv_string, InvalidPrivsError, limit_resources, + get_valid_privs, privileges_unpack, sanitize_requires, user_add, @@ -421,7 +422,8 @@ def main(): except Exception as e: module.fail_json(msg=to_native(e)) try: - priv = privileges_unpack(priv, mode) + valid_privs = get_valid_privs(cursor) + priv = privileges_unpack(priv, mode, valid_privs) except Exception as e: module.fail_json(msg="invalid privileges string: %s" % to_native(e))