mirror of
https://github.com/ansible-collections/community.mysql.git
synced 2025-04-23 19:01:28 -07:00
feat[mysql_info]: add 'users_info' filter (#580)
* add documentation for new mysql_info users_info filter * Add integration tests for mysql_info users_info * fix list parsing when cursor come from mysql_info Mysql_info use a DictCursor and mysql_user a normal cursor. * fix case when an account as same user but different host and password * document why certain authentications plugins cause issues * add version_added for users_info to the documentation * Add 'users' description to differentiate it from 'users_info' --------- Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
This commit is contained in:
parent
6b7cc14989
commit
3ef9bda95f
6 changed files with 492 additions and 12 deletions
|
@ -112,23 +112,40 @@ def get_grants(cursor, user, host):
|
|||
return grants.split(", ")
|
||||
|
||||
|
||||
def get_existing_authentication(cursor, user):
|
||||
def get_existing_authentication(cursor, user, host):
|
||||
# Return the plugin and auth_string if there is exactly one distinct existing plugin and auth_string.
|
||||
cursor.execute("SELECT VERSION()")
|
||||
if 'mariadb' in cursor.fetchone()[0].lower():
|
||||
srv_type = cursor.fetchone()
|
||||
# Mysql_info use a DictCursor so we must convert back to a list
|
||||
# otherwise we get KeyError 0
|
||||
if isinstance(srv_type, dict):
|
||||
srv_type = list(srv_type.values())
|
||||
|
||||
if 'mariadb' in srv_type[0].lower():
|
||||
# before MariaDB 10.2.19 and 10.3.11, "password" and "authentication_string" can differ
|
||||
# when using mysql_native_password
|
||||
cursor.execute("""select plugin, auth from (
|
||||
select plugin, password as auth from mysql.user where user=%(user)s
|
||||
and host=%(host)s
|
||||
union select plugin, authentication_string as auth from mysql.user where user=%(user)s
|
||||
) x group by plugin, auth limit 2
|
||||
""", {'user': user})
|
||||
and host=%(host)s) x group by plugin, auth limit 2
|
||||
""", {'user': user, 'host': host})
|
||||
else:
|
||||
cursor.execute("""select plugin, authentication_string as auth from mysql.user where user=%(user)s
|
||||
group by plugin, authentication_string limit 2""", {'user': user})
|
||||
cursor.execute("""select plugin, authentication_string as auth
|
||||
from mysql.user where user=%(user)s and host=%(host)s
|
||||
group by plugin, authentication_string limit 2""", {'user': user, 'host': host})
|
||||
rows = cursor.fetchall()
|
||||
if len(rows) == 1:
|
||||
return {'plugin': rows[0][0], 'auth_string': rows[0][1]}
|
||||
|
||||
# Mysql_info use a DictCursor so we must convert back to a list
|
||||
# otherwise we get KeyError 0
|
||||
if isinstance(rows, dict):
|
||||
rows = list(rows.values())
|
||||
|
||||
if isinstance(rows[0], tuple):
|
||||
return {'plugin': rows[0][0], 'plugin_auth_string': rows[0][1]}
|
||||
|
||||
if isinstance(rows[0], dict):
|
||||
return {'plugin': rows[0].get('plugin'), 'plugin_auth_string': rows[0].get('auth')}
|
||||
return None
|
||||
|
||||
|
||||
|
@ -149,7 +166,7 @@ def user_add(cursor, user, host, host_all, password, encrypted,
|
|||
|
||||
used_existing_password = False
|
||||
if reuse_existing_password:
|
||||
existing_auth = get_existing_authentication(cursor, user)
|
||||
existing_auth = get_existing_authentication(cursor, user, host)
|
||||
if existing_auth:
|
||||
plugin = existing_auth['plugin']
|
||||
plugin_hash_string = existing_auth['auth_string']
|
||||
|
@ -478,6 +495,12 @@ def privileges_get(cursor, user, host, maria_role=False):
|
|||
return x
|
||||
|
||||
for grant in grants:
|
||||
|
||||
# Mysql_info use a DictCursor so we must convert back to a list
|
||||
# otherwise we get KeyError 0
|
||||
if isinstance(grant, dict):
|
||||
grant = list(grant.values())
|
||||
|
||||
if not maria_role:
|
||||
res = re.match("""GRANT (.+) ON (.+) TO (['`"]).*\\3@(['`"]).*\\4( IDENTIFIED BY PASSWORD (['`"]).+\\6)? ?(.*)""", grant[0])
|
||||
else:
|
||||
|
@ -777,6 +800,11 @@ def get_resource_limits(cursor, user, host):
|
|||
cursor.execute(query, (user, host))
|
||||
res = cursor.fetchone()
|
||||
|
||||
# Mysql_info use a DictCursor so we must convert back to a list
|
||||
# otherwise we get KeyError 0
|
||||
if isinstance(res, dict):
|
||||
res = list(res.values())
|
||||
|
||||
if not res:
|
||||
return None
|
||||
|
||||
|
@ -788,11 +816,22 @@ def get_resource_limits(cursor, user, host):
|
|||
}
|
||||
|
||||
cursor.execute("SELECT VERSION()")
|
||||
if 'mariadb' in cursor.fetchone()[0].lower():
|
||||
srv_type = cursor.fetchone()
|
||||
# Mysql_info use a DictCursor so we must convert back to a list
|
||||
# otherwise we get KeyError 0
|
||||
if isinstance(srv_type, dict):
|
||||
srv_type = list(srv_type.values())
|
||||
|
||||
if 'mariadb' in srv_type[0].lower():
|
||||
query = ('SELECT max_statement_time AS MAX_STATEMENT_TIME '
|
||||
'FROM mysql.user WHERE User = %s AND Host = %s')
|
||||
cursor.execute(query, (user, host))
|
||||
res_max_statement_time = cursor.fetchone()
|
||||
|
||||
# Mysql_info use a DictCursor so we must convert back to a list
|
||||
# otherwise we get KeyError 0
|
||||
if isinstance(res_max_statement_time, dict):
|
||||
res_max_statement_time = list(res_max_statement_time.values())
|
||||
current_limits['MAX_STATEMENT_TIME'] = res_max_statement_time[0]
|
||||
|
||||
return current_limits
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue