user: add expired state

ported from
https://github.com/ansible/ansible/pull/6303

It's very useful and routine to disable a *nix user.
I implemented expired instead of locked because this prevents any use of
the account, safer than just preventing password-based authentication.

I have tests [1], but since none of the suite came along with the core
modules, I'm unsure how to submit them.

[1] https://github.com/billwanjohi/ansible/blob/add_locked_state/test/integration/roles/test_user/tasks/main.yml
This commit is contained in:
billwanjohi 2014-09-29 22:42:28 +00:00
parent db5668b84c
commit ff36edbb11

View file

@ -84,10 +84,12 @@ options:
state: state:
required: false required: false
default: "present" default: "present"
choices: [ present, absent ] choices: [ present, absent, expired ]
description: description:
- Whether the account should exist. When C(absent), removes - Whether the account should exist, and whether it is expired.
the user account. When C(absent), removes the user account.
When C(expired), the user will not be able to login through any means.
Expired state is only implemented for Linux.
createhome: createhome:
required: false required: false
default: "yes" default: "yes"
@ -318,6 +320,10 @@ class User(object):
cmd.append('-s') cmd.append('-s')
cmd.append(self.shell) cmd.append(self.shell)
if self.state == 'expired':
cmd.append('--expiredate')
cmd.append('1')
if self.password is not None: if self.password is not None:
cmd.append('-p') cmd.append('-p')
cmd.append(self.password) cmd.append(self.password)
@ -424,6 +430,10 @@ class User(object):
cmd.append('-s') cmd.append('-s')
cmd.append(self.shell) cmd.append(self.shell)
if self.state == 'expired':
cmd.append('--expiredate')
cmd.append('1')
if self.update_password == 'always' and self.password is not None and info[1] != self.password: if self.update_password == 'always' and self.password is not None and info[1] != self.password:
cmd.append('-p') cmd.append('-p')
cmd.append(self.password) cmd.append(self.password)
@ -692,6 +702,10 @@ class FreeBsdUser(User):
cmd.append('-L') cmd.append('-L')
cmd.append(self.login_class) cmd.append(self.login_class)
if self.state == 'expired':
cmd.append('-e')
cmd.append('1970-01-01')
# system cannot be handled currently - should we error if its requested? # system cannot be handled currently - should we error if its requested?
# create the user # create the user
(rc, out, err) = self.execute_command(cmd) (rc, out, err) = self.execute_command(cmd)
@ -776,6 +790,10 @@ class FreeBsdUser(User):
new_groups = groups | set(current_groups) new_groups = groups | set(current_groups)
cmd.append(','.join(new_groups)) cmd.append(','.join(new_groups))
if self.state == 'expired':
cmd.append('-e')
cmd.append('1970-01-01')
# modify the user if cmd will do anything # modify the user if cmd will do anything
if cmd_len != len(cmd): if cmd_len != len(cmd):
(rc, out, err) = self.execute_command(cmd) (rc, out, err) = self.execute_command(cmd)
@ -852,6 +870,10 @@ class OpenBSDUser(User):
cmd.append('-L') cmd.append('-L')
cmd.append(self.login_class) cmd.append(self.login_class)
if self.state == 'expired':
cmd.append('-e')
cmd.append('1')
if self.password is not None: if self.password is not None:
cmd.append('-p') cmd.append('-p')
cmd.append(self.password) cmd.append(self.password)
@ -946,6 +968,10 @@ class OpenBSDUser(User):
cmd.append('-L') cmd.append('-L')
cmd.append(self.login_class) cmd.append(self.login_class)
if self.state == 'expired':
cmd.append('-e')
cmd.append('1')
if self.update_password == 'always' and self.password is not None and info[1] != self.password: if self.update_password == 'always' and self.password is not None and info[1] != self.password:
cmd.append('-p') cmd.append('-p')
cmd.append(self.password) cmd.append(self.password)
@ -1019,6 +1045,10 @@ class NetBSDUser(User):
cmd.append('-L') cmd.append('-L')
cmd.append(self.login_class) cmd.append(self.login_class)
if self.state == 'expired':
cmd.append('-e')
cmd.append('1')
if self.password is not None: if self.password is not None:
cmd.append('-p') cmd.append('-p')
cmd.append(self.password) cmd.append(self.password)
@ -1101,6 +1131,10 @@ class NetBSDUser(User):
cmd.append('-L') cmd.append('-L')
cmd.append(self.login_class) cmd.append(self.login_class)
if self.state == 'expired':
cmd.append('-e')
cmd.append('1')
if self.update_password == 'always' and self.password is not None and info[1] != self.password: if self.update_password == 'always' and self.password is not None and info[1] != self.password:
cmd.append('-p') cmd.append('-p')
cmd.append(self.password) cmd.append(self.password)
@ -1178,6 +1212,10 @@ class SunOS(User):
if self.createhome: if self.createhome:
cmd.append('-m') cmd.append('-m')
if self.state == 'expired':
cmd.append('-e')
cmd.append('1/1/70')
cmd.append(self.name) cmd.append(self.name)
if self.module.check_mode: if self.module.check_mode:
@ -1262,6 +1300,10 @@ class SunOS(User):
cmd.append('-s') cmd.append('-s')
cmd.append(self.shell) cmd.append(self.shell)
if self.state == 'expired':
cmd.append('-e')
cmd.append('1/1/70')
if self.module.check_mode: if self.module.check_mode:
return (0, '', '') return (0, '', '')
else: else:
@ -1351,6 +1393,10 @@ class AIX(User):
if self.createhome: if self.createhome:
cmd.append('-m') cmd.append('-m')
if self.state == 'expired':
cmd.append('-e')
cmd.append('0101000070')
cmd.append(self.name) cmd.append(self.name)
(rc, out, err) = self.execute_command(cmd) (rc, out, err) = self.execute_command(cmd)
@ -1420,6 +1466,9 @@ class AIX(User):
cmd.append('-s') cmd.append('-s')
cmd.append(self.shell) cmd.append(self.shell)
if self.state == 'expired':
cmd.append('-e')
cmd.append('0101000070')
# skip if no changes to be made # skip if no changes to be made
if len(cmd) == 1: if len(cmd) == 1:
@ -1457,7 +1506,7 @@ def main():
} }
module = AnsibleModule( module = AnsibleModule(
argument_spec = dict( argument_spec = dict(
state=dict(default='present', choices=['present', 'absent'], type='str'), state=dict(default='present', choices=['present', 'absent', 'expired'], type='str'),
name=dict(required=True, aliases=['user'], type='str'), name=dict(required=True, aliases=['user'], type='str'),
uid=dict(default=None, type='str'), uid=dict(default=None, type='str'),
non_unique=dict(default='no', type='bool'), non_unique=dict(default='no', type='bool'),
@ -1512,7 +1561,10 @@ def main():
module.fail_json(name=user.name, msg=err, rc=rc) module.fail_json(name=user.name, msg=err, rc=rc)
result['force'] = user.force result['force'] = user.force
result['remove'] = user.remove result['remove'] = user.remove
elif user.state == 'present': elif user.state == 'expired' and user.platform != 'Generic':
module.fail_json(name=user.state,
msg='expired state not yet support for {0} platform'.format(user.platform))
elif user.state == 'present' or user.state == 'expired':
if not user.user_exists(): if not user.user_exists():
if module.check_mode: if module.check_mode:
module.exit_json(changed=True) module.exit_json(changed=True)