mysql_user, mysql_role: add argument subtract_privs to revoke privileges explicitly (#333)

* add option subtract_privs to mysql_role and mysql_user

see https://github.com/ansible-collections/community.mysql/issues/331

* add integration tests for subtract_privs for mysql_role and mysql_user

* add changelog fragment for PR #333

* mysql_role, mysql_user: when subtract_privileges, don't grant unwanted privileges and don't revoke USAGE implicitly

* fix integration tests

* mysql_role, mysql_user: invalid privileges are ignored when subtract_privs is true -> document that and fix integration tests

* fix mysql_role integration tests

* fix mysql_role, mysql_user integration tests

* formatting

make the PEP8 check happy

* mysql_user and mysql_role: fix granting privileges when only the GRANT OPTION needs to be added

* mysql_user and mysql_role: log some updated privileges; explain integration test blind spot

* mysql_user and mysql_role: don't grant too much privileges

If only the grant option needs to be granted, at least one privilege needs to be granted to get valid syntax. USAGE is better for that than the existing privileges, because unwanted privileges would be re-added after revokation.

* mysql_user and mysql_role: fix type error

* Update changelogs/fragments/333-mysql_user-mysql_role-add-subtract_privileges-argument.yml

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/mysql_role.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/mysql_user.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

Co-authored-by: Felix Hamme <felix.hamme@ionos.com>
Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
This commit is contained in:
betanummeric 2022-05-09 09:50:49 +02:00 committed by GitHub
parent 1dcc5ec086
commit ba4fea67b1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 459 additions and 42 deletions

View file

@ -51,7 +51,16 @@ options:
append_privs:
description:
- Append the privileges defined by the I(priv) option to the existing ones
for this role instead of overwriting them.
for this role instead of overwriting them. Mutually exclusive with I(subtract_privs).
type: bool
default: no
subtract_privs:
description:
- Revoke the privileges defined by the I(priv) option and keep other existing privileges.
If set, invalid privileges in I(priv) are ignored.
Mutually exclusive with I(append_privs).
version_added: '3.2.0'
type: bool
default: no
@ -233,6 +242,14 @@ EXAMPLES = r'''
name: business
members:
- marketing
- name: Ensure the role foo does not have the DELETE privilege
community.mysql.mysql_role:
state: present
name: foo
subtract_privs: yes
priv:
'db1.*': DELETE
'''
RETURN = '''#'''
@ -821,9 +838,9 @@ class Role():
return True
def update(self, users, privs, check_mode=False,
append_privs=False, append_members=False,
detach_members=False, admin=False,
set_default_role_all=True):
append_privs=False, subtract_privs=False,
append_members=False, detach_members=False,
admin=False, set_default_role_all=True):
"""Update a role.
Update a role if needed.
@ -837,6 +854,8 @@ class Role():
check_mode (bool): If True, just checks and does nothing.
append_privs (bool): If True, adds new privileges passed through privs
not touching current privileges.
subtract_privs (bool): If True, revoke the privileges passed through privs
not touching other existing privileges.
append_members (bool): If True, adds new members passed through users
not touching current members.
detach_members (bool): If True, removes members passed through users from a role.
@ -861,7 +880,7 @@ class Role():
if privs:
changed, msg = user_mod(self.cursor, self.name, self.host,
None, None, None, None, None, None,
privs, append_privs, None,
privs, append_privs, subtract_privs, None,
self.module, role=True, maria_role=self.is_mariadb)
if admin:
@ -931,6 +950,7 @@ def main():
admin=dict(type='str'),
priv=dict(type='raw'),
append_privs=dict(type='bool', default=False),
subtract_privs=dict(type='bool', default=False),
members=dict(type='list', elements='str'),
append_members=dict(type='bool', default=False),
detach_members=dict(type='bool', default=False),
@ -945,6 +965,7 @@ def main():
('admin', 'members'),
('admin', 'append_members'),
('admin', 'detach_members'),
('append_privs', 'subtract_privs'),
),
)
@ -958,6 +979,7 @@ def main():
connect_timeout = module.params['connect_timeout']
config_file = module.params['config_file']
append_privs = module.params['append_privs']
subtract_privs = module.boolean(module.params['subtract_privs'])
members = module.params['members']
append_members = module.params['append_members']
detach_members = module.params['detach_members']
@ -1014,7 +1036,7 @@ def main():
module.fail_json(msg=to_native(e))
try:
priv = privileges_unpack(priv, mode)
priv = privileges_unpack(priv, mode, ensure_usage=not subtract_privs)
except Exception as e:
module.fail_json(msg='Invalid privileges string: %s' % to_native(e))
@ -1043,11 +1065,13 @@ def main():
try:
if state == 'present':
if not role.exists:
if subtract_privs:
priv = None # avoid granting unwanted privileges
changed = role.add(members, priv, module.check_mode, admin,
set_default_role_all)
else:
changed = role.update(members, priv, module.check_mode, append_privs,
changed = role.update(members, priv, module.check_mode, append_privs, subtract_privs,
append_members, detach_members, admin,
set_default_role_all)