mirror of
https://github.com/ansible-collections/community.mysql.git
synced 2025-04-07 11:10:32 -07:00
password_expire support for mysql_user (#598)
* initial commit for password_expire support * sanity check and default values * add one more if block for version check * some changes and integration tests * docs and sanity and integration test fix * make integration tests work * make integration tests work * fix unneeded commits * fix verify as well * Update plugins/modules/mysql_user.py Co-authored-by: Laurent Indermühle <laurent.indermuehle@pm.me> * Update tests/integration/targets/test_mysql_user/tasks/test_password_expire.yml Co-authored-by: Laurent Indermühle <laurent.indermuehle@pm.me> * Apply suggestions from code review Co-authored-by: Laurent Indermühle <laurent.indermuehle@pm.me> * Update plugins/modules/mysql_user.py Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> * Update plugins/modules/mysql_user.py Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> * Update plugins/modules/mysql_user.py Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> * Update plugins/modules/mysql_user.py Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> * Update plugins/module_utils/user.py Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> * Update plugins/module_utils/user.py Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> * Update plugins/module_utils/user.py Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> * typo and no_log remove for password_expire* vars * add change log fragment * move one if statement to module initialiazation * fix merge conflicts * fix order * some fixes * set no_log to true for password word containing keys * fix sanity error * Update changelogs/fragments/598-password_expire-support-for-mysql_user.yml Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru> --------- Co-authored-by: Laurent Indermühle <laurent.indermuehle@pm.me> Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
This commit is contained in:
parent
21fe52d8f1
commit
40af258d86
9 changed files with 375 additions and 6 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- "mysql_user - add the ``password_expire`` and ``password_expire_interval`` arguments to implement the password expiration management for mysql user (https://github.com/ansible-collections/community.mysql/pull/598)."
|
|
@ -23,3 +23,9 @@ def server_supports_alter_user(cursor):
|
||||||
version = get_server_version(cursor)
|
version = get_server_version(cursor)
|
||||||
|
|
||||||
return LooseVersion(version) >= LooseVersion("10.2")
|
return LooseVersion(version) >= LooseVersion("10.2")
|
||||||
|
|
||||||
|
|
||||||
|
def server_supports_password_expire(cursor):
|
||||||
|
version = get_server_version(cursor)
|
||||||
|
|
||||||
|
return LooseVersion(version) >= LooseVersion("10.4.3")
|
||||||
|
|
|
@ -24,3 +24,9 @@ def server_supports_alter_user(cursor):
|
||||||
version = get_server_version(cursor)
|
version = get_server_version(cursor)
|
||||||
|
|
||||||
return LooseVersion(version) >= LooseVersion("5.6")
|
return LooseVersion(version) >= LooseVersion("5.6")
|
||||||
|
|
||||||
|
|
||||||
|
def server_supports_password_expire(cursor):
|
||||||
|
version = get_server_version(cursor)
|
||||||
|
|
||||||
|
return LooseVersion(version) >= LooseVersion("5.7")
|
||||||
|
|
|
@ -152,7 +152,8 @@ def get_existing_authentication(cursor, user, host):
|
||||||
|
|
||||||
def user_add(cursor, user, host, host_all, password, encrypted,
|
def user_add(cursor, user, host, host_all, password, encrypted,
|
||||||
plugin, plugin_hash_string, plugin_auth_string, new_priv,
|
plugin, plugin_hash_string, plugin_auth_string, new_priv,
|
||||||
attributes, tls_requires, reuse_existing_password, module):
|
attributes, tls_requires, reuse_existing_password, module,
|
||||||
|
password_expire, password_expire_interval):
|
||||||
# If attributes are set, perform a sanity check to ensure server supports user attributes before creating user
|
# If attributes are set, perform a sanity check to ensure server supports user attributes before creating user
|
||||||
if attributes and not get_attribute_support(cursor):
|
if attributes and not get_attribute_support(cursor):
|
||||||
module.fail_json(msg="user attributes were specified but the server does not support user attributes")
|
module.fail_json(msg="user attributes were specified but the server does not support user attributes")
|
||||||
|
@ -205,6 +206,12 @@ def user_add(cursor, user, host, host_all, password, encrypted,
|
||||||
query_with_args_and_tls_requires = query_with_args + (tls_requires,)
|
query_with_args_and_tls_requires = query_with_args + (tls_requires,)
|
||||||
cursor.execute(*mogrify(*query_with_args_and_tls_requires))
|
cursor.execute(*mogrify(*query_with_args_and_tls_requires))
|
||||||
|
|
||||||
|
if password_expire:
|
||||||
|
if not impl.server_supports_password_expire(cursor):
|
||||||
|
module.fail_json(msg="The server version does not match the requirements "
|
||||||
|
"for password_expire parameter. See module's documentation.")
|
||||||
|
set_password_expire(cursor, user, host, password_expire, password_expire_interval)
|
||||||
|
|
||||||
if new_priv is not None:
|
if new_priv is not None:
|
||||||
for db_table, priv in iteritems(new_priv):
|
for db_table, priv in iteritems(new_priv):
|
||||||
privileges_grant(cursor, user, host, db_table, priv, tls_requires)
|
privileges_grant(cursor, user, host, db_table, priv, tls_requires)
|
||||||
|
@ -230,7 +237,8 @@ def is_hash(password):
|
||||||
|
|
||||||
def user_mod(cursor, user, host, host_all, password, encrypted,
|
def user_mod(cursor, user, host, host_all, password, encrypted,
|
||||||
plugin, plugin_hash_string, plugin_auth_string, new_priv,
|
plugin, plugin_hash_string, plugin_auth_string, new_priv,
|
||||||
append_privs, subtract_privs, attributes, tls_requires, module, role=False, maria_role=False):
|
append_privs, subtract_privs, attributes, tls_requires, module,
|
||||||
|
password_expire, password_expire_interval, role=False, maria_role=False):
|
||||||
changed = False
|
changed = False
|
||||||
msg = "User unchanged"
|
msg = "User unchanged"
|
||||||
grant_option = False
|
grant_option = False
|
||||||
|
@ -312,6 +320,28 @@ def user_mod(cursor, user, host, host_all, password, encrypted,
|
||||||
raise e
|
raise e
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
|
# Handle password expiration
|
||||||
|
if bool(password_expire):
|
||||||
|
if not impl.server_supports_password_expire(cursor):
|
||||||
|
module.fail_json(msg="The server version does not match the requirements "
|
||||||
|
"for password_expire parameter. See module's documentation.")
|
||||||
|
update = False
|
||||||
|
mariadb_role = True if "mariadb" in str(impl.__name__) else False
|
||||||
|
current_password_policy = get_password_expiration_policy(cursor, user, host, maria_role=mariadb_role)
|
||||||
|
password_expired = is_password_expired(cursor, user, host)
|
||||||
|
# Check if changes needed to be applied.
|
||||||
|
if not ((current_password_policy == -1 and password_expire == "default") or
|
||||||
|
(current_password_policy == 0 and password_expire == "never") or
|
||||||
|
(current_password_policy == password_expire_interval and password_expire == "interval") or
|
||||||
|
(password_expire == 'now' and password_expired)):
|
||||||
|
|
||||||
|
update = True
|
||||||
|
|
||||||
|
if not module.check_mode:
|
||||||
|
set_password_expire(cursor, user, host, password_expire, password_expire_interval)
|
||||||
|
password_changed = True
|
||||||
|
changed = True
|
||||||
|
|
||||||
# Handle plugin authentication
|
# Handle plugin authentication
|
||||||
if plugin and not role:
|
if plugin and not role:
|
||||||
cursor.execute("SELECT plugin, authentication_string FROM mysql.user "
|
cursor.execute("SELECT plugin, authentication_string FROM mysql.user "
|
||||||
|
@ -973,6 +1003,72 @@ def limit_resources(module, cursor, user, host, resource_limits, check_mode):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def set_password_expire(cursor, user, host, password_expire, password_expire_interval):
|
||||||
|
"""Fuction to set passowrd expiration for user.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cursor (cursor): DB driver cursor object.
|
||||||
|
user (str): User name.
|
||||||
|
host (str): User hostname.
|
||||||
|
password_expire (str): Password expiration mode.
|
||||||
|
password_expire_days (int): Invterval of days password expires.
|
||||||
|
"""
|
||||||
|
if password_expire.lower() == "never":
|
||||||
|
statement = "PASSWORD EXPIRE NEVER"
|
||||||
|
elif password_expire.lower() == "default":
|
||||||
|
statement = "PASSWORD EXPIRE DEFAULT"
|
||||||
|
elif password_expire.lower() == "interval":
|
||||||
|
statement = "PASSWORD EXPIRE INTERVAL %d DAY" % (password_expire_interval)
|
||||||
|
elif password_expire.lower() == "now":
|
||||||
|
statement = "PASSWORD EXPIRE"
|
||||||
|
|
||||||
|
cursor.execute("ALTER USER %s@%s " + statement, (user, host))
|
||||||
|
|
||||||
|
|
||||||
|
def get_password_expiration_policy(cursor, user, host, maria_role=False):
|
||||||
|
"""Function to get password policy for user.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cursor (cursor): DB driver cursor object.
|
||||||
|
user (str): User name.
|
||||||
|
host (str): User hostname.
|
||||||
|
maria_role (bool, optional): mariadb or mysql. Defaults to False.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
policy (int): Current users password policy.
|
||||||
|
"""
|
||||||
|
if not maria_role:
|
||||||
|
statement = "SELECT IFNULL(password_lifetime, -1) FROM mysql.user \
|
||||||
|
WHERE User = %s AND Host = %s", (user, host)
|
||||||
|
else:
|
||||||
|
statement = "SELECT JSON_EXTRACT(Priv, '$.password_lifetime') AS password_lifetime \
|
||||||
|
FROM mysql.global_priv \
|
||||||
|
WHERE User = %s AND Host = %s", (user, host)
|
||||||
|
cursor.execute(*statement)
|
||||||
|
policy = cursor.fetchone()[0]
|
||||||
|
return int(policy)
|
||||||
|
|
||||||
|
|
||||||
|
def is_password_expired(cursor, user, host):
|
||||||
|
"""Function to check if password is expired
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cursor (cursor): DB driver cursor object.
|
||||||
|
user (str): User name.
|
||||||
|
host (str): User hostname.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
expired (bool): True if expired, else False.
|
||||||
|
"""
|
||||||
|
statement = "SELECT password_expired FROM mysql.user \
|
||||||
|
WHERE User = %s AND Host = %s", (user, host)
|
||||||
|
cursor.execute(*statement)
|
||||||
|
expired = cursor.fetchone()[0]
|
||||||
|
if str(expired) == "Y":
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_attribute_support(cursor):
|
def get_attribute_support(cursor):
|
||||||
"""Checks if the MySQL server supports user attributes.
|
"""Checks if the MySQL server supports user attributes.
|
||||||
|
|
||||||
|
|
|
@ -932,7 +932,8 @@ class Role():
|
||||||
result = user_mod(self.cursor, self.name, self.host,
|
result = user_mod(self.cursor, self.name, self.host,
|
||||||
None, None, None, None, None, None,
|
None, None, None, None, None, None,
|
||||||
privs, append_privs, subtract_privs, None, None,
|
privs, append_privs, subtract_privs, None, None,
|
||||||
self.module, role=True, maria_role=self.is_mariadb)
|
self.module, None, None, role=True,
|
||||||
|
maria_role=self.is_mariadb)
|
||||||
changed = result['changed']
|
changed = result['changed']
|
||||||
|
|
||||||
if admin:
|
if admin:
|
||||||
|
|
|
@ -155,6 +155,21 @@ options:
|
||||||
- Cannot be used to set global variables, use the M(community.mysql.mysql_variables) module instead.
|
- Cannot be used to set global variables, use the M(community.mysql.mysql_variables) module instead.
|
||||||
type: dict
|
type: dict
|
||||||
version_added: '3.6.0'
|
version_added: '3.6.0'
|
||||||
|
password_expire:
|
||||||
|
description:
|
||||||
|
- C(never) - I(password) will never expire.
|
||||||
|
- C(default) - I(password) is defined using global system variable I(default_password_lifetime) setting.
|
||||||
|
- C(interval) - I(password) will expire in days which is defined in I(password_expire_interval).
|
||||||
|
- C(now) - I(password) will expire immediately.
|
||||||
|
type: str
|
||||||
|
choices: [ now, never, default, interval ]
|
||||||
|
version_added: '3.9.0'
|
||||||
|
password_expire_interval:
|
||||||
|
description:
|
||||||
|
- Number of days I(password) will expire. Requires I(password_expire=interval).
|
||||||
|
type: int
|
||||||
|
version_added: '3.9.0'
|
||||||
|
|
||||||
column_case_sensitive:
|
column_case_sensitive:
|
||||||
description:
|
description:
|
||||||
- The default is C(false).
|
- The default is C(false).
|
||||||
|
@ -429,6 +444,8 @@ def main():
|
||||||
force_context=dict(type='bool', default=False),
|
force_context=dict(type='bool', default=False),
|
||||||
session_vars=dict(type='dict'),
|
session_vars=dict(type='dict'),
|
||||||
column_case_sensitive=dict(type='bool', default=None), # TODO 4.0.0 add default=True
|
column_case_sensitive=dict(type='bool', default=None), # TODO 4.0.0 add default=True
|
||||||
|
password_expire=dict(type='str', choices=['now', 'never', 'default', 'interval'], no_log=True),
|
||||||
|
password_expire_interval=dict(type='int', required_if=[('password_expire', 'interval', True)], no_log=True),
|
||||||
)
|
)
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=argument_spec,
|
argument_spec=argument_spec,
|
||||||
|
@ -466,6 +483,8 @@ def main():
|
||||||
resource_limits = module.params["resource_limits"]
|
resource_limits = module.params["resource_limits"]
|
||||||
session_vars = module.params["session_vars"]
|
session_vars = module.params["session_vars"]
|
||||||
column_case_sensitive = module.params["column_case_sensitive"]
|
column_case_sensitive = module.params["column_case_sensitive"]
|
||||||
|
password_expire = module.params["password_expire"]
|
||||||
|
password_expire_interval = module.params["password_expire_interval"]
|
||||||
|
|
||||||
if priv and not isinstance(priv, (str, dict)):
|
if priv and not isinstance(priv, (str, dict)):
|
||||||
module.fail_json(msg="priv parameter must be str or dict but %s was passed" % type(priv))
|
module.fail_json(msg="priv parameter must be str or dict but %s was passed" % type(priv))
|
||||||
|
@ -476,6 +495,10 @@ def main():
|
||||||
if mysql_driver is None:
|
if mysql_driver is None:
|
||||||
module.fail_json(msg=mysql_driver_fail_msg)
|
module.fail_json(msg=mysql_driver_fail_msg)
|
||||||
|
|
||||||
|
if password_expire_interval and password_expire_interval < 1:
|
||||||
|
module.fail_json(msg="password_expire_interval value \
|
||||||
|
should be positive number")
|
||||||
|
|
||||||
cursor = None
|
cursor = None
|
||||||
try:
|
try:
|
||||||
if check_implicit_admin:
|
if check_implicit_admin:
|
||||||
|
@ -522,12 +545,14 @@ def main():
|
||||||
if update_password == "always":
|
if update_password == "always":
|
||||||
result = user_mod(cursor, user, host, host_all, password, encrypted,
|
result = user_mod(cursor, user, host, host_all, password, encrypted,
|
||||||
plugin, plugin_hash_string, plugin_auth_string,
|
plugin, plugin_hash_string, plugin_auth_string,
|
||||||
priv, append_privs, subtract_privs, attributes, tls_requires, module)
|
priv, append_privs, subtract_privs, attributes, tls_requires, module,
|
||||||
|
password_expire, password_expire_interval)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
result = user_mod(cursor, user, host, host_all, None, encrypted,
|
result = user_mod(cursor, user, host, host_all, None, encrypted,
|
||||||
None, None, None,
|
None, None, None,
|
||||||
priv, append_privs, subtract_privs, attributes, tls_requires, module)
|
priv, append_privs, subtract_privs, attributes, tls_requires, module,
|
||||||
|
password_expire, password_expire_interval)
|
||||||
changed = result['changed']
|
changed = result['changed']
|
||||||
msg = result['msg']
|
msg = result['msg']
|
||||||
password_changed = result['password_changed']
|
password_changed = result['password_changed']
|
||||||
|
@ -544,7 +569,8 @@ def main():
|
||||||
reuse_existing_password = update_password == 'on_new_username'
|
reuse_existing_password = update_password == 'on_new_username'
|
||||||
result = user_add(cursor, user, host, host_all, password, encrypted,
|
result = user_add(cursor, user, host, host_all, password, encrypted,
|
||||||
plugin, plugin_hash_string, plugin_auth_string,
|
plugin, plugin_hash_string, plugin_auth_string,
|
||||||
priv, attributes, tls_requires, reuse_existing_password, module)
|
priv, attributes, tls_requires, reuse_existing_password, module,
|
||||||
|
password_expire, password_expire_interval)
|
||||||
changed = result['changed']
|
changed = result['changed']
|
||||||
password_changed = result['password_changed']
|
password_changed = result['password_changed']
|
||||||
final_attributes = result['attributes']
|
final_attributes = result['attributes']
|
||||||
|
|
|
@ -43,6 +43,8 @@
|
||||||
|
|
||||||
- include_tasks: test_idempotency.yml
|
- include_tasks: test_idempotency.yml
|
||||||
|
|
||||||
|
- include_tasks: test_password_expire.yml
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Create user with no privileges and verify default privileges are assign
|
# Create user with no privileges and verify default privileges are assign
|
||||||
#
|
#
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
---
|
||||||
|
# Tests scenarios for password_expire
|
||||||
|
|
||||||
|
- vars:
|
||||||
|
mysql_parameters: &mysql_params
|
||||||
|
login_user: "{{ mysql_user }}"
|
||||||
|
login_password: "{{ mysql_password }}"
|
||||||
|
login_host: "{{ mysql_host }}"
|
||||||
|
login_port: "{{ mysql_primary_port }}"
|
||||||
|
|
||||||
|
block:
|
||||||
|
- include_tasks: utils/assert_user_password_expire.yml
|
||||||
|
vars:
|
||||||
|
username: "{{ item.username }}"
|
||||||
|
host: "{{ item.host | default('localhost')}}"
|
||||||
|
password_expire: "{{ item.password_expire }}"
|
||||||
|
password: "{{ user_password_1 }}"
|
||||||
|
expect_change: "{{ item.expect_change }}"
|
||||||
|
expect_password_expire_change: "{{ item.expect_password_expire_change }}"
|
||||||
|
expected_password_lifetime: "{{ item.expected_password_lifetime }}"
|
||||||
|
password_expire_interval: "{{ item.password_expire_interval | default(omit) }}"
|
||||||
|
expected_password_expired: "{{ item.expected_password_expired }}"
|
||||||
|
check_mode: "{{ item.check_mode | default(omit) }}"
|
||||||
|
loop:
|
||||||
|
# all variants set the password when nothing exists
|
||||||
|
# never expires
|
||||||
|
- username: "{{ user_name_1 }}"
|
||||||
|
host: "%"
|
||||||
|
password_expire: never
|
||||||
|
expect_change: true
|
||||||
|
expected_password_lifetime: "0"
|
||||||
|
expected_password_expired: "N"
|
||||||
|
# expires ussing default policy
|
||||||
|
- username: "{{ user_name_2 }}"
|
||||||
|
password_expire: default
|
||||||
|
expect_change: true
|
||||||
|
expected_password_lifetime: "-1"
|
||||||
|
expected_password_expired: "N"
|
||||||
|
# expires ussing interval
|
||||||
|
- username: "{{ user_name_3 }}"
|
||||||
|
password_expire: interval
|
||||||
|
password_expire_interval: "10"
|
||||||
|
expect_change: true
|
||||||
|
expected_password_lifetime: "10"
|
||||||
|
expected_password_expired: "N"
|
||||||
|
|
||||||
|
# assert idempotency
|
||||||
|
- username: "{{ user_name_1 }}"
|
||||||
|
host: "%"
|
||||||
|
password_expire: never
|
||||||
|
expect_change: false
|
||||||
|
expected_password_lifetime: "0"
|
||||||
|
expected_password_expired: "N"
|
||||||
|
- username: "{{ user_name_2 }}"
|
||||||
|
password_expire: default
|
||||||
|
expect_change: false
|
||||||
|
expected_password_lifetime: "-1"
|
||||||
|
expected_password_expired: "N"
|
||||||
|
- username: "{{ user_name_3 }}"
|
||||||
|
password_expire: interval
|
||||||
|
password_expire_interval: "10"
|
||||||
|
expect_change: false
|
||||||
|
expected_password_lifetime: "10"
|
||||||
|
expected_password_expired: "N"
|
||||||
|
|
||||||
|
# assert change is made
|
||||||
|
- username: "{{ user_name_3 }}"
|
||||||
|
password_expire: never
|
||||||
|
expect_change: true
|
||||||
|
expected_password_lifetime: "0"
|
||||||
|
expected_password_expired: "N"
|
||||||
|
- username: "{{ user_name_1 }}"
|
||||||
|
host: "%"
|
||||||
|
password_expire: default
|
||||||
|
expect_change: true
|
||||||
|
expected_password_lifetime: "-1"
|
||||||
|
expected_password_expired: "N"
|
||||||
|
- username: "{{ user_name_2 }}"
|
||||||
|
password_expire: interval
|
||||||
|
password_expire_interval: "100"
|
||||||
|
expect_change: true
|
||||||
|
expected_password_lifetime: "100"
|
||||||
|
expected_password_expired: "N"
|
||||||
|
|
||||||
|
# assert password expires now
|
||||||
|
- username: "{{ user_name_1 }}"
|
||||||
|
host: "%"
|
||||||
|
password_expire: now
|
||||||
|
expect_change: true
|
||||||
|
expected_password_lifetime: "-1" # password lifetime should be the same
|
||||||
|
expected_password_expired: "Y"
|
||||||
|
- username: "{{ user_name_2 }}"
|
||||||
|
password_expire: now
|
||||||
|
expect_change: true
|
||||||
|
expected_password_lifetime: "100" # password lifetime should be the same
|
||||||
|
expected_password_expired: "Y"
|
||||||
|
|
||||||
|
# assert idempotency password expires now
|
||||||
|
- username: "{{ user_name_1 }}"
|
||||||
|
host: "%"
|
||||||
|
password_expire: now
|
||||||
|
expect_change: false
|
||||||
|
expected_password_lifetime: "-1" # password lifetime should be the same
|
||||||
|
expected_password_expired: "Y"
|
||||||
|
- username: "{{ user_name_2 }}"
|
||||||
|
password_expire: now
|
||||||
|
expect_change: false
|
||||||
|
expected_password_lifetime: "100" # password lifetime should be the same
|
||||||
|
expected_password_expired: "Y"
|
||||||
|
|
||||||
|
# assert check_mode
|
||||||
|
- username: "{{ user_name_3 }}"
|
||||||
|
password_expire: interval
|
||||||
|
password_expire_interval: 10
|
||||||
|
check_mode: true
|
||||||
|
expect_change: false
|
||||||
|
expected_password_lifetime: "0"
|
||||||
|
expected_password_expired: "N"
|
||||||
|
|
||||||
|
- name: password_expire | Set password_expire = interval without password_expire_interval
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: '{{ user_name_4 }}'
|
||||||
|
host: '%'
|
||||||
|
password: '{{ user_password_4 }}'
|
||||||
|
password_expire: interval
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: password_expire | Assert that action fails if 'password_expire_interval' not set
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
|
||||||
|
- name: password_expire | Set password_expire_interval < 1
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: '{{ user_name_4 }}'
|
||||||
|
host: '%'
|
||||||
|
password: '{{ user_password_4 }}'
|
||||||
|
password_expire: interval
|
||||||
|
password_expire_interval: -1
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: password_expire | Assert that action fails if 'password_expire_interval' is < 1
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
- "'should be positive number' in result.msg"
|
||||||
|
|
||||||
|
- name: password_expire | check mode for user creation
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: '{{ user_name_4 }}'
|
||||||
|
host: '%'
|
||||||
|
password: '{{ user_password_4 }}'
|
||||||
|
password_expire: interval
|
||||||
|
password_expire_interval: 20
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
check_mode: True
|
||||||
|
failed_when: result is changed
|
||||||
|
|
||||||
|
- include_tasks: utils/remove_user.yml
|
||||||
|
vars:
|
||||||
|
user_name: "{{ item.username }}"
|
||||||
|
loop:
|
||||||
|
- username: "{{ user_name_1 }}"
|
||||||
|
- username: "{{ user_name_2 }}"
|
||||||
|
- username: "{{ user_name_3 }}"
|
||||||
|
- username: "{{ user_name_4 }}"
|
|
@ -0,0 +1,56 @@
|
||||||
|
---
|
||||||
|
- name: Utils | Assert user password_expire | Create modify {{ username }} with password_expire
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
login_user: "{{ mysql_parameters.login_user }}"
|
||||||
|
login_password: "{{ mysql_parameters.login_password }}"
|
||||||
|
login_host: "{{ mysql_parameters.login_host }}"
|
||||||
|
login_port: "{{ mysql_parameters.login_port }}"
|
||||||
|
state: present
|
||||||
|
name: "{{ username }}"
|
||||||
|
host: "{{ host }}"
|
||||||
|
password: "{{ password }}"
|
||||||
|
password_expire: "{{ password_expire }}"
|
||||||
|
password_expire_interval: "{{ password_expire_interval | default(omit) }}"
|
||||||
|
register: result
|
||||||
|
check_mode: "{{ check_mode | default(false) }}"
|
||||||
|
failed_when: result.changed != expect_change_value
|
||||||
|
vars:
|
||||||
|
expect_change_value: "{{ expect_change }}"
|
||||||
|
|
||||||
|
- name: Utils | Assert user password_lifetime | Query user '{{ username }}'
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: >
|
||||||
|
{{ mysql_command }} -BNe "SELECT IFNULL(password_lifetime, -1)
|
||||||
|
FROM mysql.user where user='{{ username }}' and host='{{ host }}'"
|
||||||
|
register: password_lifetime
|
||||||
|
when:
|
||||||
|
- db_engine == 'mysql'
|
||||||
|
- db_version is version('5.7.0', '>=')
|
||||||
|
failed_when: expected_password_lifetime_value not in password_lifetime.stdout_lines
|
||||||
|
vars:
|
||||||
|
expected_password_lifetime_value: "{{ expected_password_lifetime }}"
|
||||||
|
|
||||||
|
- name: Utils | Assert user password_lifetime | Query user '{{ username }}'
|
||||||
|
ansible.builtin.command:
|
||||||
|
"{{ mysql_command }} -BNe \"SELECT JSON_EXTRACT(Priv, '$.password_lifetime') AS password_lifetime \
|
||||||
|
FROM mysql.global_priv \
|
||||||
|
WHERE user='{{ username }}' and host='{{ host }}'\""
|
||||||
|
register: password_lifetime
|
||||||
|
when:
|
||||||
|
- db_engine == 'mariadb'
|
||||||
|
- db_version is version('10.4.3', '>=')
|
||||||
|
failed_when: expected_password_lifetime_value not in password_lifetime.stdout_lines
|
||||||
|
vars:
|
||||||
|
expected_password_lifetime_value: "{{ expected_password_lifetime }}"
|
||||||
|
|
||||||
|
- name: Utils | Assert user password_expired | Query user '{{ username }}'
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: >
|
||||||
|
{{ mysql_command }} -BNe "SELECT password_expired FROM mysql.user
|
||||||
|
WHERE user='{{ username }}' and host='{{ host }}'"
|
||||||
|
register: password_expired
|
||||||
|
when: (db_engine == 'mysql' and db_version is version('5.7.0', '>=')) or
|
||||||
|
(db_engine == 'mariadb' and db_version is version('10.4.3', '>='))
|
||||||
|
failed_when: expected_password_expired_value not in password_expired.stdout_lines
|
||||||
|
vars:
|
||||||
|
expected_password_expired_value: "{{ expected_password_expired }}"
|
Loading…
Add table
Reference in a new issue