diff --git a/.gitignore b/.gitignore index f4407229..6bbe85a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /tests/output/ /changelogs/.plugin-cache.yaml +*.swp # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/changelogs/fragments/001-mysql_user_fix_pars_users_with_roles_assigned.yml b/changelogs/fragments/001-mysql_user_fix_pars_users_with_roles_assigned.yml new file mode 100644 index 00000000..121bc467 --- /dev/null +++ b/changelogs/fragments/001-mysql_user_fix_pars_users_with_roles_assigned.yml @@ -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). diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index 89cbdd8b..2fb76fdd 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -750,8 +750,19 @@ def pick(x): for grant in grants: res = re.match("""GRANT (.+) ON (.+) TO (['`"]).*\\3@(['`"]).*\\4( IDENTIFIED BY PASSWORD (['`"]).+\\6)? ?(.*)""", 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 (community.mysql 2.0.0+) to manipulate roles + # we just ignore such privs below: + res = re.match("""GRANT (.+) TO (['`"]).*""", grant[0]) + if 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] diff --git a/tests/integration/targets/test_mysql_user/tasks/main.yml b/tests/integration/targets/test_mysql_user/tasks/main.yml index 93cb12dd..9b6caf34 100644 --- a/tests/integration/targets/test_mysql_user/tasks/main.yml +++ b/tests/integration/targets/test_mysql_user/tasks/main.yml @@ -282,3 +282,6 @@ - import_tasks: issue-64560.yaml tags: - issue-64560 + + # https://github.com/ansible-collections/community.mysql/issues/231 + - include: test_user_grants_with_roles_applied.yml diff --git a/tests/integration/targets/test_mysql_user/tasks/test_user_grants_with_roles_applied.yml b/tests/integration/targets/test_mysql_user/tasks/test_user_grants_with_roles_applied.yml new file mode 100644 index 00000000..7af38904 --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/test_user_grants_with_roles_applied.yml @@ -0,0 +1,98 @@ +# 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_query: + <<: *mysql_params + query: CREATE ROLE IF NOT EXISTS test231 + + + - name: Grant role + mysql_query: + <<: *mysql_params + query: 'GRANT test231 TO {{ 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_query: + <<: *mysql_params + query: DROP ROLE IF EXISTS test231