Skip to content

Commit

Permalink
mysql_user: fix parsing privs when a user has roles assigned to it (#341
Browse files Browse the repository at this point in the history
)

* mysql_user: fix parsing errors when a user has roles assigned

* Add a changelog fragment

* Fix a typo

* Fix CI
  • Loading branch information
Andersson007 authored May 12, 2022
1 parent ba4fea6 commit 8d114c7
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/tests/output/
/changelogs/.plugin-cache.yaml
*.swp

# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bugfixes:
- mysql_user - fix parsing privs when a user has roles assigned (https://github.com/ansible-collections/community.mysql/issues/231).
11 changes: 11 additions & 0 deletions plugins/module_utils/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,19 @@ def pick(x):
res = re.match("""GRANT (.+) ON (.+) TO (['`"]).*\\3@(['`"]).*\\4( IDENTIFIED BY PASSWORD (['`"]).+\\6)? ?(.*)""", grant[0])
else:
res = re.match("""GRANT (.+) ON (.+) TO (['`"]).*\\3""", grant[0])

if res is None:
# If a user has roles assigned, we'll have one of priv tuples looking like
# GRANT `admin`@`%` TO `user1`@`localhost`
# which will result None as res value.
# As we use the mysql_role module to manipulate roles
# we just ignore such privs below:
res = re.match("""GRANT (.+) TO (['`"]).*""", grant[0])
if not maria_role and res:
continue

raise InvalidPrivsError('unable to parse the MySQL grant string: %s' % grant[0])

privileges = res.group(1).split(",")
privileges = [pick(x.strip()) for x in privileges]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1540,3 +1540,24 @@
- '{{ test_db }}'
- '{{ test_db1 }}'
- '{{ test_db2 }}'

- name: Drop users
<<: *task_params
mysql_user:
<<: *mysql_params
name: '{{ item }}'
state: absent
loop:
- '{{ user0 }}'
- '{{ user1 }}'
- '{{ user2 }}'

- name: Drop roles
<<: *task_params
mysql_role:
<<: *mysql_params
name: '{{ item }}'
state: absent
loop:
- '{{ role0 }}'
- test
3 changes: 3 additions & 0 deletions tests/integration/targets/test_mysql_user/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,6 @@
# Test that mysql_user still works with force_context enabled (database set to "mysql")
# (https://github.com/ansible-collections/community.mysql/issues/265)
- include: issue-265.yml

# https://github.com/ansible-collections/community.mysql/issues/231
- include: test_user_grants_with_roles_applied.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# https://github.com/ansible-collections/community.mysql/issues/231
- vars:
mysql_parameters: &mysql_params
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'

block:
- name: Get server version
mysql_info:
<<: *mysql_params
register: srv

# Skip unsupported versions
- meta: end_play
when: srv['version']['major'] < 8

- name: Create test databases
mysql_db:
<<: *mysql_params
name: '{{ item }}'
state: present
loop:
- data1
- data2

- name: Create user with privileges
mysql_user:
<<: *mysql_params
name: '{{ user_name_3 }}'
password: '{{ user_password_3 }}'
priv:
"data1.*": "SELECT"
"data2.*": "SELECT"
state: present

- name: Run command to show privileges for user (expect privileges in stdout)
command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_3 }}'@'localhost'\""
register: result

- name: Assert user has giving privileges
assert:
that:
- "'GRANT SELECT ON `data1`.*' in result.stdout"
- "'GRANT SELECT ON `data2`.*' in result.stdout"

- name: Create role
mysql_role:
<<: *mysql_params
name: test231
members:
- '{{ user_name_3 }}@localhost'

- name: Try to change privs
mysql_user:
<<: *mysql_params
name: '{{ user_name_3 }}'
priv:
"data1.*": "INSERT"
"data2.*": "INSERT"
state: present

- name: Run command to show privileges for user (expect privileges in stdout)
command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_3 }}'@'localhost'\""
register: result

- name: Assert user has giving privileges
assert:
that:
- "'GRANT INSERT ON `data1`.*' in result.stdout"
- "'GRANT INSERT ON `data2`.*' in result.stdout"

##########
# Clean up
- name: Drop test databases
mysql_db:
<<: *mysql_params
name: '{{ item }}'
state: present
loop:
- data1
- data2

- name: Drop test user
mysql_user:
<<: *mysql_params
name: '{{ user_name_3 }}'
state: absent

- name: Drop test role
mysql_role:
<<: *mysql_params
name: test231
state: absent

0 comments on commit 8d114c7

Please sign in to comment.