summaryrefslogtreecommitdiffstats
path: root/test/integration/targets/user
diff options
context:
space:
mode:
Diffstat (limited to 'test/integration/targets/user')
-rw-r--r--test/integration/targets/user/aliases2
-rw-r--r--test/integration/targets/user/files/userlist.sh20
-rw-r--r--test/integration/targets/user/meta/main.yml2
-rw-r--r--test/integration/targets/user/tasks/main.yml42
-rw-r--r--test/integration/targets/user/tasks/test_create_system_user.yml12
-rw-r--r--test/integration/targets/user/tasks/test_create_user.yml67
-rw-r--r--test/integration/targets/user/tasks/test_create_user_home.yml136
-rw-r--r--test/integration/targets/user/tasks/test_create_user_password.yml90
-rw-r--r--test/integration/targets/user/tasks/test_create_user_uid.yml26
-rw-r--r--test/integration/targets/user/tasks/test_expires.yml147
-rw-r--r--test/integration/targets/user/tasks/test_expires_min_max.yml73
-rw-r--r--test/integration/targets/user/tasks/test_expires_new_account.yml55
-rw-r--r--test/integration/targets/user/tasks/test_expires_new_account_epoch_negative.yml112
-rw-r--r--test/integration/targets/user/tasks/test_local.yml196
-rw-r--r--test/integration/targets/user/tasks/test_local_expires.yml333
-rw-r--r--test/integration/targets/user/tasks/test_no_home_fallback.yml106
-rw-r--r--test/integration/targets/user/tasks/test_password_lock.yml140
-rw-r--r--test/integration/targets/user/tasks/test_password_lock_new_user.yml63
-rw-r--r--test/integration/targets/user/tasks/test_remove_user.yml19
-rw-r--r--test/integration/targets/user/tasks/test_shadow_backup.yml21
-rw-r--r--test/integration/targets/user/tasks/test_ssh_key_passphrase.yml30
-rw-r--r--test/integration/targets/user/tasks/test_umask.yml57
-rw-r--r--test/integration/targets/user/vars/main.yml13
23 files changed, 1762 insertions, 0 deletions
diff --git a/test/integration/targets/user/aliases b/test/integration/targets/user/aliases
new file mode 100644
index 0000000..a4c92ef
--- /dev/null
+++ b/test/integration/targets/user/aliases
@@ -0,0 +1,2 @@
+destructive
+shippable/posix/group1
diff --git a/test/integration/targets/user/files/userlist.sh b/test/integration/targets/user/files/userlist.sh
new file mode 100644
index 0000000..96a83b2
--- /dev/null
+++ b/test/integration/targets/user/files/userlist.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+#- name: make a list of groups
+# shell: |
+# cat /etc/group | cut -d: -f1
+# register: group_names
+# when: 'ansible_distribution != "MacOSX"'
+
+#- name: make a list of groups [mac]
+# shell: dscl localhost -list /Local/Default/Groups
+# register: group_names
+# when: 'ansible_distribution == "MacOSX"'
+
+DISTRO="$*"
+
+if [[ "$DISTRO" == "MacOSX" ]]; then
+ dscl localhost -list /Local/Default/Users
+else
+ grep -E -v ^\# /etc/passwd | cut -d: -f1
+fi
diff --git a/test/integration/targets/user/meta/main.yml b/test/integration/targets/user/meta/main.yml
new file mode 100644
index 0000000..07faa21
--- /dev/null
+++ b/test/integration/targets/user/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+ - prepare_tests
diff --git a/test/integration/targets/user/tasks/main.yml b/test/integration/targets/user/tasks/main.yml
new file mode 100644
index 0000000..9d36bfc
--- /dev/null
+++ b/test/integration/targets/user/tasks/main.yml
@@ -0,0 +1,42 @@
+# Test code for the user module.
+# (c) 2017, James Tanner <tanner.jc@gmail.com>
+
+# 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 <http://www.gnu.org/licenses/>.
+#
+
+- name: skip broken distros
+ meta: end_host
+ when: ansible_distribution == 'Alpine'
+
+- import_tasks: test_create_user.yml
+- import_tasks: test_create_system_user.yml
+- import_tasks: test_create_user_uid.yml
+- import_tasks: test_create_user_password.yml
+- import_tasks: test_create_user_home.yml
+- import_tasks: test_remove_user.yml
+- import_tasks: test_no_home_fallback.yml
+- import_tasks: test_expires.yml
+- import_tasks: test_expires_new_account.yml
+- import_tasks: test_expires_new_account_epoch_negative.yml
+- import_tasks: test_expires_min_max.yml
+- import_tasks: test_shadow_backup.yml
+- import_tasks: test_ssh_key_passphrase.yml
+- import_tasks: test_password_lock.yml
+- import_tasks: test_password_lock_new_user.yml
+- import_tasks: test_local.yml
+ when: not (ansible_distribution == 'openSUSE Leap' and ansible_distribution_version is version('15.4', '>='))
+- import_tasks: test_umask.yml
+ when: ansible_facts.system == 'Linux'
diff --git a/test/integration/targets/user/tasks/test_create_system_user.yml b/test/integration/targets/user/tasks/test_create_system_user.yml
new file mode 100644
index 0000000..da746c5
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_create_system_user.yml
@@ -0,0 +1,12 @@
+# create system user
+
+- name: remove user
+ user:
+ name: ansibulluser
+ state: absent
+
+- name: create system user
+ user:
+ name: ansibulluser
+ state: present
+ system: yes
diff --git a/test/integration/targets/user/tasks/test_create_user.yml b/test/integration/targets/user/tasks/test_create_user.yml
new file mode 100644
index 0000000..bced790
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_create_user.yml
@@ -0,0 +1,67 @@
+- 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_facts.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'
+
+- 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
+ 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'"
diff --git a/test/integration/targets/user/tasks/test_create_user_home.yml b/test/integration/targets/user/tasks/test_create_user_home.yml
new file mode 100644
index 0000000..1b529f7
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_create_user_home.yml
@@ -0,0 +1,136 @@
+# https://github.com/ansible/ansible/issues/42484
+# Skipping macOS for now since there is a bug when changing home directory
+- name: Test home directory creation
+ when: ansible_facts.system != 'Darwin'
+ block:
+ - name: create user specifying home
+ user:
+ name: ansibulluser
+ state: present
+ home: "{{ user_home_prefix[ansible_facts.system] }}/ansibulluser"
+ register: user_test3_0
+
+ - name: create user again specifying home
+ user:
+ name: ansibulluser
+ state: present
+ home: "{{ user_home_prefix[ansible_facts.system] }}/ansibulluser"
+ register: user_test3_1
+
+ - name: change user home
+ user:
+ name: ansibulluser
+ state: present
+ home: "{{ user_home_prefix[ansible_facts.system] }}/ansibulluser-mod"
+ register: user_test3_2
+
+ - name: change user home back
+ user:
+ name: ansibulluser
+ state: present
+ home: "{{ user_home_prefix[ansible_facts.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
+
+# https://github.com/ansible/ansible/issues/41393
+# Create a new user account with a path that has parent directories that do not exist
+- name: Create user with home path that has parents that do not exist
+ user:
+ name: ansibulluser2
+ state: present
+ home: "{{ user_home_prefix[ansible_facts.system] }}/in2deep/ansibulluser2"
+ register: create_home_with_no_parent_1
+
+- name: Create user with home path that has parents that do not exist again
+ user:
+ name: ansibulluser2
+ state: present
+ home: "{{ user_home_prefix[ansible_facts.system] }}/in2deep/ansibulluser2"
+ register: create_home_with_no_parent_2
+
+- name: Check the created home directory
+ stat:
+ path: "{{ user_home_prefix[ansible_facts.system] }}/in2deep/ansibulluser2"
+ register: home_with_no_parent_3
+
+- name: Ensure user with non-existing parent paths was created successfully
+ assert:
+ that:
+ - create_home_with_no_parent_1 is changed
+ - create_home_with_no_parent_1.home == user_home_prefix[ansible_facts.system] ~ '/in2deep/ansibulluser2'
+ - create_home_with_no_parent_2 is not changed
+ - home_with_no_parent_3.stat.uid == create_home_with_no_parent_1.uid
+ - home_with_no_parent_3.stat.gr_name == default_user_group[ansible_facts.distribution] | default('ansibulluser2')
+
+- name: Cleanup test account
+ user:
+ name: ansibulluser2
+ home: "{{ user_home_prefix[ansible_facts.system] }}/in2deep/ansibulluser2"
+ state: absent
+ remove: yes
+
+- name: Remove testing dir
+ file:
+ path: "{{ user_home_prefix[ansible_facts.system] }}/in2deep/"
+ state: absent
+
+
+# https://github.com/ansible/ansible/issues/60307
+# Make sure we can create a user when the home directory is missing
+- name: Create user with home path that does not exist
+ user:
+ name: ansibulluser3
+ state: present
+ home: "{{ user_home_prefix[ansible_facts.system] }}/nosuchdir"
+ createhome: no
+
+- name: Cleanup test account
+ user:
+ name: ansibulluser3
+ state: absent
+ remove: yes
+
+# https://github.com/ansible/ansible/issues/70589
+# Create user with create_home: no and parent directory does not exist.
+- name: "Check if parent dir for home dir for user exists (before)"
+ stat:
+ path: "{{ user_home_prefix[ansible_facts.system] }}/thereisnodir"
+ register: create_user_no_create_home_with_no_parent_parent_dir_before
+
+- name: "Create user with create_home == no and home path parent dir does not exist"
+ user:
+ name: randomuser
+ state: present
+ create_home: false
+ home: "{{ user_home_prefix[ansible_facts.system] }}/thereisnodir/randomuser"
+ register: create_user_no_create_home_with_no_parent
+
+- name: "Check if parent dir for home dir for user exists (after)"
+ stat:
+ path: "{{ user_home_prefix[ansible_facts.system] }}/thereisnodir"
+ register: create_user_no_create_home_with_no_parent_parent_dir_after
+
+- name: "Check if home for user is created"
+ stat:
+ path: "{{ user_home_prefix[ansible_facts.system] }}/thereisnodir/randomuser"
+ register: create_user_no_create_home_with_no_parent_home_dir
+
+- name: "Ensure user with non-existing parent paths with create_home: no was created successfully"
+ assert:
+ that:
+ - not create_user_no_create_home_with_no_parent_parent_dir_before.stat.exists
+ - not create_user_no_create_home_with_no_parent_parent_dir_after.stat.isdir is defined
+ - not create_user_no_create_home_with_no_parent_home_dir.stat.exists
+
+- name: Cleanup test account
+ user:
+ name: randomuser
+ state: absent
+ remove: yes
diff --git a/test/integration/targets/user/tasks/test_create_user_password.yml b/test/integration/targets/user/tasks/test_create_user_password.yml
new file mode 100644
index 0000000..02aae00
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_create_user_password.yml
@@ -0,0 +1,90 @@
+# 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"
+
+# https://github.com/ansible/ansible/issues/65711
+- name: Test updating password only on creation
+ user:
+ name: ansibulluser
+ password: '*'
+ update_password: on_create
+ register: test_user_update_password
+
+- name: Ensure password was not changed
+ assert:
+ that:
+ - test_user_update_password is not changed
+
+- name: Verify password hash for Linux
+ when: ansible_facts.os_family in ['RedHat', 'Debian', 'Suse']
+ block:
+ - name: LINUX | Get shadow entry for ansibulluser
+ getent:
+ database: shadow
+ key: ansibulluser
+
+ - name: LINUX | Ensure password hash was not removed
+ assert:
+ that:
+ - getent_shadow['ansibulluser'][1] != '*'
+
+- name: Test plaintext warning
+ when: ansible_facts.system != 'Darwin'
+ 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"
+
+ - name: change password to '!'
+ user:
+ name: ansibulluser
+ password: '!'
+ register: test_user_encrypt3
+
+ - name: change password to '*'
+ user:
+ name: ansibulluser
+ password: '*'
+ register: test_user_encrypt4
+
+ - name: change password to '*************'
+ user:
+ name: ansibulluser
+ password: '*************'
+ register: test_user_encrypt5
+
+ - name: there should be no warnings when setting the password to '!', '*' or '*************'
+ assert:
+ that:
+ - "'warnings' not in test_user_encrypt3"
+ - "'warnings' not in test_user_encrypt4"
+ - "'warnings' not in test_user_encrypt5"
diff --git a/test/integration/targets/user/tasks/test_create_user_uid.yml b/test/integration/targets/user/tasks/test_create_user_uid.yml
new file mode 100644
index 0000000..9ac8a96
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_create_user_uid.yml
@@ -0,0 +1,26 @@
+# test adding user with uid
+# https://github.com/ansible/ansible/issues/62969
+- name: remove the test user
+ user:
+ name: ansibulluser
+ state: absent
+
+- name: try to create a user with uid
+ user:
+ name: ansibulluser
+ state: present
+ uid: 572
+ register: user_test01_0
+
+- name: create the user again
+ user:
+ name: ansibulluser
+ state: present
+ uid: 572
+ register: user_test01_1
+
+- name: validate results for testcase 0
+ assert:
+ that:
+ - user_test01_0 is changed
+ - user_test01_1 is not changed
diff --git a/test/integration/targets/user/tasks/test_expires.yml b/test/integration/targets/user/tasks/test_expires.yml
new file mode 100644
index 0000000..8c23893
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_expires.yml
@@ -0,0 +1,147 @@
+# Date is March 3, 2050
+- name: Set user expiration
+ user:
+ name: ansibulluser
+ state: present
+ expires: 2529881062
+ register: user_test_expires1
+ tags:
+ - timezone
+
+- name: Set user expiration again to ensure no change is made
+ user:
+ name: ansibulluser
+ state: present
+ expires: 2529881062
+ register: user_test_expires2
+ tags:
+ - timezone
+
+- 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_facts.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 == '2529881062'
+ when: ansible_facts.os_family == 'FreeBSD'
+
+- name: Change timezone
+ timezone:
+ name: America/Denver
+ register: original_timezone
+ tags:
+ - 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
+ tags:
+ - timezone
+
+ - name: Ensure that no change was reported
+ assert:
+ that:
+ - user_test_different_tz is not changed
+ tags:
+ - timezone
+
+ always:
+ - name: Restore original timezone - {{ original_timezone.diff.before.name }}
+ timezone:
+ name: "{{ original_timezone.diff.before.name }}"
+ when: original_timezone.diff.before.name != "n/a"
+ tags:
+ - timezone
+
+ - name: Restore original timezone when n/a
+ file:
+ path: /etc/sysconfig/clock
+ state: absent
+ when:
+ - original_timezone.diff.before.name == "n/a"
+ - "'/etc/sysconfig/clock' in original_timezone.msg"
+ tags:
+ - timezone
+
+
+- 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] | int < 0
+ when: ansible_facts.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_facts.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_facts.os_family == 'FreeBSD'
diff --git a/test/integration/targets/user/tasks/test_expires_min_max.yml b/test/integration/targets/user/tasks/test_expires_min_max.yml
new file mode 100644
index 0000000..0b80379
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_expires_min_max.yml
@@ -0,0 +1,73 @@
+# https://github.com/ansible/ansible/issues/68775
+- name: Test setting maximum expiration
+ when: ansible_facts.os_family in ['RedHat', 'Debian', 'Suse']
+ block:
+ - name: create user
+ user:
+ name: ansibulluser
+ state: present
+
+ - name: add maximum expire date for password
+ user:
+ name: ansibulluser
+ password_expire_max: 10
+ register: pass_max_1_0
+
+ - name: again add maximum expire date for password
+ user:
+ name: ansibulluser
+ password_expire_max: 10
+ register: pass_max_1_1
+
+ - name: validate result for maximum expire date
+ assert:
+ that:
+ - pass_max_1_0 is changed
+ - pass_max_1_1 is not changed
+
+ - name: add minimum expire date for password
+ user:
+ name: ansibulluser
+ password_expire_min: 5
+ register: pass_min_2_0
+
+ - name: again add minimum expire date for password
+ user:
+ name: ansibulluser
+ password_expire_min: 5
+ register: pass_min_2_1
+
+ - name: validate result for minimum expire date
+ assert:
+ that:
+ - pass_min_2_0 is changed
+ - pass_min_2_1 is not changed
+
+ - name: Get shadow data for ansibulluser
+ getent:
+ database: shadow
+ key: ansibulluser
+
+ - name: Ensure password expiration was set properly
+ assert:
+ that:
+ - ansible_facts.getent_shadow['ansibulluser'][2] == '5'
+ - ansible_facts.getent_shadow['ansibulluser'][3] == '10'
+
+ - name: Set min and max at the same time
+ user:
+ name: ansibulluser
+ # also checks that assigning 0 works
+ password_expire_min: 0
+ password_expire_max: 0
+
+ - name: Get shadow data for ansibulluser
+ getent:
+ database: shadow
+ key: ansibulluser
+
+ - name: Ensure password expiration was set properly
+ assert:
+ that:
+ - ansible_facts.getent_shadow['ansibulluser'][2] == '0'
+ - ansible_facts.getent_shadow['ansibulluser'][3] == '0'
diff --git a/test/integration/targets/user/tasks/test_expires_new_account.yml b/test/integration/targets/user/tasks/test_expires_new_account.yml
new file mode 100644
index 0000000..b77d137
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_expires_new_account.yml
@@ -0,0 +1,55 @@
+# Test setting no expiration when creating a new account
+# https://github.com/ansible/ansible/issues/44155
+- name: Remove ansibulluser
+ user:
+ name: ansibulluser
+ state: absent
+
+- name: Create user account without expiration
+ user:
+ name: ansibulluser
+ state: present
+ expires: -1
+ register: user_test_create_no_expires_1
+
+- name: Create user account without expiration again
+ user:
+ name: ansibulluser
+ state: present
+ expires: -1
+ register: user_test_create_no_expires_2
+
+- name: Ensure changes were made appropriately
+ assert:
+ msg: Setting 'expires='-1 resulted in incorrect changes
+ that:
+ - user_test_create_no_expires_1 is changed
+ - user_test_create_no_expires_2 is not changed
+
+- 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] | int < 0
+ when: ansible_facts.os_family in ['RedHat', 'Debian', 'Suse']
+
+- 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_facts.os_family == 'FreeBSD'
diff --git a/test/integration/targets/user/tasks/test_expires_new_account_epoch_negative.yml b/test/integration/targets/user/tasks/test_expires_new_account_epoch_negative.yml
new file mode 100644
index 0000000..77a07c4
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_expires_new_account_epoch_negative.yml
@@ -0,0 +1,112 @@
+# Test setting epoch 0 expiration when creating a new account, then removing the expiry
+# https://github.com/ansible/ansible/issues/47114
+- name: Remove ansibulluser
+ user:
+ name: ansibulluser
+ state: absent
+
+- name: Create user account with epoch 0 expiration
+ user:
+ name: ansibulluser
+ state: present
+ expires: 0
+ register: user_test_expires_create0_1
+
+- name: Create user account with epoch 0 expiration again
+ user:
+ name: ansibulluser
+ state: present
+ expires: 0
+ register: user_test_expires_create0_2
+
+- name: Change the user account to remove the expiry time
+ user:
+ name: ansibulluser
+ expires: -1
+ register: user_test_remove_expires_1
+
+- name: Change the user account to remove the expiry time again
+ user:
+ name: ansibulluser
+ expires: -1
+ register: user_test_remove_expires_2
+
+
+- name: Verify un expiration date for Linux
+ block:
+ - name: LINUX | Ensure changes were made appropriately
+ assert:
+ msg: Creating an account with 'expries=0' then removing that expriation with 'expires=-1' resulted in incorrect changes
+ that:
+ - user_test_expires_create0_1 is changed
+ - user_test_expires_create0_2 is not changed
+ - user_test_remove_expires_1 is changed
+ - user_test_remove_expires_2 is not changed
+
+ - 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] | int < 0
+ when: ansible_facts.os_family in ['RedHat', 'Debian', 'Suse']
+
+
+- name: Verify proper expiration behavior for BSD
+ block:
+ - name: BSD | Ensure changes were made appropriately
+ assert:
+ msg: Creating an account with 'expries=0' then removing that expriation with 'expires=-1' resulted in incorrect changes
+ that:
+ - user_test_expires_create0_1 is changed
+ - user_test_expires_create0_2 is not changed
+ - user_test_remove_expires_1 is not changed
+ - user_test_remove_expires_2 is not changed
+ when: ansible_facts.os_family == 'FreeBSD'
+
+
+# Test expiration with a very large negative number. This should have the same
+# result as setting -1.
+- name: Set expiration date using very long negative number
+ user:
+ name: ansibulluser
+ state: present
+ expires: -2529881062
+ register: user_test_expires5
+
+- name: Ensure no change was made
+ assert:
+ that:
+ - user_test_expires5 is not changed
+
+- 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] | int < 0
+ when: ansible_facts.os_family in ['RedHat', 'Debian', 'Suse']
+
+- 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_facts.os_family == 'FreeBSD'
diff --git a/test/integration/targets/user/tasks/test_local.yml b/test/integration/targets/user/tasks/test_local.yml
new file mode 100644
index 0000000..67c24a2
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_local.yml
@@ -0,0 +1,196 @@
+## Check local mode
+# Even if we don't have a system that is bound to a directory, it's useful
+# to run with local: true to exercise the code path that reads through the local
+# user database file.
+# https://github.com/ansible/ansible/issues/50947
+
+- name: Create /etc/gshadow
+ file:
+ path: /etc/gshadow
+ state: touch
+ when: ansible_facts.os_family == 'Suse'
+ tags:
+ - user_test_local_mode
+
+- name: Create /etc/libuser.conf
+ file:
+ path: /etc/libuser.conf
+ state: touch
+ when:
+ - ansible_facts.distribution == 'Ubuntu'
+ - ansible_facts.distribution_major_version is version_compare('16', '==')
+ tags:
+ - user_test_local_mode
+
+- name: Ensure luseradd is present
+ action: "{{ ansible_facts.pkg_mgr }}"
+ args:
+ name: libuser
+ state: present
+ when: ansible_facts.system in ['Linux']
+ tags:
+ - user_test_local_mode
+
+- name: Create local account that already exists to check for warning
+ user:
+ name: root
+ local: yes
+ register: local_existing
+ tags:
+ - user_test_local_mode
+
+- name: Create local_ansibulluser
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ register: local_user_test_1
+ tags:
+ - user_test_local_mode
+
+- name: Create local_ansibulluser again
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ register: local_user_test_2
+ tags:
+ - user_test_local_mode
+
+- name: Remove local_ansibulluser
+ user:
+ name: local_ansibulluser
+ state: absent
+ remove: yes
+ local: yes
+ register: local_user_test_remove_1
+ tags:
+ - user_test_local_mode
+
+- name: Remove local_ansibulluser again
+ user:
+ name: local_ansibulluser
+ state: absent
+ remove: yes
+ local: yes
+ register: local_user_test_remove_2
+ tags:
+ - user_test_local_mode
+
+- name: Create test groups
+ group:
+ name: "{{ item }}"
+ loop:
+ - testgroup1
+ - testgroup2
+ - testgroup3
+ - testgroup4
+ - testgroup5
+ - local_ansibulluser
+ tags:
+ - user_test_local_mode
+
+- name: Create local_ansibulluser with groups
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ groups: ['testgroup1', 'testgroup2']
+ register: local_user_test_3
+ ignore_errors: yes
+ tags:
+ - user_test_local_mode
+
+- name: Append groups for local_ansibulluser
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ groups: ['testgroup3', 'testgroup4']
+ append: yes
+ register: local_user_test_4
+ ignore_errors: yes
+ tags:
+ - user_test_local_mode
+
+- name: Test append without groups for local_ansibulluser
+ user:
+ name: local_ansibulluser
+ state: present
+ append: yes
+ register: local_user_test_5
+ ignore_errors: yes
+ tags:
+ - user_test_local_mode
+
+- name: Assign named group for local_ansibulluser
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ group: testgroup5
+ register: local_user_test_6
+ tags:
+ - user_test_local_mode
+
+# If we don't re-assign, then "Set user expiration" will
+# fail.
+- name: Re-assign named group for local_ansibulluser
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ group: local_ansibulluser
+ ignore_errors: yes
+ tags:
+ - user_test_local_mode
+
+- name: Remove local_ansibulluser again
+ user:
+ name: local_ansibulluser
+ state: absent
+ remove: yes
+ local: yes
+ tags:
+ - user_test_local_mode
+
+- name: Remove test groups
+ group:
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - testgroup1
+ - testgroup2
+ - testgroup3
+ - testgroup4
+ - testgroup5
+ - local_ansibulluser
+ tags:
+ - user_test_local_mode
+
+- name: Ensure local user accounts were created and removed properly
+ assert:
+ that:
+ - local_user_test_1 is changed
+ - local_user_test_2 is not changed
+ - local_user_test_3 is changed
+ - local_user_test_4 is changed
+ - local_user_test_6 is changed
+ - local_user_test_remove_1 is changed
+ - local_user_test_remove_2 is not changed
+ tags:
+ - user_test_local_mode
+
+- name: Ensure warnings were displayed properly
+ assert:
+ that:
+ - local_user_test_1['warnings'] | length > 0
+ - local_user_test_1['warnings'] | first is search('The local user account may already exist')
+ - local_user_test_5['warnings'] is search("'append' is set, but no 'groups' are specified. Use 'groups'")
+ - local_existing['warnings'] is not defined
+ when: ansible_facts.system in ['Linux']
+ tags:
+ - user_test_local_mode
+
+- name: Test expires for local users
+ import_tasks: test_local_expires.yml
diff --git a/test/integration/targets/user/tasks/test_local_expires.yml b/test/integration/targets/user/tasks/test_local_expires.yml
new file mode 100644
index 0000000..e662035
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_local_expires.yml
@@ -0,0 +1,333 @@
+---
+## local user expires
+# Date is March 3, 2050
+
+- name: Remove local_ansibulluser
+ user:
+ name: local_ansibulluser
+ state: absent
+ remove: yes
+ local: yes
+ tags:
+ - user_test_local_mode
+
+- name: Set user expiration
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ expires: 2529881062
+ register: user_test_local_expires1
+ tags:
+ - timezone
+ - user_test_local_mode
+
+- name: Set user expiration again to ensure no change is made
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ expires: 2529881062
+ register: user_test_local_expires2
+ tags:
+ - timezone
+ - user_test_local_mode
+
+- name: Ensure that account with expiration was created and did not change on subsequent run
+ assert:
+ that:
+ - user_test_local_expires1 is changed
+ - user_test_local_expires2 is not changed
+ tags:
+ - user_test_local_mode
+
+- name: Verify expiration date for Linux
+ block:
+ - name: LINUX | Get expiration date for local_ansibulluser
+ getent:
+ database: shadow
+ key: local_ansibulluser
+ tags:
+ - user_test_local_mode
+
+ - name: LINUX | Ensure proper expiration date was set
+ assert:
+ that:
+ - getent_shadow['local_ansibulluser'][6] == '29281'
+ tags:
+ - user_test_local_mode
+ when: ansible_facts.os_family in ['RedHat', 'Debian', 'Suse']
+
+- name: Change timezone
+ timezone:
+ name: America/Denver
+ register: original_timezone
+ tags:
+ - timezone
+ - user_test_local_mode
+
+- 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: local_ansibulluser
+ state: present
+ local: yes
+ expires: 2529881062
+ register: user_test_local_different_tz
+ tags:
+ - timezone
+ - user_test_local_mode
+
+ - name: Ensure that no change was reported
+ assert:
+ that:
+ - user_test_local_different_tz is not changed
+ tags:
+ - timezone
+ - user_test_local_mode
+
+ always:
+ - name: Restore original timezone - {{ original_timezone.diff.before.name }}
+ timezone:
+ name: "{{ original_timezone.diff.before.name }}"
+ when: original_timezone.diff.before.name != "n/a"
+ tags:
+ - timezone
+ - user_test_local_mode
+
+ - name: Restore original timezone when n/a
+ file:
+ path: /etc/sysconfig/clock
+ state: absent
+ when:
+ - original_timezone.diff.before.name == "n/a"
+ - "'/etc/sysconfig/clock' in original_timezone.msg"
+ tags:
+ - timezone
+ - user_test_local_mode
+
+
+- name: Unexpire user
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ expires: -1
+ register: user_test_local_expires3
+ tags:
+ - user_test_local_mode
+
+- name: Verify un expiration date for Linux
+ block:
+ - name: LINUX | Get expiration date for local_ansibulluser
+ getent:
+ database: shadow
+ key: local_ansibulluser
+ tags:
+ - user_test_local_mode
+
+ - name: LINUX | Ensure proper expiration date was set
+ assert:
+ msg: "expiry is supposed to be empty or -1, not {{ getent_shadow['local_ansibulluser'][6] }}"
+ that:
+ - not getent_shadow['local_ansibulluser'][6] or getent_shadow['local_ansibulluser'][6] | int < 0
+ tags:
+ - user_test_local_mode
+ when: ansible_facts.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: local_ansibulluser
+ state: present
+ local: yes
+ expires: -1
+ register: user_test_local_expires4
+ tags:
+ - user_test_local_mode
+
+ - 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_local_expires3 is changed
+ - user_test_local_expires4 is not changed
+ tags:
+ - user_test_local_mode
+ when: ansible_facts.os_family in ['RedHat', 'Debian', 'Suse', 'FreeBSD']
+
+# Test setting no expiration when creating a new account
+# https://github.com/ansible/ansible/issues/44155
+- name: Remove local_ansibulluser
+ user:
+ name: local_ansibulluser
+ state: absent
+ remove: yes
+ local: yes
+ tags:
+ - user_test_local_mode
+
+- name: Create user account without expiration
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ expires: -1
+ register: user_test_local_create_no_expires_1
+ tags:
+ - user_test_local_mode
+
+- name: Create user account without expiration again
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ expires: -1
+ register: user_test_local_create_no_expires_2
+ tags:
+ - user_test_local_mode
+
+- name: Ensure changes were made appropriately
+ assert:
+ msg: Setting 'expires='-1 resulted in incorrect changes
+ that:
+ - user_test_local_create_no_expires_1 is changed
+ - user_test_local_create_no_expires_2 is not changed
+ tags:
+ - user_test_local_mode
+
+- name: Verify un expiration date for Linux
+ block:
+ - name: LINUX | Get expiration date for local_ansibulluser
+ getent:
+ database: shadow
+ key: local_ansibulluser
+ tags:
+ - user_test_local_mode
+
+ - name: LINUX | Ensure proper expiration date was set
+ assert:
+ msg: "expiry is supposed to be empty or -1, not {{ getent_shadow['local_ansibulluser'][6] }}"
+ that:
+ - not getent_shadow['local_ansibulluser'][6] or getent_shadow['local_ansibulluser'][6] | int < 0
+ tags:
+ - user_test_local_mode
+ when: ansible_facts.os_family in ['RedHat', 'Debian', 'Suse']
+
+# Test setting epoch 0 expiration when creating a new account, then removing the expiry
+# https://github.com/ansible/ansible/issues/47114
+- name: Remove local_ansibulluser
+ user:
+ name: local_ansibulluser
+ state: absent
+ remove: yes
+ local: yes
+ tags:
+ - user_test_local_mode
+
+- name: Create user account with epoch 0 expiration
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ expires: 0
+ register: user_test_local_expires_create0_1
+ tags:
+ - user_test_local_mode
+
+- name: Create user account with epoch 0 expiration again
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ expires: 0
+ register: user_test_local_expires_create0_2
+ tags:
+ - user_test_local_mode
+
+- name: Change the user account to remove the expiry time
+ user:
+ name: local_ansibulluser
+ expires: -1
+ local: yes
+ register: user_test_local_remove_expires_1
+ tags:
+ - user_test_local_mode
+
+- name: Change the user account to remove the expiry time again
+ user:
+ name: local_ansibulluser
+ expires: -1
+ local: yes
+ register: user_test_local_remove_expires_2
+ tags:
+ - user_test_local_mode
+
+
+- name: Verify un expiration date for Linux
+ block:
+ - name: LINUX | Ensure changes were made appropriately
+ assert:
+ msg: Creating an account with 'expries=0' then removing that expriation with 'expires=-1' resulted in incorrect changes
+ that:
+ - user_test_local_expires_create0_1 is changed
+ - user_test_local_expires_create0_2 is not changed
+ - user_test_local_remove_expires_1 is changed
+ - user_test_local_remove_expires_2 is not changed
+ tags:
+ - user_test_local_mode
+
+ - name: LINUX | Get expiration date for local_ansibulluser
+ getent:
+ database: shadow
+ key: local_ansibulluser
+ tags:
+ - user_test_local_mode
+
+ - name: LINUX | Ensure proper expiration date was set
+ assert:
+ msg: "expiry is supposed to be empty or -1, not {{ getent_shadow['local_ansibulluser'][6] }}"
+ that:
+ - not getent_shadow['local_ansibulluser'][6] or getent_shadow['local_ansibulluser'][6] | int < 0
+ tags:
+ - user_test_local_mode
+ when: ansible_facts.os_family in ['RedHat', 'Debian', 'Suse']
+
+# Test expiration with a very large negative number. This should have the same
+# result as setting -1.
+- name: Set expiration date using very long negative number
+ user:
+ name: local_ansibulluser
+ state: present
+ local: yes
+ expires: -2529881062
+ register: user_test_local_expires5
+ tags:
+ - user_test_local_mode
+
+- name: Ensure no change was made
+ assert:
+ that:
+ - user_test_local_expires5 is not changed
+ tags:
+ - user_test_local_mode
+
+- name: Verify un expiration date for Linux
+ block:
+ - name: LINUX | Get expiration date for local_ansibulluser
+ getent:
+ database: shadow
+ key: local_ansibulluser
+ tags:
+ - user_test_local_mode
+
+ - name: LINUX | Ensure proper expiration date was set
+ assert:
+ msg: "expiry is supposed to be empty or -1, not {{ getent_shadow['local_ansibulluser'][6] }}"
+ that:
+ - not getent_shadow['local_ansibulluser'][6] or getent_shadow['local_ansibulluser'][6] | int < 0
+ tags:
+ - user_test_local_mode
+ when: ansible_facts.os_family in ['RedHat', 'Debian', 'Suse']
diff --git a/test/integration/targets/user/tasks/test_no_home_fallback.yml b/test/integration/targets/user/tasks/test_no_home_fallback.yml
new file mode 100644
index 0000000..f7627fa
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_no_home_fallback.yml
@@ -0,0 +1,106 @@
+## create user without home and test fallback home dir create
+
+- name: Test home directory creation
+ when: ansible_facts.system != 'Darwin'
+ block:
+ - name: create the user
+ user:
+ name: ansibulluser
+
+ - name: delete the user and home dir
+ user:
+ name: ansibulluser
+ state: absent
+ force: true
+ remove: true
+
+ - name: create the user without home
+ user:
+ name: ansibulluser
+ create_home: no
+
+ - name: create the user home dir
+ user:
+ name: ansibulluser
+ register: user_create_home_fallback
+
+ - name: stat home dir
+ stat:
+ path: '{{ user_create_home_fallback.home }}'
+ register: user_create_home_fallback_dir
+
+ - name: read UMASK from /etc/login.defs and return mode
+ shell: |
+ import re
+ import os
+ try:
+ for line in open('/etc/login.defs').readlines():
+ m = re.match(r'^UMASK\s+(\d+)$', line)
+ if m:
+ umask = int(m.group(1), 8)
+ except:
+ umask = os.umask(0)
+ mode = oct(0o777 & ~umask)
+ print(str(mode).replace('o', ''))
+ args:
+ executable: "{{ ansible_python_interpreter }}"
+ register: user_login_defs_umask
+
+ - name: validate that user home dir is created
+ assert:
+ that:
+ - user_create_home_fallback is changed
+ - user_create_home_fallback_dir.stat.exists
+ - user_create_home_fallback_dir.stat.isdir
+ - user_create_home_fallback_dir.stat.pw_name == 'ansibulluser'
+ - user_create_home_fallback_dir.stat.mode == user_login_defs_umask.stdout
+
+- name: Create non-system user
+ when: ansible_facts.distribution == "MacOSX"
+ 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
diff --git a/test/integration/targets/user/tasks/test_password_lock.yml b/test/integration/targets/user/tasks/test_password_lock.yml
new file mode 100644
index 0000000..dde374e
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_password_lock.yml
@@ -0,0 +1,140 @@
+- name: Test password lock
+ when: ansible_facts.system in ['FreeBSD', 'OpenBSD', 'Linux']
+ block:
+ - name: Remove ansibulluser
+ user:
+ name: ansibulluser
+ state: absent
+ remove: yes
+
+ - name: Create ansibulluser with password
+ user:
+ name: ansibulluser
+ password: "$6$rounds=656000$TT4O7jz2M57npccl$33LF6FcUMSW11qrESXL1HX0BS.bsiT6aenFLLiVpsQh6hDtI9pJh5iY7x8J7ePkN4fP8hmElidHXaeD51pbGS."
+
+ - name: Lock account without password parameter
+ user:
+ name: ansibulluser
+ password_lock: yes
+ register: password_lock_1
+
+ - name: Lock account without password parameter again
+ user:
+ name: ansibulluser
+ password_lock: yes
+ register: password_lock_2
+
+ - name: Unlock account without password parameter
+ user:
+ name: ansibulluser
+ password_lock: no
+ register: password_lock_3
+
+ - name: Unlock account without password parameter again
+ user:
+ name: ansibulluser
+ password_lock: no
+ register: password_lock_4
+
+ - name: Lock account with password parameter
+ user:
+ name: ansibulluser
+ password_lock: yes
+ password: "$6$rounds=656000$TT4O7jz2M57npccl$33LF6FcUMSW11qrESXL1HX0BS.bsiT6aenFLLiVpsQh6hDtI9pJh5iY7x8J7ePkN4fP8hmElidHXaeD51pbGS."
+ register: password_lock_5
+
+ - name: Lock account with password parameter again
+ user:
+ name: ansibulluser
+ password_lock: yes
+ password: "$6$rounds=656000$TT4O7jz2M57npccl$33LF6FcUMSW11qrESXL1HX0BS.bsiT6aenFLLiVpsQh6hDtI9pJh5iY7x8J7ePkN4fP8hmElidHXaeD51pbGS."
+ register: password_lock_6
+
+ - name: Unlock account with password parameter
+ user:
+ name: ansibulluser
+ password_lock: no
+ password: "$6$rounds=656000$TT4O7jz2M57npccl$33LF6FcUMSW11qrESXL1HX0BS.bsiT6aenFLLiVpsQh6hDtI9pJh5iY7x8J7ePkN4fP8hmElidHXaeD51pbGS."
+ register: password_lock_7
+
+ - name: Unlock account with password parameter again
+ user:
+ name: ansibulluser
+ password_lock: no
+ password: "$6$rounds=656000$TT4O7jz2M57npccl$33LF6FcUMSW11qrESXL1HX0BS.bsiT6aenFLLiVpsQh6hDtI9pJh5iY7x8J7ePkN4fP8hmElidHXaeD51pbGS."
+ register: password_lock_8
+
+ - name: Ensure task reported changes appropriately
+ assert:
+ msg: The password_lock tasks did not make changes appropriately
+ that:
+ - password_lock_1 is changed
+ - password_lock_2 is not changed
+ - password_lock_3 is changed
+ - password_lock_4 is not changed
+ - password_lock_5 is changed
+ - password_lock_6 is not changed
+ - password_lock_7 is changed
+ - password_lock_8 is not changed
+
+ - name: Lock account
+ user:
+ name: ansibulluser
+ password_lock: yes
+
+ - name: Verify account lock for BSD
+ when: ansible_facts.system in ['FreeBSD', 'OpenBSD']
+ block:
+ - name: BSD | Get account status
+ shell: "{{ status_command[ansible_facts['system']] }}"
+ register: account_status_locked
+
+ - name: Unlock account
+ user:
+ name: ansibulluser
+ password_lock: no
+
+ - name: BSD | Get account status
+ shell: "{{ status_command[ansible_facts['system']] }}"
+ register: account_status_unlocked
+
+ - name: FreeBSD | Ensure account is locked
+ assert:
+ that:
+ - "'LOCKED' in account_status_locked.stdout"
+ - "'LOCKED' not in account_status_unlocked.stdout"
+ when: ansible_facts['system'] == 'FreeBSD'
+
+ - name: Verify account lock for Linux
+ when: ansible_facts.system == 'Linux'
+ block:
+ - name: LINUX | Get account status
+ getent:
+ database: shadow
+ key: ansibulluser
+
+ - name: LINUX | Ensure account is locked
+ assert:
+ that:
+ - getent_shadow['ansibulluser'][0].startswith('!')
+
+ - name: Unlock account
+ user:
+ name: ansibulluser
+ password_lock: no
+
+ - name: LINUX | Get account status
+ getent:
+ database: shadow
+ key: ansibulluser
+
+ - name: LINUX | Ensure account is unlocked
+ assert:
+ that:
+ - not getent_shadow['ansibulluser'][0].startswith('!')
+
+ always:
+ - name: Unlock account
+ user:
+ name: ansibulluser
+ password_lock: no
diff --git a/test/integration/targets/user/tasks/test_password_lock_new_user.yml b/test/integration/targets/user/tasks/test_password_lock_new_user.yml
new file mode 100644
index 0000000..dd4f23d
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_password_lock_new_user.yml
@@ -0,0 +1,63 @@
+- name: Test password lock
+ when: ansible_facts.system in ['FreeBSD', 'OpenBSD', 'Linux']
+ block:
+ - name: Remove ansibulluser
+ user:
+ name: ansibulluser
+ state: absent
+ remove: yes
+
+ - name: Create ansibulluser with password and locked
+ user:
+ name: ansibulluser
+ password: "$6$rounds=656000$TT4O7jz2M57npccl$33LF6FcUMSW11qrESXL1HX0BS.bsiT6aenFLLiVpsQh6hDtI9pJh5iY7x8J7ePkN4fP8hmElidHXaeD51pbGS."
+ password_lock: yes
+ register: create_with_lock_1
+
+ - name: Create ansibulluser with password and locked again
+ user:
+ name: ansibulluser
+ password: "$6$rounds=656000$TT4O7jz2M57npccl$33LF6FcUMSW11qrESXL1HX0BS.bsiT6aenFLLiVpsQh6hDtI9pJh5iY7x8J7ePkN4fP8hmElidHXaeD51pbGS."
+ password_lock: yes
+ register: create_with_lock_2
+
+ - name: Ensure task reported changes appropriately
+ assert:
+ msg: The password_lock tasks did not make changes appropriately
+ that:
+ - create_with_lock_1 is changed
+ - create_with_lock_2 is not changed
+
+ - name: Verify account lock for BSD
+ when: ansible_facts.system in ['FreeBSD', 'OpenBSD']
+ block:
+ - name: BSD | Get account status
+ shell: "{{ status_command[ansible_facts['system']] }}"
+ register: account_status_locked
+
+ - name: FreeBSD | Ensure account is locked
+ assert:
+ that:
+ - "'LOCKED' in account_status_locked.stdout"
+ when: ansible_facts.system == 'FreeBSD'
+
+
+ - name: Verify account lock for Linux
+ when: ansible_facts.system == 'Linux'
+ block:
+ - name: LINUX | Get account status
+ getent:
+ database: shadow
+ key: ansibulluser
+
+ - name: LINUX | Ensure account is locked
+ assert:
+ that:
+ - getent_shadow['ansibulluser'][0].startswith('!')
+
+
+ always:
+ - name: Unlock account
+ user:
+ name: ansibulluser
+ password_lock: no
diff --git a/test/integration/targets/user/tasks/test_remove_user.yml b/test/integration/targets/user/tasks/test_remove_user.yml
new file mode 100644
index 0000000..dea71cb
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_remove_user.yml
@@ -0,0 +1,19 @@
+- 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_facts.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'
diff --git a/test/integration/targets/user/tasks/test_shadow_backup.yml b/test/integration/targets/user/tasks/test_shadow_backup.yml
new file mode 100644
index 0000000..2655fbf
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_shadow_backup.yml
@@ -0,0 +1,21 @@
+- name: Test shadow backup on Solaris
+ when: ansible_facts.os_family == 'Solaris'
+ 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
diff --git a/test/integration/targets/user/tasks/test_ssh_key_passphrase.yml b/test/integration/targets/user/tasks/test_ssh_key_passphrase.yml
new file mode 100644
index 0000000..f0725ed
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_ssh_key_passphrase.yml
@@ -0,0 +1,30 @@
+# Test creating ssh key with passphrase
+- name: Remove ansibulluser
+ user:
+ name: ansibulluser
+ state: absent
+
+- name: Create user with ssh key
+ user:
+ name: ansibulluser
+ state: present
+ generate_ssh_key: yes
+ force: yes
+ ssh_key_file: .ssh/test_id_rsa
+ ssh_key_passphrase: secret_passphrase
+ register: ansibulluser_create_with_ssh_key
+
+- name: Unlock ssh key
+ command: "ssh-keygen -y -f {{ ansibulluser_create_with_ssh_key.ssh_key_file|quote }} -P secret_passphrase"
+ register: result
+
+- name: Check that ssh key was unlocked successfully
+ assert:
+ that:
+ - result.rc == 0
+
+- name: Clean ssh key
+ file:
+ path: "{{ ansibulluser_create_with_ssh_key.ssh_key_file }}"
+ state: absent
+ when: ansible_os_family == 'FreeBSD'
diff --git a/test/integration/targets/user/tasks/test_umask.yml b/test/integration/targets/user/tasks/test_umask.yml
new file mode 100644
index 0000000..9e16297
--- /dev/null
+++ b/test/integration/targets/user/tasks/test_umask.yml
@@ -0,0 +1,57 @@
+---
+- name: remove comments of /etc/login.defs
+ command: sed -e '/^[ \t]*#/d' /etc/login.defs
+ register: logindefs
+
+- block:
+ - name: Create user with 000 umask
+ user:
+ name: umaskuser_test_1
+ umask: "000"
+ register: umaskuser_test_1
+
+ - name: Create user with 077 umask
+ user:
+ name: umaskuser_test_2
+ umask: "077"
+ register: umaskuser_test_2
+
+ - name: check permissions on created home folder
+ stat:
+ path: "{{ user_home_prefix[ansible_facts.system] }}/umaskuser_test_1"
+ register: umaskuser_test_1_path
+
+ - name: check permissions on created home folder
+ stat:
+ path: "{{ user_home_prefix[ansible_facts.system] }}/umaskuser_test_2"
+ register: umaskuser_test_2_path
+
+ - name: remove created users
+ user:
+ name: "{{ item }}"
+ state: absent
+ register: umaskuser_test_remove
+ loop:
+ - umaskuser_test_1
+ - umaskuser_test_2
+
+ - name: Ensure correct umask has been set on created users
+ assert:
+ that:
+ - umaskuser_test_1_path.stat.mode == "0777"
+ - umaskuser_test_2_path.stat.mode == "0700"
+ - umaskuser_test_remove is changed
+ when: logindefs.stdout_lines is not search ("HOME_MODE")
+
+- name: Create user with setting both umask and local
+ user:
+ name: umaskuser_test_3
+ umask: "077"
+ local: true
+ register: umaskuser_test_3
+ ignore_errors: true
+
+- name: Ensure task has been failed
+ assert:
+ that:
+ - umaskuser_test_3 is failed
diff --git a/test/integration/targets/user/vars/main.yml b/test/integration/targets/user/vars/main.yml
new file mode 100644
index 0000000..4b328f7
--- /dev/null
+++ b/test/integration/targets/user/vars/main.yml
@@ -0,0 +1,13 @@
+user_home_prefix:
+ Linux: '/home'
+ FreeBSD: '/home'
+ SunOS: '/home'
+ Darwin: '/Users'
+
+status_command:
+ OpenBSD: "grep ansibulluser /etc/master.passwd | cut -d ':' -f 2"
+ FreeBSD: 'pw user show ansibulluser'
+
+default_user_group:
+ openSUSE Leap: users
+ MacOSX: admin