|
|
|
@ -214,8 +214,7 @@ EXAMPLES = """
|
|
|
|
|
# password=n<_665{vS43y
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import getpass
|
|
|
|
|
import tempfile
|
|
|
|
|
|
|
|
|
|
import re
|
|
|
|
|
import string
|
|
|
|
|
try:
|
|
|
|
@ -236,6 +235,7 @@ VALID_PRIVS = frozenset(('CREATE', 'DROP', 'GRANT', 'GRANT OPTION',
|
|
|
|
|
'REPLICATION SLAVE', 'SHOW DATABASES', 'SHUTDOWN',
|
|
|
|
|
'SUPER', 'ALL', 'ALL PRIVILEGES', 'USAGE', 'REQUIRESSL'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class InvalidPrivsError(Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
@ -243,6 +243,7 @@ class InvalidPrivsError(Exception):
|
|
|
|
|
# MySQL module specific support methods.
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# User Authentication Management was change in MySQL 5.7
|
|
|
|
|
# This is a generic check for if the server version is less than version 5.7
|
|
|
|
|
def server_version_check(cursor):
|
|
|
|
@ -255,11 +256,12 @@ def server_version_check(cursor):
|
|
|
|
|
# mariadb and the old-style update continues to work
|
|
|
|
|
if 'mariadb' in version_str.lower():
|
|
|
|
|
return True
|
|
|
|
|
if (int(version[0]) <= 5 and int(version[1]) < 7):
|
|
|
|
|
if int(version[0]) <= 5 and int(version[1]) < 7:
|
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_mode(cursor):
|
|
|
|
|
cursor.execute('SELECT @@GLOBAL.sql_mode')
|
|
|
|
|
result = cursor.fetchone()
|
|
|
|
@ -270,6 +272,7 @@ def get_mode(cursor):
|
|
|
|
|
mode = 'NOTANSI'
|
|
|
|
|
return mode
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def user_exists(cursor, user, host, host_all):
|
|
|
|
|
if host_all:
|
|
|
|
|
cursor.execute("SELECT count(*) FROM user WHERE user = %s", ([user]))
|
|
|
|
@ -279,6 +282,7 @@ def user_exists(cursor, user, host, host_all):
|
|
|
|
|
count = cursor.fetchone()
|
|
|
|
|
return count[0] > 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def user_add(cursor, user, host, host_all, password, encrypted, new_priv, check_mode):
|
|
|
|
|
# we cannot create users without a proper hostname
|
|
|
|
|
if host_all:
|
|
|
|
@ -298,6 +302,7 @@ def user_add(cursor, user, host, host_all, password, encrypted, new_priv, check_
|
|
|
|
|
privileges_grant(cursor, user, host, db_table, priv)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_hash(password):
|
|
|
|
|
ishash = False
|
|
|
|
|
if len(password) == 41 and password[0] == '*':
|
|
|
|
@ -305,6 +310,7 @@ def is_hash(password):
|
|
|
|
|
ishash = True
|
|
|
|
|
return ishash
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def user_mod(cursor, user, host, host_all, password, encrypted, new_priv, append_privs, module):
|
|
|
|
|
changed = False
|
|
|
|
|
grant_option = False
|
|
|
|
@ -385,7 +391,7 @@ def user_mod(cursor, user, host, host_all, password, encrypted, new_priv, append
|
|
|
|
|
db_table_intersect = set(new_priv.keys()) & set(curr_priv.keys())
|
|
|
|
|
for db_table in db_table_intersect:
|
|
|
|
|
priv_diff = set(new_priv[db_table]) ^ set(curr_priv[db_table])
|
|
|
|
|
if (len(priv_diff) > 0):
|
|
|
|
|
if len(priv_diff) > 0:
|
|
|
|
|
if module.check_mode:
|
|
|
|
|
return True
|
|
|
|
|
if not append_privs:
|
|
|
|
@ -395,6 +401,7 @@ def user_mod(cursor, user, host, host_all, password, encrypted, new_priv, append
|
|
|
|
|
|
|
|
|
|
return changed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def user_delete(cursor, user, host, host_all, check_mode):
|
|
|
|
|
if check_mode:
|
|
|
|
|
return True
|
|
|
|
@ -409,6 +416,7 @@ def user_delete(cursor, user, host, host_all, check_mode):
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def user_get_hostnames(cursor, user):
|
|
|
|
|
cursor.execute("SELECT Host FROM mysql.user WHERE user = %s", user)
|
|
|
|
|
hostnames_raw = cursor.fetchall()
|
|
|
|
@ -419,6 +427,7 @@ def user_get_hostnames(cursor, user):
|
|
|
|
|
|
|
|
|
|
return hostnames
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def privileges_get(cursor, user, host):
|
|
|
|
|
""" MySQL doesn't have a better method of getting privileges aside from the
|
|
|
|
|
SHOW GRANTS query syntax, which requires us to then parse the returned string.
|
|
|
|
@ -453,6 +462,7 @@ def privileges_get(cursor, user,host):
|
|
|
|
|
output[db] = privileges
|
|
|
|
|
return output
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def privileges_unpack(priv, mode):
|
|
|
|
|
""" 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
|
|
|
|
@ -501,6 +511,7 @@ def privileges_unpack(priv, mode):
|
|
|
|
|
|
|
|
|
|
return output
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def privileges_revoke(cursor, user, host, db_table, priv, grant_option):
|
|
|
|
|
# Escape '%' since mysql db.execute() uses a format string
|
|
|
|
|
db_table = db_table.replace('%', '%%')
|
|
|
|
@ -515,6 +526,7 @@ def privileges_revoke(cursor, user,host,db_table,priv,grant_option):
|
|
|
|
|
query = ' '.join(query)
|
|
|
|
|
cursor.execute(query, (user, host))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def privileges_grant(cursor, user, host, db_table, priv):
|
|
|
|
|
# Escape '%' since mysql db.execute uses a format string and the
|
|
|
|
|
# specification of db and table often use a % (SQL wildcard)
|
|
|
|
@ -533,6 +545,7 @@ def privileges_grant(cursor, user,host,db_table,priv):
|
|
|
|
|
# Module execution.
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
module = AnsibleModule(
|
|
|
|
|
argument_spec=dict(
|
|
|
|
@ -645,5 +658,6 @@ def main():
|
|
|
|
|
from ansible.module_utils.basic import *
|
|
|
|
|
from ansible.module_utils.database import *
|
|
|
|
|
from ansible.module_utils.mysql import *
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
main()
|
|
|
|
|