Add Jmainguy as author, fix hash check

This commit is contained in:
Jonathan Mainguy 2015-12-11 20:29:45 -05:00 committed by Matt Clay
parent 9c131ea619
commit b86224a7ec

View file

@ -43,7 +43,7 @@ options:
- set the user's password. (Required when adding a user) - set the user's password. (Required when adding a user)
required: false required: false
default: null default: null
password_hash: encrypted:
description: description:
- Indicate that the 'password' field is a `mysql_native_password` hash - Indicate that the 'password' field is a `mysql_native_password` hash
required: false required: false
@ -144,7 +144,7 @@ notes:
- Currently, there is only support for the `mysql_native_password` encryted password hash module. - Currently, there is only support for the `mysql_native_password` encryted password hash module.
requirements: [ "MySQLdb" ] requirements: [ "MySQLdb" ]
author: "Ansible Core Team" author: "Jonathan Mainguy (@Jmainguy)"
''' '''
EXAMPLES = """ EXAMPLES = """
@ -253,10 +253,22 @@ def user_add(cursor, user, host, host_all, password, new_priv):
privileges_grant(cursor, user,host,db_table,priv) privileges_grant(cursor, user,host,db_table,priv)
return True return True
def user_mod(cursor, user, host, host_all, password, new_priv, append_privs): def is_hash(password):
ishash = False
if len(password) == 41 and password[0] == '*':
if frozenset(password[1:]).issubset(string.hexdigits):
ishash = True
return ishash
def user_mod(cursor, user, host, password, encrypted, new_priv, append_privs):
changed = False changed = False
grant_option = False grant_option = False
# Handle clear text and hashed passwords.
if bool(password):
# Determine what user management method server uses
old_user_mgmt = server_version_check(cursor)
# to simplify code, if we have a specific host and no host_all, we create # to simplify code, if we have a specific host and no host_all, we create
# a list with just host and loop over that # a list with just host and loop over that
if host_all: if host_all:
@ -268,13 +280,32 @@ def user_mod(cursor, user, host, host_all, password, new_priv, append_privs):
# Handle passwords # Handle passwords
if password is not None: if password is not None:
cursor.execute("SELECT password FROM user WHERE user = %s AND host = %s", (user,host)) cursor.execute("SELECT password FROM user WHERE user = %s AND host = %s", (user,host))
else:
cursor.execute("SELECT authentication_string FROM user WHERE user = %s AND host = %s", (user,host))
current_pass_hash = cursor.fetchone() current_pass_hash = cursor.fetchone()
if encrypted:
encrypted_string = (password)
if is_hash(password):
if current_pass_hash[0] != encrypted_string:
if old_user_mgmt:
cursor.execute("SET PASSWORD FOR %s@%s = %s", (user, host, password))
else:
cursor.execute("ALTER USER %s@%s IDENTIFIED WITH mysql_native_password AS %s", (user, host, password))
changed = True
else:
module.fail_json(msg="encrypted was specified however it does not appear to be a valid hash expecting: *SHA1(SHA1(your_password))")
else:
if old_user_mgmt:
cursor.execute("SELECT PASSWORD(%s)", (password,)) cursor.execute("SELECT PASSWORD(%s)", (password,))
else:
cursor.execute("SELECT CONCAT('*', UCASE(SHA1(UNHEX(SHA1(%s)))))", (password,))
new_pass_hash = cursor.fetchone() new_pass_hash = cursor.fetchone()
if current_pass_hash[0] != new_pass_hash[0]: if current_pass_hash[0] != new_pass_hash[0]:
cursor.execute("SET PASSWORD FOR %s@%s = PASSWORD(%s)", (user,host,password)) cursor.execute("SET PASSWORD FOR %s@%s = PASSWORD(%s)", (user,host,password))
changed = True changed = True
# Handle privileges # Handle privileges
if new_priv is not None: if new_priv is not None:
curr_priv = privileges_get(cursor, user,host) curr_priv = privileges_get(cursor, user,host)
@ -290,13 +321,6 @@ def user_mod(cursor, user, host, host_all, password, new_priv, append_privs):
privileges_revoke(cursor, user,host,db_table,priv,grant_option) privileges_revoke(cursor, user,host,db_table,priv,grant_option)
changed = True changed = True
# If the user doesn't currently have any privileges on a db.table, then
# we can perform a straight grant operation.
for db_table, priv in new_priv.iteritems():
if db_table not in curr_priv:
privileges_grant(cursor, user,host,db_table,priv)
changed = True
# If the db.table specification exists in both the user's current privileges # If the db.table specification exists in both the user's current privileges
# and in the new privileges, then we need to see if there's a difference. # and in the new privileges, then we need to see if there's a difference.
db_table_intersect = set(new_priv.keys()) & set(curr_priv.keys()) db_table_intersect = set(new_priv.keys()) & set(curr_priv.keys())
@ -502,12 +526,12 @@ def main():
module.fail_json(msg="unable to connect to database, check login_user and login_password are correct or ~/.my.cnf has the credentials") module.fail_json(msg="unable to connect to database, check login_user and login_password are correct or ~/.my.cnf has the credentials")
if state == "present": if state == "present":
if user_exists(cursor, user, host, host_all): if user_exists(cursor, user, host):
try: try:
if update_password == 'always': if update_password == 'always':
changed = user_mod(cursor, user, host, host_all, password, priv, append_privs) changed = user_mod(cursor, user, host, password, encrypted, priv, append_privs)
else: else:
changed = user_mod(cursor, user, host, host_all, None, priv, append_privs) changed = user_mod(cursor, user, host, None, encrypted, priv, append_privs)
except (SQLParseError, InvalidPrivsError, MySQLdb.Error), e: except (SQLParseError, InvalidPrivsError, MySQLdb.Error), e:
module.fail_json(msg=str(e)) module.fail_json(msg=str(e))