# test code for the mysql_user module # (c) 2014, Wayne Rosario # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 dof the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . # ============================================================ # create mysql user and verify user is added to mysql database # - name: alias mysql command to include default options set_fact: mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp" - 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: - include: create_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} - include: resource_limits.yml - include: assert_user.yml user_name={{user_name_1}} - include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} - include: assert_no_user.yml user_name={{user_name_1}} # ============================================================ # Create mysql user that already exist on mysql database # - include: create_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} - name: create mysql user that already exist (expect changed=false) mysql_user: <<: *mysql_params name: '{{user_name_1}}' password: '{{user_password_1}}' state: present register: result - name: assert output message mysql user was not created assert: { that: "result.changed == false" } # ============================================================ # remove mysql user and verify user is removed from mysql database # - name: remove mysql user state=absent (expect changed=true) mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' password: '{{ user_password_1 }}' state: absent register: result - name: assert output message mysql user was removed assert: that: - "result.changed == true" - include: assert_no_user.yml user_name={{user_name_1}} # ============================================================ # remove mysql user that does not exist on mysql database # - name: remove mysql user that does not exist state=absent (expect changed=false) mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' password: '{{ user_password_1 }}' state: absent register: result - name: assert output message mysql user that does not exist assert: that: - "result.changed == false" - include: assert_no_user.yml user_name={{user_name_1}} # ============================================================ # Create user with no privileges and verify default privileges are assign # - name: create user with select privilege state=present (expect changed=true) mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' password: '{{ user_password_1 }}' state: present register: result - include: assert_user.yml user_name={{user_name_1}} priv=USAGE - include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} - include: assert_no_user.yml user_name={{user_name_1}} # ============================================================ # Create user with select privileges and verify select privileges are assign # - name: create user with select privilege state=present (expect changed=true) mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' password: '{{ user_password_2 }}' state: present priv: '*.*:SELECT' register: result - include: assert_user.yml user_name={{user_name_2}} priv=SELECT - include: remove_user.yml user_name={{user_name_2}} user_password={{ user_password_2 }} - include: assert_no_user.yml user_name={{user_name_2}} # ============================================================ # Create users with TLS requirements and verify requirements are assigned # - name: find out the database version mysql_info: <<: *mysql_params filter: version register: db_version - name: create user with TLS requirements in check mode (expect changed=true) mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" password: "{{ user_password_1 }}" tls_requires: SSL: check_mode: yes register: result - name: Assert check mode user create reports changed state assert: that: - result is changed - include: assert_no_user.yml user_name={{user_name_1}} - name: create user with TLS requirements state=present (expect changed=true) mysql_user: <<: *mysql_params name: '{{ item[0] }}' password: '{{ user_password_1 }}' tls_requires: '{{ item[1] }}' with_together: - [ '{{ user_name_1 }}', '{{ user_name_2 }}', '{{ user_name_3 }}'] - - SSL: - X509: - subject: '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland' cipher: 'ECDHE-ECDSA-AES256-SHA384' issuer: '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland' - block: - name: retrieve TLS requiremets for users in old database version command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ item }}'@'localhost'\"" register: old_result with_items: ['{{ user_name_1 }}', '{{ user_name_2 }}', '{{ user_name_3 }}'] - name: set old database separator set_fact: separator: '\n' when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 - block: - name: retrieve TLS requiremets for users in new database version command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ item }}'@'localhost'\"" register: new_result with_items: ['{{ user_name_1 }}', '{{ user_name_2 }}', '{{ user_name_3 }}'] - name: set new database separator set_fact: separator: 'PASSWORD' when: db_version.version.major >= 5 and db_version.version.major < 10 and db_version.version.minor > 6 or db_version.version.major == 10 and db_version.version.minor >= 2 - block: - name: assert user1 TLS requirements assert: that: - "'SSL' in reqs" vars: - reqs: "{{((old_result.results[0] is skipped | ternary(new_result, old_result)).results | selectattr('item', 'contains', user_name_1) | first).stdout.split('REQUIRE')[1].split(separator)[0].strip()}}" - name: assert user2 TLS requirements assert: that: - "'X509' in reqs" vars: - reqs: "{{((old_result.results[0] is skipped | ternary(new_result, old_result)).results | selectattr('item', 'contains', user_name_2) | first).stdout.split('REQUIRE')[1].split(separator)[0].strip()}}" - name: assert user3 TLS requirements assert: that: - "'/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland' in (reqs | select('contains', 'SUBJECT') | first)" - "'/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland' in (reqs | select('contains', 'ISSUER') | first)" - "'ECDHE-ECDSA-AES256-SHA384' in (reqs | select('contains', 'CIPHER') | first)" vars: - reqs: "{{((old_result.results[0] is skipped | ternary(new_result, old_result)).results | selectattr('item', 'contains', user_name_3) | first).stdout.split('REQUIRE')[1].split(separator)[0].replace(\"' \", \"':\").split(\":\")}}" # CentOS 6 uses an older version of jinja that does not provide the selectattr filter. when: ansible_distribution != 'CentOS' or ansible_distribution_major_version != '6' - name: modify user with TLS requirements state=present in check mode (expect changed=true) mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' password: '{{ user_password_1 }}' tls_requires: X509: check_mode: yes register: result - name: Assert check mode user update reports changed state assert: that: - result is changed - name: retrieve TLS requiremets for users in old database version command: mysql -L -N -s -e "SHOW GRANTS for '{{ user_name_1 }}'@'localhost'" register: old_result when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 - name: retrieve TLS requiremets for users in new database version command: mysql -L -N -s -e "SHOW CREATE USER '{{ user_name_1 }}'@'localhost'" register: new_result when: db_version.version.major >= 5 and db_version.version.major < 10 and db_version.version.minor > 6 or db_version.version.major == 10 and db_version.version.minor >= 2 - name: assert user1 TLS requirements was not changed assert: that: "'SSL' in reqs" vars: - reqs: "{{(old_result is skipped | ternary(new_result, old_result)).stdout.split('REQUIRE')[1].split(separator)[0].strip()}}" - name: modify user with TLS requirements state=present (expect changed=true) mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' password: '{{ user_password_1 }}' tls_requires: X509: - name: retrieve TLS requiremets for users in old database version command: mysql -L -N -s -e "SHOW GRANTS for '{{ user_name_1 }}'@'localhost'" register: old_result when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 - name: retrieve TLS requiremets for users in new database version command: mysql -L -N -s -e "SHOW CREATE USER '{{ user_name_1 }}'@'localhost'" register: new_result when: db_version.version.major >= 5 and db_version.version.major < 10 and db_version.version.minor > 6 or db_version.version.major == 10 and db_version.version.minor >= 2 - name: assert user1 TLS requirements assert: that: "'X509' in reqs" vars: - reqs: "{{(old_result is skipped | ternary(new_result, old_result)).stdout.split('REQUIRE')[1].split(separator)[0].strip()}}" - include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} - include: remove_user.yml user_name={{user_name_2}} user_password={{ user_password_1 }} - include: remove_user.yml user_name={{user_name_3}} user_password={{ user_password_1 }} - include: assert_no_user.yml user_name={{user_name_1}} - include: assert_no_user.yml user_name={{user_name_2}} - include: assert_no_user.yml user_name={{user_name_3}} # ============================================================ # Assert user has access to multiple databases # - name: give users access to multiple databases mysql_user: <<: *mysql_params name: '{{ item[0] }}' priv: '{{ item[1] }}.*:ALL' append_privs: yes password: '{{ user_password_1 }}' with_nested: - [ '{{ user_name_1 }}', '{{ user_name_2 }}'] - "{{db_names}}" - name: show grants access for user1 on multiple database command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_1 }}'@'localhost'\"" register: result - name: assert grant access for user1 on multiple database assert: that: - "'{{ item }}' in result.stdout" with_items: "{{db_names}}" - name: show grants access for user2 on multiple database command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_2 }}'@'localhost'\"" register: result - name: assert grant access for user2 on multiple database assert: that: - "'{{ item }}' in result.stdout" with_items: "{{db_names}}" - include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} - include: remove_user.yml user_name={{user_name_2}} user_password={{ user_password_1 }} - name: give user access to database via wildcard mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' priv: '%db.*:SELECT' append_privs: yes password: '{{ user_password_1 }}' - name: show grants access for user1 on multiple database command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_1 }}'@'localhost'\"" register: result - name: assert grant access for user1 on multiple database assert: that: - "'%db' in result.stdout" - "'SELECT' in result.stdout" - name: change user access to database via wildcard mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' priv: '%db.*:INSERT' append_privs: yes password: '{{ user_password_1 }}' - name: show grants access for user1 on multiple database command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_1 }}'@'localhost'\"" register: result - name: assert grant access for user1 on multiple database assert: that: - "'%db' in result.stdout" - "'INSERT' in result.stdout" - include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} # ============================================================ # Update user password for a user. # Assert the user password is updated and old password can no longer be used. # #- include: user_password_update_test.yml # ============================================================ # Assert create user with SELECT privileges, attempt to create database and update privileges to create database # - include: test_privs.yml current_privilege=SELECT current_append_privs=no # ============================================================ # Assert creating user with SELECT privileges, attempt to create database and append privileges to create database # - include: test_privs.yml current_privilege=DROP current_append_privs=yes # ============================================================ # Assert create user with SELECT privileges, attempt to create database and update privileges to create database # - include: test_privs.yml current_privilege='UPDATE,ALTER' current_append_privs=no # ============================================================ # Assert creating user with SELECT privileges, attempt to create database and append privileges to create database # - include: test_privs.yml current_privilege='INSERT,DELETE' current_append_privs=yes # Tests for the priv parameter with dict value (https://github.com/ansible/ansible/issues/57533) - include: test_priv_dict.yml - import_tasks: issue-29511.yaml tags: - issue-29511 - import_tasks: issue-64560.yaml tags: - issue-64560