|
|
@ -106,6 +106,10 @@ options:
|
|
|
|
description:
|
|
|
|
description:
|
|
|
|
- When used with C(state=absent), behavior is as with
|
|
|
|
- When used with C(state=absent), behavior is as with
|
|
|
|
C(userdel --force).
|
|
|
|
C(userdel --force).
|
|
|
|
|
|
|
|
login_class:
|
|
|
|
|
|
|
|
required: false
|
|
|
|
|
|
|
|
description:
|
|
|
|
|
|
|
|
- Optionally sets the user's login class for FreeBSD, OpenBSD and NetBSD systems.
|
|
|
|
remove:
|
|
|
|
remove:
|
|
|
|
required: false
|
|
|
|
required: false
|
|
|
|
default: "no"
|
|
|
|
default: "no"
|
|
|
@ -215,6 +219,7 @@ class User(object):
|
|
|
|
self.remove = module.params['remove']
|
|
|
|
self.remove = module.params['remove']
|
|
|
|
self.createhome = module.params['createhome']
|
|
|
|
self.createhome = module.params['createhome']
|
|
|
|
self.system = module.params['system']
|
|
|
|
self.system = module.params['system']
|
|
|
|
|
|
|
|
self.login_class = module.params['login_class']
|
|
|
|
self.append = module.params['append']
|
|
|
|
self.append = module.params['append']
|
|
|
|
self.sshkeygen = module.params['generate_ssh_key']
|
|
|
|
self.sshkeygen = module.params['generate_ssh_key']
|
|
|
|
self.ssh_bits = module.params['ssh_key_bits']
|
|
|
|
self.ssh_bits = module.params['ssh_key_bits']
|
|
|
@ -526,7 +531,7 @@ class FreeBsdUser(User):
|
|
|
|
This is a FreeBSD User manipulation class - it uses the pw command
|
|
|
|
This is a FreeBSD User manipulation class - it uses the pw command
|
|
|
|
to manipulate the user database, followed by the chpass command
|
|
|
|
to manipulate the user database, followed by the chpass command
|
|
|
|
to change the password.
|
|
|
|
to change the password.
|
|
|
|
|
|
|
|
|
|
|
|
This overrides the following methods from the generic class:-
|
|
|
|
This overrides the following methods from the generic class:-
|
|
|
|
- create_user()
|
|
|
|
- create_user()
|
|
|
|
- remove_user()
|
|
|
|
- remove_user()
|
|
|
@ -554,7 +559,7 @@ class FreeBsdUser(User):
|
|
|
|
self.module.get_bin_path('pw', True),
|
|
|
|
self.module.get_bin_path('pw', True),
|
|
|
|
'useradd',
|
|
|
|
'useradd',
|
|
|
|
'-n',
|
|
|
|
'-n',
|
|
|
|
self.name
|
|
|
|
self.name,
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
if self.uid is not None:
|
|
|
|
if self.uid is not None:
|
|
|
@ -590,6 +595,10 @@ class FreeBsdUser(User):
|
|
|
|
cmd.append('-s')
|
|
|
|
cmd.append('-s')
|
|
|
|
cmd.append(self.shell)
|
|
|
|
cmd.append(self.shell)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.login_class is not None:
|
|
|
|
|
|
|
|
cmd.append('-L')
|
|
|
|
|
|
|
|
cmd.append(self.login_class)
|
|
|
|
|
|
|
|
|
|
|
|
# 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)
|
|
|
@ -645,6 +654,10 @@ class FreeBsdUser(User):
|
|
|
|
cmd.append('-s')
|
|
|
|
cmd.append('-s')
|
|
|
|
cmd.append(self.shell)
|
|
|
|
cmd.append(self.shell)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.login_class is not None:
|
|
|
|
|
|
|
|
cmd.append('-L')
|
|
|
|
|
|
|
|
cmd.append(self.login_class)
|
|
|
|
|
|
|
|
|
|
|
|
if self.groups is not None:
|
|
|
|
if self.groups is not None:
|
|
|
|
current_groups = self.user_group_membership()
|
|
|
|
current_groups = self.user_group_membership()
|
|
|
|
groups = self.get_groups_set()
|
|
|
|
groups = self.get_groups_set()
|
|
|
@ -690,6 +703,308 @@ class FreeBsdUser(User):
|
|
|
|
|
|
|
|
|
|
|
|
# ===========================================
|
|
|
|
# ===========================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OpenBSDUser(User):
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
This is a OpenBSD User manipulation class.
|
|
|
|
|
|
|
|
Main differences are that OpenBSD:-
|
|
|
|
|
|
|
|
- has no concept of "system" account.
|
|
|
|
|
|
|
|
- has no force delete user
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This overrides the following methods from the generic class:-
|
|
|
|
|
|
|
|
- create_user()
|
|
|
|
|
|
|
|
- remove_user()
|
|
|
|
|
|
|
|
- modify_user()
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
platform = 'OpenBSD'
|
|
|
|
|
|
|
|
distribution = None
|
|
|
|
|
|
|
|
SHADOWFILE = '/etc/master.passwd'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_user(self):
|
|
|
|
|
|
|
|
cmd = [self.module.get_bin_path('useradd', True)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.uid is not None:
|
|
|
|
|
|
|
|
cmd.append('-u')
|
|
|
|
|
|
|
|
cmd.append(self.uid)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.non_unique:
|
|
|
|
|
|
|
|
cmd.append('-o')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.group is not None:
|
|
|
|
|
|
|
|
if not self.group_exists(self.group):
|
|
|
|
|
|
|
|
self.module.fail_json(msg="Group %s does not exist" % self.group)
|
|
|
|
|
|
|
|
cmd.append('-g')
|
|
|
|
|
|
|
|
cmd.append(self.group)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.groups is not None:
|
|
|
|
|
|
|
|
groups = self.get_groups_set()
|
|
|
|
|
|
|
|
cmd.append('-G')
|
|
|
|
|
|
|
|
cmd.append(','.join(groups))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.comment is not None:
|
|
|
|
|
|
|
|
cmd.append('-c')
|
|
|
|
|
|
|
|
cmd.append(self.comment)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.home is not None:
|
|
|
|
|
|
|
|
cmd.append('-d')
|
|
|
|
|
|
|
|
cmd.append(self.home)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.shell is not None:
|
|
|
|
|
|
|
|
cmd.append('-s')
|
|
|
|
|
|
|
|
cmd.append(self.shell)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.login_class is not None:
|
|
|
|
|
|
|
|
cmd.append('-L')
|
|
|
|
|
|
|
|
cmd.append(self.login_class)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.password is not None:
|
|
|
|
|
|
|
|
cmd.append('-p')
|
|
|
|
|
|
|
|
cmd.append(self.password)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.createhome:
|
|
|
|
|
|
|
|
cmd.append('-m')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd.append(self.name)
|
|
|
|
|
|
|
|
return self.execute_command(cmd)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def remove_user_userdel(self):
|
|
|
|
|
|
|
|
cmd = [self.module.get_bin_path('userdel', True)]
|
|
|
|
|
|
|
|
if self.remove:
|
|
|
|
|
|
|
|
cmd.append('-r')
|
|
|
|
|
|
|
|
cmd.append(self.name)
|
|
|
|
|
|
|
|
return self.execute_command(cmd)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def modify_user(self):
|
|
|
|
|
|
|
|
cmd = [self.module.get_bin_path('usermod', True)]
|
|
|
|
|
|
|
|
info = self.user_info()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.uid is not None and info[2] != int(self.uid):
|
|
|
|
|
|
|
|
cmd.append('-u')
|
|
|
|
|
|
|
|
cmd.append(self.uid)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.non_unique:
|
|
|
|
|
|
|
|
cmd.append('-o')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.group is not None:
|
|
|
|
|
|
|
|
if not self.group_exists(self.group):
|
|
|
|
|
|
|
|
self.module.fail_json(msg="Group %s does not exist" % self.group)
|
|
|
|
|
|
|
|
ginfo = self.group_info(self.group)
|
|
|
|
|
|
|
|
if info[3] != ginfo[2]:
|
|
|
|
|
|
|
|
cmd.append('-g')
|
|
|
|
|
|
|
|
cmd.append(self.group)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.groups is not None:
|
|
|
|
|
|
|
|
current_groups = self.user_group_membership()
|
|
|
|
|
|
|
|
groups_need_mod = False
|
|
|
|
|
|
|
|
groups_option = '-G'
|
|
|
|
|
|
|
|
groups = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.groups == '':
|
|
|
|
|
|
|
|
if current_groups and not self.append:
|
|
|
|
|
|
|
|
groups_need_mod = True
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
groups = self.get_groups_set()
|
|
|
|
|
|
|
|
group_diff = set(current_groups).symmetric_difference(groups)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if group_diff:
|
|
|
|
|
|
|
|
if self.append:
|
|
|
|
|
|
|
|
for g in groups:
|
|
|
|
|
|
|
|
if g in group_diff:
|
|
|
|
|
|
|
|
groups_option = '-S'
|
|
|
|
|
|
|
|
groups_need_mod = True
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
groups_need_mod = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if groups_need_mod:
|
|
|
|
|
|
|
|
cmd.append(groups_option)
|
|
|
|
|
|
|
|
cmd.append(','.join(groups))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.comment is not None and info[4] != self.comment:
|
|
|
|
|
|
|
|
cmd.append('-c')
|
|
|
|
|
|
|
|
cmd.append(self.comment)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.home is not None and info[5] != self.home:
|
|
|
|
|
|
|
|
cmd.append('-d')
|
|
|
|
|
|
|
|
cmd.append(self.home)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.shell is not None and info[6] != self.shell:
|
|
|
|
|
|
|
|
cmd.append('-s')
|
|
|
|
|
|
|
|
cmd.append(self.shell)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.login_class is not None:
|
|
|
|
|
|
|
|
cmd.append('-L')
|
|
|
|
|
|
|
|
cmd.append(self.login_class)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.password is not None and info[1] != self.password:
|
|
|
|
|
|
|
|
cmd.append('-p')
|
|
|
|
|
|
|
|
cmd.append(self.password)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# skip if no changes to be made
|
|
|
|
|
|
|
|
if len(cmd) == 1:
|
|
|
|
|
|
|
|
return (None, '', '')
|
|
|
|
|
|
|
|
elif self.module.check_mode:
|
|
|
|
|
|
|
|
return (0, '', '')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd.append(self.name)
|
|
|
|
|
|
|
|
return self.execute_command(cmd)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===========================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NetBSDUser(User):
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
This is a NetBSD User manipulation class.
|
|
|
|
|
|
|
|
Main differences are that NetBSD:-
|
|
|
|
|
|
|
|
- has no concept of "system" account.
|
|
|
|
|
|
|
|
- has no force delete user
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This overrides the following methods from the generic class:-
|
|
|
|
|
|
|
|
- create_user()
|
|
|
|
|
|
|
|
- remove_user()
|
|
|
|
|
|
|
|
- modify_user()
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
platform = 'NetBSD'
|
|
|
|
|
|
|
|
distribution = None
|
|
|
|
|
|
|
|
SHADOWFILE = '/etc/master.passwd'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_user(self):
|
|
|
|
|
|
|
|
cmd = [self.module.get_bin_path('useradd', True)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.uid is not None:
|
|
|
|
|
|
|
|
cmd.append('-u')
|
|
|
|
|
|
|
|
cmd.append(self.uid)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.non_unique:
|
|
|
|
|
|
|
|
cmd.append('-o')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.group is not None:
|
|
|
|
|
|
|
|
if not self.group_exists(self.group):
|
|
|
|
|
|
|
|
self.module.fail_json(msg="Group %s does not exist" % self.group)
|
|
|
|
|
|
|
|
cmd.append('-g')
|
|
|
|
|
|
|
|
cmd.append(self.group)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.groups is not None:
|
|
|
|
|
|
|
|
groups = self.get_groups_set()
|
|
|
|
|
|
|
|
if len(groups) > 16:
|
|
|
|
|
|
|
|
self.module.fail_json(msg="Too many groups (%d) NetBSD allows for 16 max." % len(groups))
|
|
|
|
|
|
|
|
cmd.append('-G')
|
|
|
|
|
|
|
|
cmd.append(','.join(groups))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.comment is not None:
|
|
|
|
|
|
|
|
cmd.append('-c')
|
|
|
|
|
|
|
|
cmd.append(self.comment)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.home is not None:
|
|
|
|
|
|
|
|
cmd.append('-d')
|
|
|
|
|
|
|
|
cmd.append(self.home)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.shell is not None:
|
|
|
|
|
|
|
|
cmd.append('-s')
|
|
|
|
|
|
|
|
cmd.append(self.shell)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.login_class is not None:
|
|
|
|
|
|
|
|
cmd.append('-L')
|
|
|
|
|
|
|
|
cmd.append(self.login_class)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.password is not None:
|
|
|
|
|
|
|
|
cmd.append('-p')
|
|
|
|
|
|
|
|
cmd.append(self.password)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.createhome:
|
|
|
|
|
|
|
|
cmd.append('-m')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd.append(self.name)
|
|
|
|
|
|
|
|
return self.execute_command(cmd)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def remove_user_userdel(self):
|
|
|
|
|
|
|
|
cmd = [self.module.get_bin_path('userdel', True)]
|
|
|
|
|
|
|
|
if self.remove:
|
|
|
|
|
|
|
|
cmd.append('-r')
|
|
|
|
|
|
|
|
cmd.append(self.name)
|
|
|
|
|
|
|
|
return self.execute_command(cmd)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def modify_user(self):
|
|
|
|
|
|
|
|
cmd = [self.module.get_bin_path('usermod', True)]
|
|
|
|
|
|
|
|
info = self.user_info()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.uid is not None and info[2] != int(self.uid):
|
|
|
|
|
|
|
|
cmd.append('-u')
|
|
|
|
|
|
|
|
cmd.append(self.uid)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.non_unique:
|
|
|
|
|
|
|
|
cmd.append('-o')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.group is not None:
|
|
|
|
|
|
|
|
if not self.group_exists(self.group):
|
|
|
|
|
|
|
|
self.module.fail_json(msg="Group %s does not exist" % self.group)
|
|
|
|
|
|
|
|
ginfo = self.group_info(self.group)
|
|
|
|
|
|
|
|
if info[3] != ginfo[2]:
|
|
|
|
|
|
|
|
cmd.append('-g')
|
|
|
|
|
|
|
|
cmd.append(self.group)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.groups is not None:
|
|
|
|
|
|
|
|
current_groups = self.user_group_membership()
|
|
|
|
|
|
|
|
groups_need_mod = False
|
|
|
|
|
|
|
|
groups = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.groups == '':
|
|
|
|
|
|
|
|
if current_groups and not self.append:
|
|
|
|
|
|
|
|
groups_need_mod = True
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
groups = self.get_groups_set()
|
|
|
|
|
|
|
|
group_diff = set(current_groups).symmetric_difference(groups)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if group_diff:
|
|
|
|
|
|
|
|
if self.append:
|
|
|
|
|
|
|
|
for g in groups:
|
|
|
|
|
|
|
|
if g in group_diff:
|
|
|
|
|
|
|
|
groups = set(current_groups).union(groups)
|
|
|
|
|
|
|
|
groups_need_mod = True
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
groups_need_mod = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if groups_need_mod:
|
|
|
|
|
|
|
|
if len(groups) > 16:
|
|
|
|
|
|
|
|
self.module.fail_json(msg="Too many groups (%d) NetBSD allows for 16 max." % len(groups))
|
|
|
|
|
|
|
|
cmd.append('-G')
|
|
|
|
|
|
|
|
cmd.append(','.join(groups))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.comment is not None and info[4] != self.comment:
|
|
|
|
|
|
|
|
cmd.append('-c')
|
|
|
|
|
|
|
|
cmd.append(self.comment)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.home is not None and info[5] != self.home:
|
|
|
|
|
|
|
|
cmd.append('-d')
|
|
|
|
|
|
|
|
cmd.append(self.home)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.shell is not None and info[6] != self.shell:
|
|
|
|
|
|
|
|
cmd.append('-s')
|
|
|
|
|
|
|
|
cmd.append(self.shell)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.login_class is not None:
|
|
|
|
|
|
|
|
cmd.append('-L')
|
|
|
|
|
|
|
|
cmd.append(self.login_class)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.password is not None and info[1] != self.password:
|
|
|
|
|
|
|
|
cmd.append('-p')
|
|
|
|
|
|
|
|
cmd.append(self.password)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# skip if no changes to be made
|
|
|
|
|
|
|
|
if len(cmd) == 1:
|
|
|
|
|
|
|
|
return (None, '', '')
|
|
|
|
|
|
|
|
elif self.module.check_mode:
|
|
|
|
|
|
|
|
return (0, '', '')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd.append(self.name)
|
|
|
|
|
|
|
|
return self.execute_command(cmd)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===========================================
|
|
|
|
|
|
|
|
|
|
|
|
class SunOS(User):
|
|
|
|
class SunOS(User):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
This is a SunOS User manipulation class - The main difference between
|
|
|
|
This is a SunOS User manipulation class - The main difference between
|
|
|
@ -1024,6 +1339,7 @@ def main():
|
|
|
|
home=dict(default=None, type='str'),
|
|
|
|
home=dict(default=None, type='str'),
|
|
|
|
shell=dict(default=None, type='str'),
|
|
|
|
shell=dict(default=None, type='str'),
|
|
|
|
password=dict(default=None, type='str'),
|
|
|
|
password=dict(default=None, type='str'),
|
|
|
|
|
|
|
|
login_class=dict(default=None, type='str'),
|
|
|
|
# following options are specific to userdel
|
|
|
|
# following options are specific to userdel
|
|
|
|
force=dict(default='no', type='bool'),
|
|
|
|
force=dict(default='no', type='bool'),
|
|
|
|
remove=dict(default='no', type='bool'),
|
|
|
|
remove=dict(default='no', type='bool'),
|
|
|
|