From eaf4571e4257fa21a4883f2028dd18e231e89ad7 Mon Sep 17 00:00:00 2001 From: Wayne Rosario Date: Mon, 21 Jul 2014 10:37:05 -0400 Subject: [PATCH] Adding the following Test Coverage: Use mysql_user module to create, delete users. Update user password and ensure new password was updated for the correct user. Assert user has access to multiple databases Assert user creation, deleting using different user privilege and ensure privilege work correctly. --- library/database/mysql_user | 3 +- test/integration/destructive.yml | 1 + .../roles/test_mysql_user/defaults/main.yml | 16 ++ .../roles/test_mysql_user/meta/main.yml | 2 + .../test_mysql_user/tasks/assert_no_user.yml | 25 +++ .../test_mysql_user/tasks/assert_user.yml | 34 ++++ .../test_mysql_user/tasks/create_user.yml | 25 +++ .../roles/test_mysql_user/tasks/main.yml | 152 ++++++++++++++++++ .../test_mysql_user/tasks/remove_user.yml | 25 +++ .../test_mysql_user/tasks/test_privs.yml | 73 +++++++++ .../tasks/user_password_update_test.yml | 84 ++++++++++ 11 files changed, 439 insertions(+), 1 deletion(-) create mode 100644 test/integration/roles/test_mysql_user/defaults/main.yml create mode 100644 test/integration/roles/test_mysql_user/meta/main.yml create mode 100644 test/integration/roles/test_mysql_user/tasks/assert_no_user.yml create mode 100644 test/integration/roles/test_mysql_user/tasks/assert_user.yml create mode 100644 test/integration/roles/test_mysql_user/tasks/create_user.yml create mode 100644 test/integration/roles/test_mysql_user/tasks/main.yml create mode 100644 test/integration/roles/test_mysql_user/tasks/remove_user.yml create mode 100644 test/integration/roles/test_mysql_user/tasks/test_privs.yml create mode 100644 test/integration/roles/test_mysql_user/tasks/user_password_update_test.yml diff --git a/library/database/mysql_user b/library/database/mysql_user index db4b334716..aaec05f99f 100644 --- a/library/database/mysql_user +++ b/library/database/mysql_user @@ -209,7 +209,8 @@ def user_mod(cursor, user, host, password, new_priv, append_privs): for db_table in db_table_intersect: priv_diff = set(new_priv[db_table]) ^ set(curr_priv[db_table]) if (len(priv_diff) > 0): - privileges_revoke(cursor, user,host,db_table,grant_option) + if not append_privs: + privileges_revoke(cursor, user,host,db_table,grant_option) privileges_grant(cursor, user,host,db_table,new_priv[db_table]) changed = True diff --git a/test/integration/destructive.yml b/test/integration/destructive.yml index ae6041be9b..29f6541510 100644 --- a/test/integration/destructive.yml +++ b/test/integration/destructive.yml @@ -8,3 +8,4 @@ - { role: test_apt, tags: test_apt } - { role: test_apt_repository, tags: test_apt_repository } - { role: test_mysql_db, tags: test_mysql_db} + - { role: test_mysql_user, tags: test_mysql_user} diff --git a/test/integration/roles/test_mysql_user/defaults/main.yml b/test/integration/roles/test_mysql_user/defaults/main.yml new file mode 100644 index 0000000000..ff7503f8f0 --- /dev/null +++ b/test/integration/roles/test_mysql_user/defaults/main.yml @@ -0,0 +1,16 @@ +--- +# defaults file for test_mysql_user +db_name: 'data' +user_name_1: 'db_user1' +user_name_2: 'db_user2' + +user_password_1: '12345' +user_password_2: '98765' + +db_names: + - clientdb + - employeedb + - providerdb + +tmp_dir: '/tmp' + diff --git a/test/integration/roles/test_mysql_user/meta/main.yml b/test/integration/roles/test_mysql_user/meta/main.yml new file mode 100644 index 0000000000..4aa170dc06 --- /dev/null +++ b/test/integration/roles/test_mysql_user/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_mysql_db diff --git a/test/integration/roles/test_mysql_user/tasks/assert_no_user.yml b/test/integration/roles/test_mysql_user/tasks/assert_no_user.yml new file mode 100644 index 0000000000..4d4a411fe2 --- /dev/null +++ b/test/integration/roles/test_mysql_user/tasks/assert_no_user.yml @@ -0,0 +1,25 @@ +# test code to assert no mysql user +# (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 of 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 . + +# ============================================================ +- name: run command to query for mysql user + command: mysql "-e SELECT User FROM mysql.user where user='{{ user_name }}';" + register: result + +- name: assert mysql user is not present + assert: { that: "'{{ user_name }}' not in result.stdout" } diff --git a/test/integration/roles/test_mysql_user/tasks/assert_user.yml b/test/integration/roles/test_mysql_user/tasks/assert_user.yml new file mode 100644 index 0000000000..7b35a1f350 --- /dev/null +++ b/test/integration/roles/test_mysql_user/tasks/assert_user.yml @@ -0,0 +1,34 @@ +# test code to assert mysql user +# (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 of 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 . + +# ============================================================ +- name: run command to query for mysql user + command: mysql "-e SELECT User FROM mysql.user where user='{{ user_name }}';" + register: result + +- name: assert mysql user is present + assert: { that: "'{{ user_name }}' in result.stdout" } + +- name: run command to show privileges for user (expect privileges in stdout) + command: mysql "-e SHOW GRANTS FOR '{{ user_name }}'@'localhost';" + register: result + when: priv is defined + +- name: assert user has giving privileges + assert: { that: "'GRANT {{priv}} ON *.*' in result.stdout" } + when: priv is defined diff --git a/test/integration/roles/test_mysql_user/tasks/create_user.yml b/test/integration/roles/test_mysql_user/tasks/create_user.yml new file mode 100644 index 0000000000..6122098e1e --- /dev/null +++ b/test/integration/roles/test_mysql_user/tasks/create_user.yml @@ -0,0 +1,25 @@ +# test code to create mysql user +# (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 of 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 . + +# ============================================================ +- name: create mysql user {{user_name}} + mysql_user: name={{user_name}} password={{user_password}} state=present + register: result + +- name: assert output message mysql user was created {{state}} + assert: { that: "result.changed == true" } diff --git a/test/integration/roles/test_mysql_user/tasks/main.yml b/test/integration/roles/test_mysql_user/tasks/main.yml new file mode 100644 index 0000000000..7ad42d471b --- /dev/null +++ b/test/integration/roles/test_mysql_user/tasks/main.yml @@ -0,0 +1,152 @@ +# 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 +# +- include: create_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} + +- 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: 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: 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: 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: 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: 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}} + +# ============================================================ +# Assert user has access to multiple databases +# +- name: give users access to multiple databases + mysql_user: 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 "-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 "-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 }} + +# ============================================================ +# 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, attemp 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, attemp 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, attemp 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, attemp to create database and append privileges to create database +# +- include: test_privs.yml current_privilege='INSERT,DELETE' current_append_privs=yes + + + + + + + diff --git a/test/integration/roles/test_mysql_user/tasks/remove_user.yml b/test/integration/roles/test_mysql_user/tasks/remove_user.yml new file mode 100644 index 0000000000..76eca35b87 --- /dev/null +++ b/test/integration/roles/test_mysql_user/tasks/remove_user.yml @@ -0,0 +1,25 @@ +# test code to remove mysql user +# (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 of 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 . + +# ============================================================ +- name: remove mysql user {{user_name}} + mysql_user: name={{user_name}} password={{user_password}} state=absent + register: result + +- name: assert output message mysql user was removed {{state}} + assert: { that: "result.changed == true" } diff --git a/test/integration/roles/test_mysql_user/tasks/test_privs.yml b/test/integration/roles/test_mysql_user/tasks/test_privs.yml new file mode 100644 index 0000000000..6bfc2d5d16 --- /dev/null +++ b/test/integration/roles/test_mysql_user/tasks/test_privs.yml @@ -0,0 +1,73 @@ +# test code for privileges for 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 of 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 . + +# ============================================================ +- name: create user with basic select privileges + mysql_user: name={{ user_name_2 }} password={{ user_password_2 }} priv=*.*:SELECT state=present + when: current_append_privs == "yes" + +- include: assert_user.yml user_name={{user_name_2}} priv='SELECT' + when: current_append_privs == "yes" + +- name: create user with current privileges (expect changed=true) + mysql_user: name={{ user_name_2 }} password={{ user_password_2 }} priv=*.*:'{{current_privilege}}' append_privs={{current_append_privs}} state=present + register: result + +- name: assert output message for current privileges + assert: { that: "result.changed == true" } + +- name: run command to show privileges for user (expect privileges in stdout) + command: mysql "-e SHOW GRANTS FOR '{{user_name_2}}'@'localhost';" + register: result + +- name: assert user has correct privileges + assert: { that: "'GRANT {{current_privilege | replace(',', ', ')}} ON *.*' in result.stdout" } + when: current_append_privs == "no" + +- name: assert user has correct privileges + assert: { that: "'GRANT SELECT, {{current_privilege | replace(',', ', ')}} ON *.*' in result.stdout" } + when: current_append_privs == "yes" + +- name: create database using user current privileges + mysql_db: name={{ db_name }} state=present login_user={{ user_name_2 }} login_password={{ user_password_2 }} + ignore_errors: true + +- name: run command to test that database was not created + command: mysql "-e show databases like '{{ db_name }}';" + register: result + +- name: assert database was not created + assert: { that: "'{{ db_name }}' not in result.stdout" } + +- name: update user with all privileges + mysql_user: name={{ user_name_2 }} password={{ user_password_2 }} priv=*.*:ALL state=present + +- include: assert_user.yml user_name={{user_name_2}} priv='ALL PRIVILEGES' + +- name: create database using user + mysql_db: name={{ db_name }} state=present login_user={{ user_name_2 }} login_password={{ user_password_2 }} + register: result + +- name: run command to test database was created using user new privileges + command: mysql "-e SHOW CREATE DATABASE {{ db_name }};" + +- name: drop database using using user + mysql_db: name={{ db_name }} state=absent login_user={{ user_name_2 }} login_password={{ user_password_2 }} + +- name: remove username + mysql_user: name={{ user_name_2 }} password={{ user_password_2 }} state=absent diff --git a/test/integration/roles/test_mysql_user/tasks/user_password_update_test.yml b/test/integration/roles/test_mysql_user/tasks/user_password_update_test.yml new file mode 100644 index 0000000000..d342d0a4ac --- /dev/null +++ b/test/integration/roles/test_mysql_user/tasks/user_password_update_test.yml @@ -0,0 +1,84 @@ +# test code update password 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 . + +# ============================================================ +# Update user password for a user. +# Assert the user password is updated and old password can no longer be used. +# +- name: create user1 state=present with a password + mysql_user: name={{ user_name_1 }} password={{ user_password_1 }} priv=*.*:ALL state=present + +- name: create user2 state=present with a password + mysql_user: name={{ user_name_2 }} password={{ user_password_2 }} priv=*.*:ALL state=present + +- name: store user2 grants with old password + command: mysql "-e SHOW GRANTS FOR '{{ user_name_2 }}'@'localhost';" + register: user_password_old + +- name: update user2 state=present with same password (expect changed=false) + mysql_user: name={{ user_name_2 }} password={{ user_password_2 }} priv=*.*:ALL state=present + register: result + +- name: assert output user2 was not updated + assert: { that: "result.changed == false" } + +- include: assert_user.yml user_name={{user_name_2}} priv='ALL PRIVILEGES' + +- name: update user2 state=present with a new password (expect changed=true) + mysql_user: name={{ user_name_2 }} password={{ user_password_1 }} state=present + register: result + +- include: assert_user.yml user_name={{user_name_2}} priv='ALL PRIVILEGES' + +- name: store user2 grants with new password + command: mysql "-e SHOW GRANTS FOR '{{ user_name_2 }}'@'localhost';" + register: user_password_new + +- name: assert output message password was update for user2 + assert: { that: "user_password_old.stdout != user_password_new.stdout" } + +- name: create database using user2 and old password + mysql_db: name={{ db_name }} state=present login_user={{ user_name_2 }} login_password={{ user_password_2 }} + ignore_errors: true + register: result + +- name: assert output message that database not create with old password + assert: + that: + - "result.failed == true" + - "'check login_user and login_password are correct' in result.msg" + +- name: create database using user2 and new password + mysql_db: name={{ db_name }} state=present login_user={{ user_name_2 }} login_password={{ user_password_1 }} + register: result + +- name: assert output message that database is created with new password + assert: { that: "result.changed == true" } + +- name: remove database + mysql_db: name={{ db_name }} state=absent + +- 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 }} + + + + + +