# Test code for the user module. # (c) 2017, James Tanner # 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: get the jinja2 version shell: python -c 'import jinja2; print(jinja2.__version__)' register: jinja2_version delegate_to: localhost changed_when: no - debug: msg: "Jinja version: {{ jinja2_version.stdout }}, Python version: {{ ansible_python_version }}" ## user add - name: remove the test user user: name: ansibulluser state: absent - name: try to create a user user: name: ansibulluser state: present register: user_test0_0 - name: create the user again user: name: ansibulluser state: present register: user_test0_1 - debug: var: user_test0 verbosity: 2 - name: make a list of users script: userlist.sh {{ ansible_distribution }} register: user_names - debug: var: user_names verbosity: 2 - name: validate results for testcase 0 assert: that: - user_test0_0 is changed - user_test0_1 is not changed - '"ansibulluser" in user_names.stdout_lines' # test user add with password - name: add an encrypted password for user user: name: ansibulluser password: "$6$rounds=656000$TT4O7jz2M57npccl$33LF6FcUMSW11qrESXL1HX0BS.bsiT6aenFLLiVpsQh6hDtI9pJh5iY7x8J7ePkN4fP8hmElidHXaeD51pbGS." state: present update_password: always register: test_user_encrypt0 - name: there should not be warnings assert: that: "'warnings' not in test_user_encrypt0" - block: - name: add an plaintext password for user user: name: ansibulluser password: "plaintextpassword" state: present update_password: always register: test_user_encrypt1 - name: there should be a warning complains that the password is plaintext assert: that: "'warnings' in test_user_encrypt1" - name: add an invalid hashed password user: name: ansibulluser password: "$6$rounds=656000$tgK3gYTyRLUmhyv2$lAFrYUQwn7E6VsjPOwQwoSx30lmpiU9r/E0Al7tzKrR9mkodcMEZGe9OXD0H/clOn6qdsUnaL4zefy5fG+++++" state: present update_password: always register: test_user_encrypt2 - name: there should be a warning complains about the character set of password assert: that: "'warnings' in test_user_encrypt2" when: ansible_system != 'Darwin' # https://github.com/ansible/ansible/issues/42484 # Skipping macOS for now since there is a bug when changing home directory - block: - name: create user specifying home user: name: ansibulluser state: present home: "{{ user_home_prefix[ansible_system] }}/ansibulluser" register: user_test3_0 - name: create user again specifying home user: name: ansibulluser state: present home: "{{ user_home_prefix[ansible_system] }}/ansibulluser" register: user_test3_1 - name: change user home user: name: ansibulluser state: present home: "{{ user_home_prefix[ansible_system] }}/ansibulluser-mod" register: user_test3_2 - name: change user home back user: name: ansibulluser state: present home: "{{ user_home_prefix[ansible_system] }}/ansibulluser" register: user_test3_3 - name: validate results for testcase 3 assert: that: - user_test3_0 is not changed - user_test3_1 is not changed - user_test3_2 is changed - user_test3_3 is changed when: ansible_system != 'Darwin' ## user check - name: run existing user check tests user: name: "{{ user_names.stdout_lines | random }}" state: present create_home: no loop: "{{ range(1, 5+1) | list }}" register: user_test1 - debug: var: user_test1 verbosity: 2 - name: validate results for testcase 1 assert: that: - user_test1.results is defined - user_test1.results | length == 5 - name: validate changed results for testcase 1 (jinja >= 2.6) assert: that: - user_test1.results | map(attribute='changed') | unique | list == [False] - user_test1.results | map(attribute='state') | unique | list == ['present'] when: jinja2_version.stdout is version('2.6', '>=') - name: validate changed results for testcase 1 (jinja < 2.6) assert: that: - "user_test1.results[0] is not changed" - "user_test1.results[1] is not changed" - "user_test1.results[2] is not changed" - "user_test1.results[3] is not changed" - "user_test1.results[4] is not changed" - "user_test1.results[0]['state'] == 'present'" - "user_test1.results[1]['state'] == 'present'" - "user_test1.results[2]['state'] == 'present'" - "user_test1.results[3]['state'] == 'present'" - "user_test1.results[4]['state'] == 'present'" when: jinja2_version.stdout is version('2.6', '<') ## user remove - name: try to delete the user user: name: ansibulluser state: absent force: true register: user_test2 - name: make a new list of users script: userlist.sh {{ ansible_distribution }} register: user_names2 - debug: var: user_names2 verbosity: 2 - name: validate results for testcase 2 assert: that: - '"ansibulluser" not in user_names2.stdout_lines' - block: - name: create non-system user on macOS to test the shell is set to /bin/bash user: name: macosuser register: macosuser_output - name: validate the shell is set to /bin/bash assert: that: - 'macosuser_output.shell == "/bin/bash"' - name: cleanup user: name: macosuser state: absent - name: create system user on macos to test the shell is set to /usr/bin/false user: name: macosuser system: yes register: macosuser_output - name: validate the shell is set to /usr/bin/false assert: that: - 'macosuser_output.shell == "/usr/bin/false"' - name: cleanup user: name: macosuser state: absent - name: create non-system user on macos and set the shell to /bin/sh user: name: macosuser shell: /bin/sh register: macosuser_output - name: validate the shell is set to /bin/sh assert: that: - 'macosuser_output.shell == "/bin/sh"' - name: cleanup user: name: macosuser state: absent when: ansible_distribution == "MacOSX" ## user expires # Date is March 3, 2050 - name: Create user with expiration user: name: ansibulluser state: present expires: 2529881062 register: user_test_expires1 - name: Create user with expiration again to ensure no change is made user: name: ansibulluser state: present expires: 2529881062 register: user_test_expires2 - name: Ensure that account with expiration was created and did not change on subsequent run assert: that: - user_test_expires1 is changed - user_test_expires2 is not changed - name: Verify expiration date for Linux block: - name: LINUX | Get expiration date for ansibulluser getent: database: shadow key: ansibulluser - name: LINUX | Ensure proper expiration date was set assert: that: - getent_shadow['ansibulluser'][6] == '29281' when: ansible_os_family in ['RedHat', 'Debian', 'Suse'] - name: Verify expiration date for BSD block: - name: BSD | Get expiration date for ansibulluser shell: 'grep ansibulluser /etc/master.passwd | cut -d: -f 7' changed_when: no register: bsd_account_expiration - name: BSD | Ensure proper expiration date was set assert: that: - bsd_account_expiration.stdout == '2529878400' when: ansible_os_family == 'FreeBSD' - name: Change timezone timezone: name: America/Denver register: original_timezone - name: Change system timezone to make sure expiration comparison works properly block: - name: Create user with expiration again to ensure no change is made in a new timezone user: name: ansibulluser state: present expires: 2529881062 register: user_test_different_tz - name: Ensure that no change was reported assert: that: - user_test_different_tz is not changed always: - name: Restore original timezone - {{ original_timezone.diff.before.name }} timezone: name: "{{ original_timezone.diff.before.name }}" - name: Unexpire user user: name: ansibulluser state: present expires: -1 register: user_test_expires3 - name: Verify un expiration date for Linux block: - name: LINUX | Get expiration date for ansibulluser getent: database: shadow key: ansibulluser - name: LINUX | Ensure proper expiration date was set assert: msg: "expiry is supposed to be empty or -1, not {{getent_shadow['ansibulluser'][6]}}" that: - not getent_shadow['ansibulluser'][6] or getent_shadow['ansibulluser'][6] < 0 when: ansible_os_family in ['RedHat', 'Debian', 'Suse'] - name: Verify un expiration date for linux/BSD block: - name: Unexpire user again to check for change user: name: ansibulluser state: present expires: -1 register: user_test_expires4 - name: Ensure first expiration reported a change and second did not assert: msg: The second run of the expiration removal task reported a change when it should not that: - user_test_expires3 is changed - user_test_expires4 is not changed when: ansible_os_family in ['RedHat', 'Debian', 'Suse', 'FreeBSD'] - name: Verify un expiration date for BSD block: - name: BSD | Get expiration date for ansibulluser shell: 'grep ansibulluser /etc/master.passwd | cut -d: -f 7' changed_when: no register: bsd_account_expiration - name: BSD | Ensure proper expiration date was set assert: msg: "expiry is supposed to be '0', not {{bsd_account_expiration.stdout}}" that: - bsd_account_expiration.stdout == '0' when: ansible_os_family == 'FreeBSD' ## shadow backup - block: - name: Create a user to test shadow file backup user: name: ansibulluser state: present register: result - name: Find shadow backup files find: path: /etc patterns: 'shadow\..*~$' use_regex: yes register: shadow_backups - name: Assert that a backup file was created assert: that: - result.bakup - shadow_backups.files | map(attribute='path') | list | length > 0 when: ansible_os_family == 'Solaris'