mirror of https://github.com/ansible/ansible.git
[stable-2.10] user - properly handle password and password lock when used together (#73016) (#73177)
Do the right thing on Linux when password lock and a password hash are provided by writing
out the password hash prepended by the appropriate lock string rather than using -U and -L.
This is the correct way to set and lock the account in one command.
On BSD, run separate commands as appropriate since locking and setting the password cannot
be done in a single action.
FreeBSD requires running several commands to get the account in the desired state. As a result,
the rc, output, and error from all commands need to be combined and evaluated so an accurate
and complete summary can be given at the end of module execution.
* Improve integration tests to cover this scenario.
* Break up user integration tests into smaller files
* Properly lock account when creating a new account and password is supplied
* Simplify rc collection in FreeBSD class
Since the _handle_lock() method was added, the rc would be set to None, which could make
task change reporting incorrect. My first attempt to solve this used a set and was a bit too
complicated. Simplify it my comparing the rc from _handle_lock() and the current value of rc.
* Improve the Linux password hash and locking behavior
If password lock and hash are provided, set the hash and lock the account by using a password
hash since -L cannot be used with -p.
* Ensure -U and -L are not combined with -p since they are mutually exclusive to usermod.
* Clarify password_lock behavior..
(cherry picked from commit 264e08f21a
)
Co-authored-by: Sam Doran <sdoran@redhat.com>
pull/73186/head
parent
6ba066fc9e
commit
b4b1bf9932
@ -0,0 +1,4 @@
|
||||
bugfixes:
|
||||
- >
|
||||
user - do the right thing when ``password_lock=True`` and ``password``
|
||||
are used together (https://github.com/ansible/ansible/issues/72992)
|
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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'"
|
@ -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
|
@ -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"
|
@ -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
|
@ -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'
|
@ -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'
|
@ -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'
|
@ -0,0 +1,169 @@
|
||||
## 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
|
||||
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: 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
|
||||
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_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
|
@ -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
|
@ -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
|
@ -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
|
@ -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'
|
@ -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
|
@ -0,0 +1,29 @@
|
||||
# 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: "{{ output_dir }}/test_id_rsa"
|
||||
ssh_key_passphrase: secret_passphrase
|
||||
|
||||
- name: Unlock ssh key
|
||||
command: "ssh-keygen -y -f {{ output_dir }}/test_id_rsa -P secret_passphrase"
|
||||
register: result
|
||||
|
||||
- name: Check that ssh key was unlocked successfully
|
||||
assert:
|
||||
that:
|
||||
- result.rc == 0
|
||||
|
||||
- name: Clean ssh key
|
||||
file:
|
||||
path: "{{ output_dir }}/test_id_rsa"
|
||||
state: absent
|
||||
when: ansible_os_family == 'FreeBSD'
|
Loading…
Reference in New Issue