diff --git a/changelogs/fragments/user-restore-disabled-account.yaml b/changelogs/fragments/user-restore-disabled-account.yaml new file mode 100644 index 00000000000..5c73bd92487 --- /dev/null +++ b/changelogs/fragments/user-restore-disabled-account.yaml @@ -0,0 +1,2 @@ +bugfixes: + - user - remove warning when creating a disabled account with '!' or '*' in the password field (https://github.com/ansible/ansible/issues/46334) diff --git a/lib/ansible/modules/system/user.py b/lib/ansible/modules/system/user.py index 385194ed150..d19a56d2f53 100644 --- a/lib/ansible/modules/system/user.py +++ b/lib/ansible/modules/system/user.py @@ -98,6 +98,7 @@ options: description: - Optionally set the user's password to this crypted value. - On macOS systems, this value has to be cleartext. Beware of security issues. + - To create a disabled account or Linux systems, set this to C('!') or C('*'). - See U(https://docs.ansible.com/ansible/faq.html#how-do-i-generate-crypted-passwords-for-the-user-module) for details on various ways to generate these password values. state: @@ -448,32 +449,37 @@ class User(object): self.ssh_file = os.path.join('.ssh', 'id_%s' % self.ssh_type) def check_password_encrypted(self): - # darwin need cleartext password, so no check + # Darwin needs cleartext password, so skip validation if self.module.params['password'] and self.platform != 'Darwin': maybe_invalid = False - # : for delimiter, * for disable user, ! for lock user - # these characters are invalid in the password - if any(char in self.module.params['password'] for char in ':*!'): - maybe_invalid = True - if '$' not in self.module.params['password']: - maybe_invalid = True + + # Allow setting the password to * or ! in order to disable the account + if self.module.params['password'] in set(['*', '!']): + maybe_invalid = False else: - fields = self.module.params['password'].split("$") - if len(fields) >= 3: - # contains character outside the crypto constraint - if bool(_HASH_RE.search(fields[-1])): - maybe_invalid = True - # md5 - if fields[1] == '1' and len(fields[-1]) != 22: - maybe_invalid = True - # sha256 - if fields[1] == '5' and len(fields[-1]) != 43: - maybe_invalid = True - # sha512 - if fields[1] == '6' and len(fields[-1]) != 86: - maybe_invalid = True - else: + # : for delimiter, * for disable user, ! for lock user + # these characters are invalid in the password + if any(char in self.module.params['password'] for char in ':*!'): + maybe_invalid = True + if '$' not in self.module.params['password']: maybe_invalid = True + else: + fields = self.module.params['password'].split("$") + if len(fields) >= 3: + # contains character outside the crypto constraint + if bool(_HASH_RE.search(fields[-1])): + maybe_invalid = True + # md5 + if fields[1] == '1' and len(fields[-1]) != 22: + maybe_invalid = True + # sha256 + if fields[1] == '5' and len(fields[-1]) != 43: + maybe_invalid = True + # sha512 + if fields[1] == '6' and len(fields[-1]) != 86: + maybe_invalid = True + else: + maybe_invalid = True if maybe_invalid: self.module.warn("The input password appears not to have been hashed. " "The 'password' argument must be encrypted for this module to work properly.") diff --git a/test/integration/targets/user/tasks/main.yml b/test/integration/targets/user/tasks/main.yml index d001cbdc484..248bf823591 100644 --- a/test/integration/targets/user/tasks/main.yml +++ b/test/integration/targets/user/tasks/main.yml @@ -101,6 +101,24 @@ - 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: there should be no warnings when setting the password to '!' and '*' + assert: + that: + - "'warnings' not in test_user_encrypt3" + - "'warnings' not in test_user_encrypt4" when: ansible_system != 'Darwin' @@ -314,6 +332,8 @@ timezone: name: America/Denver register: original_timezone + tags: + - timezone - name: Change system timezone to make sure expiration comparison works properly block: @@ -333,6 +353,8 @@ - name: Restore original timezone - {{ original_timezone.diff.before.name }} timezone: name: "{{ original_timezone.diff.before.name }}" + tags: + - timezone - name: Unexpire user