make password locking in user module idempotent (#43671)

* Simplify logic and add FreeBSD & NetBSD

* Remove incorrect flag for lock and unlock on FreeBSD

* Add tests and changelog


Co-authored-by: Chris Gadd <gaddman@email.com>
This commit is contained in:
Christopher Gadd 2018-11-09 15:29:38 +13:00 committed by Sam Doran
commit f75a84e382
4 changed files with 128 additions and 9 deletions

View file

@ -194,7 +194,7 @@ options:
- Lock the password (usermod -L, pw lock, usermod -C).
BUT implementation differs on different platforms, this option does not always mean the user cannot login via other methods.
This option does not disable the user, only lock the password. Do not change the password in the same task.
Currently supported on Linux, FreeBSD, DragonFlyBSD, NetBSD.
Currently supported on Linux, FreeBSD, DragonFlyBSD, NetBSD, OpenBSD.
type: bool
version_added: "2.6"
local:
@ -718,9 +718,11 @@ class User(object):
cmd.append('-e')
cmd.append(time.strftime(self.DATE_FORMAT, self.expires))
if self.password_lock:
# Lock if no password or unlocked, unlock only if locked
if self.password_lock and not info[1].startswith('!'):
cmd.append('-L')
elif self.password_lock is not None:
elif self.password_lock is False and info[1].startswith('!'):
# usermod will refuse to unlock a user with no password, module shows 'changed' regardless
cmd.append('-U')
if self.update_password == 'always' and self.password is not None and info[1] != self.password:
@ -1214,22 +1216,20 @@ class FreeBsdUser(User):
return self.execute_command(cmd)
# we have to lock/unlock the password in a distinct command
if self.password_lock:
if self.password_lock and not info[1].startswith('*LOCKED*'):
cmd = [
self.module.get_bin_path('pw', True),
'lock',
'-n',
self.name
]
if self.uid is not None and info[2] != int(self.uid):
cmd.append('-u')
cmd.append(self.uid)
return self.execute_command(cmd)
elif self.password_lock is not None:
elif self.password_lock is False and info[1].startswith('*LOCKED*'):
cmd = [
self.module.get_bin_path('pw', True),
'unlock',
'-n',
self.name
]
if self.uid is not None and info[2] != int(self.uid):
@ -1402,6 +1402,11 @@ class OpenBSDUser(User):
cmd.append('-L')
cmd.append(self.login_class)
if self.password_lock and not info[1].startswith('*'):
cmd.append('-Z')
elif self.password_lock is False and info[1].startswith('*'):
cmd.append('-U')
if self.update_password == 'always' and self.password is not None \
and self.password != '*' and info[1] != self.password:
cmd.append('-p')
@ -1562,9 +1567,9 @@ class NetBSDUser(User):
cmd.append('-p')
cmd.append(self.password)
if self.password_lock:
if self.password_lock and not info[1].startswith('*LOCKED*'):
cmd.append('-C yes')
elif self.password_lock is not None:
elif self.password_lock is False and info[1].startswith('*LOCKED*'):
cmd.append('-C no')
# skip if no changes to be made