user - consistently create user home directory on Linux (#71952)
Always use create_homedir when we are asked to create a home directory in the User class. Don't use the -m and -k parameters from useradd / luseradd as they behave differently with respect to preexisting home directories. Instead always specify -M to ensure that useradd / luseradd do not try to create the home directory. This does not change potential different behaviours in child classes of the User class. Consider the new umask option from #73821 in create_homedir as well as we do not let luseradd / useradd create the home directory any longer.
This commit is contained in:
parent
2e97240c67
commit
2f7e0b8489
5 changed files with 88 additions and 31 deletions
4
changelogs/fragments/fix_create_home.yml
Normal file
4
changelogs/fragments/fix_create_home.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
bugfixes:
|
||||
- >-
|
||||
user - properly create home path on Linux when ``local: yes`` and parent directories
|
||||
specified in ``home`` do not exist (https://github.com/ansible/ansible/pull/71952/)
|
|
@ -685,13 +685,8 @@ class User(object):
|
|||
cmd.append(self.comment)
|
||||
|
||||
if self.home is not None:
|
||||
# If the specified path to the user home contains parent directories that
|
||||
# do not exist and create_home is True first create the parent directory
|
||||
# since useradd cannot create it.
|
||||
if self.create_home:
|
||||
parent = os.path.dirname(self.home)
|
||||
if not os.path.isdir(parent):
|
||||
self.create_homedir(self.home)
|
||||
self.create_homedir(self.home)
|
||||
cmd.append('-d')
|
||||
cmd.append(self.home)
|
||||
|
||||
|
@ -713,19 +708,7 @@ class User(object):
|
|||
else:
|
||||
cmd.append(self.password)
|
||||
|
||||
if self.create_home:
|
||||
if not self.local:
|
||||
cmd.append('-m')
|
||||
|
||||
if self.skeleton is not None:
|
||||
cmd.append('-k')
|
||||
cmd.append(self.skeleton)
|
||||
|
||||
if self.umask is not None:
|
||||
cmd.append('-K')
|
||||
cmd.append('UMASK=' + self.umask)
|
||||
else:
|
||||
cmd.append('-M')
|
||||
cmd.append('-M')
|
||||
|
||||
if self.system:
|
||||
cmd.append('-r')
|
||||
|
@ -1250,18 +1233,26 @@ class User(object):
|
|||
os.makedirs(path)
|
||||
except OSError as e:
|
||||
self.module.exit_json(failed=True, msg="%s" % to_native(e))
|
||||
# get umask from /etc/login.defs and set correct home mode
|
||||
if os.path.exists(self.LOGIN_DEFS):
|
||||
with open(self.LOGIN_DEFS, 'r') as f:
|
||||
for line in f:
|
||||
m = re.match(r'^UMASK\s+(\d+)$', line)
|
||||
if m:
|
||||
umask = int(m.group(1), 8)
|
||||
mode = 0o777 & ~umask
|
||||
try:
|
||||
os.chmod(path, mode)
|
||||
except OSError as e:
|
||||
self.module.exit_json(failed=True, msg="%s" % to_native(e))
|
||||
umask_string = None
|
||||
# If an umask was set take it from there
|
||||
if self.umask is not None:
|
||||
umask_string = self.umask
|
||||
else:
|
||||
# try to get umask from /etc/login.defs
|
||||
if os.path.exists(self.LOGIN_DEFS):
|
||||
with open(self.LOGIN_DEFS, 'r') as f:
|
||||
for line in f:
|
||||
m = re.match(r'^UMASK\s+(\d+)$', line)
|
||||
if m:
|
||||
umask_string = m.group(1)
|
||||
# set correct home mode if we have a umask
|
||||
if umask_string is not None:
|
||||
umask = int(umask_string, 8)
|
||||
mode = 0o777 & ~umask
|
||||
try:
|
||||
os.chmod(path, mode)
|
||||
except OSError as e:
|
||||
self.module.exit_json(failed=True, msg="%s" % to_native(e))
|
||||
|
||||
def chown_homedir(self, uid, gid, path):
|
||||
try:
|
||||
|
|
|
@ -167,3 +167,6 @@
|
|||
|
||||
- name: Test expires for local users
|
||||
import_tasks: test_local_expires.yml
|
||||
|
||||
- name: Test missing home directory parent directory for local users
|
||||
import_tasks: test_local_missing_parent_dir.yml
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
# Create a new local user account with a path that has parent directories that do not exist
|
||||
- name: Create local user with home path that has parents that do not exist
|
||||
user:
|
||||
name: ansibulluser2
|
||||
state: present
|
||||
local: yes
|
||||
home: "{{ user_home_prefix[ansible_facts.system] }}/in2deep/ansibulluser2"
|
||||
register: create_home_local_with_no_parent_1
|
||||
tags:
|
||||
- user_test_local_mode
|
||||
|
||||
- name: Create local user with home path that has parents that do not exist again
|
||||
user:
|
||||
name: ansibulluser2
|
||||
state: present
|
||||
local: yes
|
||||
home: "{{ user_home_prefix[ansible_facts.system] }}/in2deep/ansibulluser2"
|
||||
register: create_home_local_with_no_parent_2
|
||||
tags:
|
||||
- user_test_local_mode
|
||||
|
||||
- name: Check the created home directory
|
||||
stat:
|
||||
path: "{{ user_home_prefix[ansible_facts.system] }}/in2deep/ansibulluser2"
|
||||
register: home_local_with_no_parent_3
|
||||
tags:
|
||||
- user_test_local_mode
|
||||
|
||||
- name: Ensure user with non-existing parent paths was created successfully
|
||||
assert:
|
||||
that:
|
||||
- create_home_local_with_no_parent_1 is changed
|
||||
- create_home_local_with_no_parent_1.home == user_home_prefix[ansible_facts.system] ~ '/in2deep/ansibulluser2'
|
||||
- create_home_local_with_no_parent_2 is not changed
|
||||
- home_local_with_no_parent_3.stat.uid == create_home_local_with_no_parent_1.uid
|
||||
- home_local_with_no_parent_3.stat.gr_name == default_local_user_group[ansible_facts.distribution] | default('ansibulluser2')
|
||||
tags:
|
||||
- user_test_local_mode
|
||||
|
||||
- name: Cleanup test account
|
||||
user:
|
||||
name: ansibulluser2
|
||||
home: "{{ user_home_prefix[ansible_facts.system] }}/in2deep/ansibulluser2"
|
||||
state: absent
|
||||
local: yes
|
||||
remove: yes
|
||||
tags:
|
||||
- user_test_local_mode
|
||||
|
||||
- name: Remove testing dir
|
||||
file:
|
||||
path: "{{ user_home_prefix[ansible_facts.system] }}/in2deep/"
|
||||
state: absent
|
||||
tags:
|
||||
- user_test_local_mode
|
|
@ -11,3 +11,6 @@ status_command:
|
|||
default_user_group:
|
||||
openSUSE Leap: users
|
||||
MacOSX: admin
|
||||
|
||||
default_local_user_group:
|
||||
MacOSX: admin
|
||||
|
|
Loading…
Reference in a new issue