mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-01-13 08:05:19 +01:00
Compare commits
1 commit
f66b86a830
...
95f1f90278
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95f1f90278 |
2 changed files with 22 additions and 50 deletions
|
|
@ -1,3 +0,0 @@
|
||||||
---
|
|
||||||
bugfixes:
|
|
||||||
- acl - Fixed to set ACLs on paths mounted with NFS version 4 correctly (https://github.com/ansible-collections/ansible.posix/issues/240).
|
|
||||||
|
|
@ -75,10 +75,6 @@ options:
|
||||||
use_nfsv4_acls:
|
use_nfsv4_acls:
|
||||||
description:
|
description:
|
||||||
- Use NFSv4 ACLs instead of POSIX ACLs.
|
- Use NFSv4 ACLs instead of POSIX ACLs.
|
||||||
- This feature uses C(nfs4_setfacl) and C(nfs4_getfacl). The behavior depends on those implementation.
|
|
||||||
And currently it only supports C(A) in ACE, so C(D) must be replaced with the appropriate C(A).
|
|
||||||
- Permission is set as optimised ACLs by the system. You can check the actual ACLs that has been set using the return value.
|
|
||||||
- More info C(man nfs4_setfacl)
|
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
recalculate_mask:
|
recalculate_mask:
|
||||||
|
|
@ -183,7 +179,7 @@ def split_entry(entry):
|
||||||
def build_entry(etype, entity, permissions=None, use_nfsv4_acls=False):
|
def build_entry(etype, entity, permissions=None, use_nfsv4_acls=False):
|
||||||
'''Builds and returns an entry string. Does not include the permissions bit if they are not provided.'''
|
'''Builds and returns an entry string. Does not include the permissions bit if they are not provided.'''
|
||||||
if use_nfsv4_acls:
|
if use_nfsv4_acls:
|
||||||
return ':'.join(['A', 'g' if etype == 'group' else '', entity, permissions + 'tcy'])
|
return ':'.join([etype, entity, permissions, 'allow'])
|
||||||
|
|
||||||
if permissions:
|
if permissions:
|
||||||
return etype + ':' + entity + ':' + permissions
|
return etype + ':' + entity + ':' + permissions
|
||||||
|
|
@ -191,27 +187,22 @@ def build_entry(etype, entity, permissions=None, use_nfsv4_acls=False):
|
||||||
return etype + ':' + entity
|
return etype + ':' + entity
|
||||||
|
|
||||||
|
|
||||||
def build_command(module, mode, path, follow, default, recursive, recalculate_mask, use_nfsv4_acls, entry=''):
|
def build_command(module, mode, path, follow, default, recursive, recalculate_mask, entry=''):
|
||||||
'''Builds and returns a getfacl/setfacl command.'''
|
'''Builds and returns a getfacl/setfacl command.'''
|
||||||
if mode == 'set':
|
if mode == 'set':
|
||||||
cmd = [module.get_bin_path('nfs4_setfacl' if use_nfsv4_acls else 'setfacl', True)]
|
cmd = [module.get_bin_path('setfacl', True)]
|
||||||
cmd.extend(['-a' if use_nfsv4_acls else '-m', entry])
|
cmd.extend(['-m', entry])
|
||||||
elif mode == 'rm':
|
elif mode == 'rm':
|
||||||
cmd = [module.get_bin_path('nfs4_setfacl' if use_nfsv4_acls else 'setfacl', True)]
|
cmd = [module.get_bin_path('setfacl', True)]
|
||||||
cmd.extend(['-x', entry])
|
cmd.extend(['-x', entry])
|
||||||
else: # mode == 'get'
|
else: # mode == 'get'
|
||||||
cmd = [module.get_bin_path('getfacl', True)]
|
cmd = [module.get_bin_path('getfacl', True)]
|
||||||
# prevents absolute path warnings and removes headers
|
# prevents absolute path warnings and removes headers
|
||||||
if platform.system().lower() == 'linux':
|
if platform.system().lower() == 'linux':
|
||||||
if use_nfsv4_acls:
|
|
||||||
# use nfs4_getfacl instead of getfacl if use_nfsv4_acls is True
|
|
||||||
cmd = [module.get_bin_path('nfs4_getfacl', True)]
|
|
||||||
else:
|
|
||||||
cmd = [module.get_bin_path('getfacl', True)]
|
|
||||||
cmd.append('--absolute-names')
|
|
||||||
cmd.append('--omit-header')
|
cmd.append('--omit-header')
|
||||||
|
cmd.append('--absolute-names')
|
||||||
|
|
||||||
if recursive and not use_nfsv4_acls:
|
if recursive:
|
||||||
cmd.append('--recursive')
|
cmd.append('--recursive')
|
||||||
|
|
||||||
if recalculate_mask == 'mask' and mode in ['set', 'rm']:
|
if recalculate_mask == 'mask' and mode in ['set', 'rm']:
|
||||||
|
|
@ -219,7 +210,7 @@ def build_command(module, mode, path, follow, default, recursive, recalculate_ma
|
||||||
elif recalculate_mask == 'no_mask' and mode in ['set', 'rm']:
|
elif recalculate_mask == 'no_mask' and mode in ['set', 'rm']:
|
||||||
cmd.append('--no-mask')
|
cmd.append('--no-mask')
|
||||||
|
|
||||||
if not follow and not use_nfsv4_acls:
|
if not follow:
|
||||||
if platform.system().lower() == 'linux':
|
if platform.system().lower() == 'linux':
|
||||||
cmd.append('--physical')
|
cmd.append('--physical')
|
||||||
elif platform.system().lower() == 'freebsd':
|
elif platform.system().lower() == 'freebsd':
|
||||||
|
|
@ -232,34 +223,24 @@ def build_command(module, mode, path, follow, default, recursive, recalculate_ma
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
def acl_changed(module, cmd, entry, use_nfsv4_acls=False):
|
def acl_changed(module, cmd):
|
||||||
'''Returns true if the provided command affects the existing ACLs, false otherwise.'''
|
'''Returns true if the provided command affects the existing ACLs, false otherwise.'''
|
||||||
# To check the ACL changes, use the output of setfacl or nfs4_setfacl with '--test'.
|
# FreeBSD do not have a --test flag, so by default, it is safer to always say "true"
|
||||||
# FreeBSD do not have a --test flag, so by default, it is safer to always say "true".
|
|
||||||
if platform.system().lower() == 'freebsd':
|
if platform.system().lower() == 'freebsd':
|
||||||
return True
|
return True
|
||||||
|
|
||||||
cmd = cmd[:] # lists are mutables so cmd would be overwritten without this
|
cmd = cmd[:] # lists are mutables so cmd would be overwritten without this
|
||||||
cmd.insert(1, '--test')
|
cmd.insert(1, '--test')
|
||||||
lines = run_acl(module, cmd)
|
lines = run_acl(module, cmd)
|
||||||
counter = 0
|
|
||||||
for line in lines:
|
|
||||||
if line.endswith('*,*') and not use_nfsv4_acls:
|
|
||||||
return False
|
|
||||||
# if use_nfsv4_acls and entry is listed
|
|
||||||
if use_nfsv4_acls and entry == line:
|
|
||||||
counter += 1
|
|
||||||
|
|
||||||
# The current 'nfs4_setfacl --test' lists a new entry,
|
for line in lines:
|
||||||
# which will be added at the top of list, followed by the existing entries.
|
if not line.endswith('*,*'):
|
||||||
# So if the entry has already been registered, the entry should be find twice.
|
|
||||||
if counter == 2:
|
|
||||||
return False
|
|
||||||
return True
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def run_acl(module, cmd, check_rc=True):
|
def run_acl(module, cmd, check_rc=True):
|
||||||
'''Runs the provided command and returns the output as a list of lines.'''
|
|
||||||
try:
|
try:
|
||||||
(rc, out, err) = module.run_command(cmd, check_rc=check_rc)
|
(rc, out, err) = module.run_command(cmd, check_rc=check_rc)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -332,7 +313,7 @@ def main():
|
||||||
module.fail_json(msg="'recalculate_mask' MUST NOT be set to 'mask' or 'no_mask' when 'state=query'.")
|
module.fail_json(msg="'recalculate_mask' MUST NOT be set to 'mask' or 'no_mask' when 'state=query'.")
|
||||||
|
|
||||||
if not entry:
|
if not entry:
|
||||||
if state == 'absent' and permissions and not use_nfsv4_acls:
|
if state == 'absent' and permissions:
|
||||||
module.fail_json(msg="'permissions' MUST NOT be set when 'state=absent'.")
|
module.fail_json(msg="'permissions' MUST NOT be set when 'state=absent'.")
|
||||||
|
|
||||||
if state == 'absent' and not entity:
|
if state == 'absent' and not entity:
|
||||||
|
|
@ -369,24 +350,21 @@ def main():
|
||||||
entry = build_entry(etype, entity, permissions, use_nfsv4_acls)
|
entry = build_entry(etype, entity, permissions, use_nfsv4_acls)
|
||||||
command = build_command(
|
command = build_command(
|
||||||
module, 'set', path, follow,
|
module, 'set', path, follow,
|
||||||
default, recursive, recalculate_mask, use_nfsv4_acls, entry
|
default, recursive, recalculate_mask, entry
|
||||||
)
|
)
|
||||||
changed = acl_changed(module, command, entry, use_nfsv4_acls)
|
changed = acl_changed(module, command)
|
||||||
|
|
||||||
if changed and not module.check_mode:
|
if changed and not module.check_mode:
|
||||||
run_acl(module, command)
|
run_acl(module, command)
|
||||||
msg = "%s is present" % entry
|
msg = "%s is present" % entry
|
||||||
|
|
||||||
elif state == 'absent':
|
elif state == 'absent':
|
||||||
if use_nfsv4_acls:
|
|
||||||
entry = build_entry(etype, entity, permissions, use_nfsv4_acls)
|
|
||||||
else:
|
|
||||||
entry = build_entry(etype, entity, use_nfsv4_acls)
|
entry = build_entry(etype, entity, use_nfsv4_acls)
|
||||||
command = build_command(
|
command = build_command(
|
||||||
module, 'rm', path, follow,
|
module, 'rm', path, follow,
|
||||||
default, recursive, recalculate_mask, use_nfsv4_acls, entry
|
default, recursive, recalculate_mask, entry
|
||||||
)
|
)
|
||||||
changed = acl_changed(module, command, entry, use_nfsv4_acls)
|
changed = acl_changed(module, command)
|
||||||
|
|
||||||
if changed and not module.check_mode:
|
if changed and not module.check_mode:
|
||||||
run_acl(module, command, False)
|
run_acl(module, command, False)
|
||||||
|
|
@ -397,10 +375,7 @@ def main():
|
||||||
|
|
||||||
acl = run_acl(
|
acl = run_acl(
|
||||||
module,
|
module,
|
||||||
build_command(
|
build_command(module, 'get', path, follow, default, recursive, recalculate_mask)
|
||||||
module, 'get', path, follow, default, recursive,
|
|
||||||
recalculate_mask, use_nfsv4_acls
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
module.exit_json(changed=changed, msg=msg, acl=acl)
|
module.exit_json(changed=changed, msg=msg, acl=acl)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue