|
|
|
@ -36,6 +36,11 @@ options:
|
|
|
|
|
- set the user's password. (Required when adding a user)
|
|
|
|
|
required: false
|
|
|
|
|
default: null
|
|
|
|
|
password_hash:
|
|
|
|
|
description:
|
|
|
|
|
- set the user's password hash (used in place of plain text password)
|
|
|
|
|
required: false
|
|
|
|
|
default: null
|
|
|
|
|
host:
|
|
|
|
|
description:
|
|
|
|
|
- the 'host' part of the MySQL username
|
|
|
|
@ -159,6 +164,7 @@ password=n<_665{vS43y
|
|
|
|
|
import getpass
|
|
|
|
|
import tempfile
|
|
|
|
|
import re
|
|
|
|
|
import string
|
|
|
|
|
try:
|
|
|
|
|
import MySQLdb
|
|
|
|
|
except ImportError:
|
|
|
|
@ -208,26 +214,48 @@ def user_exists(cursor, user, host):
|
|
|
|
|
count = cursor.fetchone()
|
|
|
|
|
return count[0] > 0
|
|
|
|
|
|
|
|
|
|
def user_add(cursor, user, host, password, new_priv):
|
|
|
|
|
def user_add(cursor, user, host, password, password_hash, new_priv):
|
|
|
|
|
if password and not password_hash:
|
|
|
|
|
cursor.execute("CREATE USER %s@%s IDENTIFIED BY %s", (user,host,password))
|
|
|
|
|
elif password_hash:
|
|
|
|
|
cursor.execute("CREATE USER %s@%s IDENTIFIED BY PASSWORD %s", (user,host,password_hash))
|
|
|
|
|
if new_priv is not None:
|
|
|
|
|
for db_table, priv in new_priv.iteritems():
|
|
|
|
|
privileges_grant(cursor, user,host,db_table,priv)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def user_mod(cursor, user, host, password, new_priv, append_privs):
|
|
|
|
|
def is_hash(password):
|
|
|
|
|
ishash = False
|
|
|
|
|
if len(password) is 41 and password[0] is '*':
|
|
|
|
|
ishash = True
|
|
|
|
|
for i in password[1:]:
|
|
|
|
|
if i not in string.hexdigits:
|
|
|
|
|
ishash = False
|
|
|
|
|
break
|
|
|
|
|
return ishash
|
|
|
|
|
|
|
|
|
|
def user_mod(cursor, user, host, password, password_hash, new_priv, append_privs):
|
|
|
|
|
changed = False
|
|
|
|
|
grant_option = False
|
|
|
|
|
|
|
|
|
|
# Handle passwords
|
|
|
|
|
if password is not None:
|
|
|
|
|
# Handle passwords.
|
|
|
|
|
if password is not None or password_hash is not None:
|
|
|
|
|
cursor.execute("SELECT password FROM user WHERE user = %s AND host = %s", (user,host))
|
|
|
|
|
current_pass_hash = cursor.fetchone()
|
|
|
|
|
|
|
|
|
|
if password:
|
|
|
|
|
cursor.execute("SELECT PASSWORD(%s)", (password,))
|
|
|
|
|
new_pass_hash = cursor.fetchone()
|
|
|
|
|
if current_pass_hash[0] != new_pass_hash[0]:
|
|
|
|
|
cursor.execute("SET PASSWORD FOR %s@%s = PASSWORD(%s)", (user,host,password))
|
|
|
|
|
changed = True
|
|
|
|
|
elif password_hash:
|
|
|
|
|
if is_hash(password_hash):
|
|
|
|
|
if current_pass_hash[0] != password_hash:
|
|
|
|
|
cursor.execute("SET PASSWORD FOR %s@%s = %s", (user, host, password_hash))
|
|
|
|
|
changed = True
|
|
|
|
|
else:
|
|
|
|
|
module.fail_json(msg="password_hash was specified however it does not appear to be a valid hash expecting: *SHA1(SHA1(your_password))")
|
|
|
|
|
|
|
|
|
|
# Handle privileges
|
|
|
|
|
if new_priv is not None:
|
|
|
|
@ -384,7 +412,8 @@ def main():
|
|
|
|
|
login_port=dict(default=3306, type='int'),
|
|
|
|
|
login_unix_socket=dict(default=None),
|
|
|
|
|
user=dict(required=True, aliases=['name']),
|
|
|
|
|
password=dict(default=None, no_log=True),
|
|
|
|
|
password=dict(default=None),
|
|
|
|
|
password_hash=dict(default=None),
|
|
|
|
|
host=dict(default="localhost"),
|
|
|
|
|
state=dict(default="present", choices=["absent", "present"]),
|
|
|
|
|
priv=dict(default=None),
|
|
|
|
@ -398,7 +427,8 @@ def main():
|
|
|
|
|
login_password = module.params["login_password"]
|
|
|
|
|
user = module.params["user"]
|
|
|
|
|
password = module.params["password"]
|
|
|
|
|
host = module.params["host"].lower()
|
|
|
|
|
password_hash = module.params["password_hash"]
|
|
|
|
|
host = module.params["host"]
|
|
|
|
|
state = module.params["state"]
|
|
|
|
|
priv = module.params["priv"]
|
|
|
|
|
check_implicit_admin = module.params['check_implicit_admin']
|
|
|
|
@ -430,21 +460,11 @@ def main():
|
|
|
|
|
|
|
|
|
|
if state == "present":
|
|
|
|
|
if user_exists(cursor, user, host):
|
|
|
|
|
try:
|
|
|
|
|
if update_password == 'always':
|
|
|
|
|
changed = user_mod(cursor, user, host, password, priv, append_privs)
|
|
|
|
|
changed = user_mod(cursor, user, host, password, password_hash, priv, append_privs)
|
|
|
|
|
else:
|
|
|
|
|
changed = user_mod(cursor, user, host, None, priv, append_privs)
|
|
|
|
|
|
|
|
|
|
except (SQLParseError, InvalidPrivsError, MySQLdb.Error), e:
|
|
|
|
|
module.fail_json(msg=str(e))
|
|
|
|
|
else:
|
|
|
|
|
if password is None:
|
|
|
|
|
module.fail_json(msg="password parameter required when adding a user")
|
|
|
|
|
try:
|
|
|
|
|
changed = user_add(cursor, user, host, password, priv)
|
|
|
|
|
except (SQLParseError, InvalidPrivsError, MySQLdb.Error), e:
|
|
|
|
|
module.fail_json(msg=str(e))
|
|
|
|
|
if password is None and password_hash is None:
|
|
|
|
|
module.fail_json(msg="password or password_hash parameter required when adding a user")
|
|
|
|
|
changed = user_add(cursor, user, host, password, password_hash, priv)
|
|
|
|
|
elif state == "absent":
|
|
|
|
|
if user_exists(cursor, user, host):
|
|
|
|
|
changed = user_delete(cursor, user, host)
|
|
|
|
|