%PDF- %PDF-
Direktori : /usr/lib/python2.7/site-packages/salt/states/ |
Current File : //usr/lib/python2.7/site-packages/salt/states/linux_acl.py |
# -*- coding: utf-8 -*- ''' Linux File Access Control Lists The Linux ACL state module requires the `getfacl` and `setfacl` binaries. Ensure a Linux ACL is present .. code-block:: yaml root: acl.present: - name: /root - acl_type: user - acl_name: damian - perms: rwx Ensure a Linux ACL does not exist .. code-block:: yaml root: acl.absent: - name: /root - acl_type: user - acl_name: damian - perms: rwx Ensure a Linux ACL list is present .. code-block:: yaml root: acl.list_present: - name: /root - acl_type: user - acl_name: - damian - homer - perms: rwx Ensure a Linux ACL list does not exist .. code-block:: yaml root: acl.list_absent: - name: /root - acl_type: user - acl_name: - damian - homer - perms: rwx ''' # Import Python libs from __future__ import absolute_import, print_function, unicode_literals import logging import os # Import salt libs from salt.ext import six from salt.exceptions import CommandExecutionError import salt.utils.path log = logging.getLogger(__name__) __virtualname__ = 'acl' def __virtual__(): ''' Ensure getfacl & setfacl exist ''' if salt.utils.path.which('getfacl') and salt.utils.path.which('setfacl'): return __virtualname__ return False, 'The linux_acl state cannot be loaded: the getfacl or setfacl binary is not in the path.' def present(name, acl_type, acl_name='', perms='', recurse=False, force=False): ''' Ensure a Linux ACL is present name The acl path acl_type The type of the acl is used for it can be 'user' or 'group' acl_name The user or group perms Set the permissions eg.: rwx recurse Set the permissions recursive in the path force Wipe out old permissions and ensure only the new permissions are set ''' ret = {'name': name, 'result': True, 'changes': {}, 'comment': ''} _octal = {'r': 4, 'w': 2, 'x': 1, '-': 0} _octal_lookup = {0: '-', 1: 'r', 2: 'w', 4: 'x'} if not os.path.exists(name): ret['comment'] = '{0} does not exist'.format(name) ret['result'] = False return ret __current_perms = __salt__['acl.getfacl'](name, recursive=recurse) if acl_type.startswith(('d:', 'default:')): _acl_type = ':'.join(acl_type.split(':')[1:]) _current_perms = __current_perms[name].get('defaults', {}) _default = True else: _acl_type = acl_type _current_perms = __current_perms[name] _default = False # The getfacl execution module lists default with empty names as being # applied to the user/group that owns the file, e.g., # default:group::rwx would be listed as default:group:root:rwx # In this case, if acl_name is empty, we really want to search for root # but still uses '' for other # We search through the dictionary getfacl returns for the owner of the # file if acl_name is empty. if acl_name == '': _search_name = __current_perms[name].get('comment').get(_acl_type, '') else: _search_name = acl_name if _current_perms.get(_acl_type, None) or _default: try: user = [i for i in _current_perms[_acl_type] if next(six.iterkeys(i)) == _search_name].pop() except (AttributeError, IndexError, StopIteration, KeyError): user = None if user: octal_sum = sum([_octal.get(i, i) for i in perms]) need_refresh = False for path in __current_perms: acl_found = False for user_acl in __current_perms[path].get(_acl_type, []): if _search_name in user_acl and user_acl[_search_name]['octal'] == octal_sum: acl_found = True break if not acl_found: need_refresh = True break if not need_refresh: ret['comment'] = 'Permissions are in the desired state' else: _num = user[_search_name]['octal'] new_perms = '{}{}{}'.format(_octal_lookup[_num & 1], _octal_lookup[_num & 2], _octal_lookup[_num & 4]) changes = {'new': {'acl_name': acl_name, 'acl_type': acl_type, 'perms': perms}, 'old': {'acl_name': acl_name, 'acl_type': acl_type, 'perms': new_perms}} if __opts__['test']: ret.update({'comment': 'Updated permissions will be applied for ' '{0}: {1} -> {2}'.format( acl_name, new_perms, perms), 'result': None, 'changes': changes}) return ret try: if force: __salt__['acl.wipefacls'](name, recursive=recurse, raise_err=True) __salt__['acl.modfacl'](acl_type, acl_name, perms, name, recursive=recurse, raise_err=True) ret.update({'comment': 'Updated permissions for ' '{0}'.format(acl_name), 'result': True, 'changes': changes}) except CommandExecutionError as exc: ret.update({'comment': 'Error updating permissions for ' '{0}: {1}'.format(acl_name, exc.strerror), 'result': False}) else: changes = {'new': {'acl_name': acl_name, 'acl_type': acl_type, 'perms': perms}} if __opts__['test']: ret.update({'comment': 'New permissions will be applied for ' '{0}: {1}'.format(acl_name, perms), 'result': None, 'changes': changes}) ret['result'] = None return ret try: if force: __salt__['acl.wipefacls'](name, recursive=recurse, raise_err=True) __salt__['acl.modfacl'](acl_type, acl_name, perms, name, recursive=recurse, raise_err=True) ret.update({'comment': 'Applied new permissions for ' '{0}'.format(acl_name), 'result': True, 'changes': changes}) except CommandExecutionError as exc: ret.update({'comment': 'Error updating permissions for {0}: ' '{1}'.format(acl_name, exc.strerror), 'result': False}) else: ret['comment'] = 'ACL Type does not exist' ret['result'] = False return ret def absent(name, acl_type, acl_name='', perms='', recurse=False): ''' Ensure a Linux ACL does not exist name The acl path acl_type The type of the acl is used for, it can be 'user' or 'group' acl_names The user or group perms Remove the permissions eg.: rwx recurse Set the permissions recursive in the path ''' ret = {'name': name, 'result': True, 'changes': {}, 'comment': ''} if not os.path.exists(name): ret['comment'] = '{0} does not exist'.format(name) ret['result'] = False return ret __current_perms = __salt__['acl.getfacl'](name, recursive=recurse) if acl_type.startswith(('d:', 'default:')): _acl_type = ':'.join(acl_type.split(':')[1:]) _current_perms = __current_perms[name].get('defaults', {}) _default = True else: _acl_type = acl_type _current_perms = __current_perms[name] _default = False # The getfacl execution module lists default with empty names as being # applied to the user/group that owns the file, e.g., # default:group::rwx would be listed as default:group:root:rwx # In this case, if acl_name is empty, we really want to search for root # but still uses '' for other # We search through the dictionary getfacl returns for the owner of the # file if acl_name is empty. if acl_name == '': _search_name = __current_perms[name].get('comment').get(_acl_type, '') else: _search_name = acl_name if _current_perms.get(_acl_type, None) or _default: try: user = [i for i in _current_perms[_acl_type] if next(six.iterkeys(i)) == _search_name].pop() except (AttributeError, IndexError, StopIteration, KeyError): user = None need_refresh = False for path in __current_perms: acl_found = False for user_acl in __current_perms[path].get(_acl_type, []): if _search_name in user_acl: acl_found = True break if acl_found: need_refresh = True break if user or need_refresh: ret['comment'] = 'Removing permissions' if __opts__['test']: ret['result'] = None return ret __salt__['acl.delfacl'](acl_type, acl_name, perms, name, recursive=recurse) else: ret['comment'] = 'Permissions are in the desired state' else: ret['comment'] = 'ACL Type does not exist' ret['result'] = False return ret def list_present(name, acl_type, acl_names=None, perms='', recurse=False, force=False): ''' Ensure a Linux ACL list is present Takes a list of acl names and add them to the given path name The acl path acl_type The type of the acl is used for it can be 'user' or 'group' acl_names The list of users or groups perms Set the permissions eg.: rwx recurse Set the permissions recursive in the path force Wipe out old permissions and ensure only the new permissions are set ''' if acl_names is None: acl_names = [] ret = {'name': name, 'result': True, 'changes': {}, 'pchanges': {}, 'comment': ''} _octal = {'r': 4, 'w': 2, 'x': 1, '-': 0} _octal_perms = sum([_octal.get(i, i) for i in perms]) if not os.path.exists(name): ret['comment'] = '{0} does not exist'.format(name) ret['result'] = False return ret __current_perms = __salt__['acl.getfacl'](name) if acl_type.startswith(('d:', 'default:')): _acl_type = ':'.join(acl_type.split(':')[1:]) _current_perms = __current_perms[name].get('defaults', {}) _default = True else: _acl_type = acl_type _current_perms = __current_perms[name] _default = False _origin_group = _current_perms.get('comment', {}).get('group', None) _origin_owner = _current_perms.get('comment', {}).get('owner', None) _current_acl_types = [] diff_perms = False for key in _current_perms[acl_type]: for current_acl_name in key.keys(): _current_acl_types.append(current_acl_name.encode('utf-8')) diff_perms = _octal_perms == key[current_acl_name]['octal'] if acl_type == 'user': try: _current_acl_types.remove(_origin_owner) except ValueError: pass else: try: _current_acl_types.remove(_origin_group) except ValueError: pass diff_acls = set(_current_acl_types) ^ set(acl_names) if not diff_acls and diff_perms and not force: ret = {'name': name, 'result': True, 'changes': {}, 'pchanges': {}, 'comment': 'Permissions and {}s are in the desired state'.format(acl_type)} return ret # The getfacl execution module lists default with empty names as being # applied to the user/group that owns the file, e.g., # default:group::rwx would be listed as default:group:root:rwx # In this case, if acl_name is empty, we really want to search for root # but still uses '' for other # We search through the dictionary getfacl returns for the owner of the # file if acl_name is empty. if acl_names == '': _search_names = __current_perms[name].get('comment').get(_acl_type, '') else: _search_names = acl_names if _current_perms.get(_acl_type, None) or _default: try: users = {} for i in _current_perms[_acl_type]: if i and next(six.iterkeys(i)) in _search_names: users.update(i) except (AttributeError, KeyError): users = None if users: changes = {} for count, search_name in enumerate(_search_names): if search_name in users: if users[search_name]['octal'] == sum([_octal.get(i, i) for i in perms]): ret['comment'] = 'Permissions are in the desired state' else: changes.update({'new': {'acl_name': ', '.join(acl_names), 'acl_type': acl_type, 'perms': _octal_perms}, 'old': {'acl_name': ', '.join(acl_names), 'acl_type': acl_type, 'perms': six.text_type(users[search_name]['octal'])}}) if __opts__['test']: ret.update({'comment': 'Updated permissions will be applied for ' '{0}: {1} -> {2}'.format( acl_names, six.text_type(users[search_name]['octal']), perms), 'result': None, 'pchanges': changes}) return ret try: if force: __salt__['acl.wipefacls'](name, recursive=recurse, raise_err=True) for acl_name in acl_names: __salt__['acl.modfacl'](acl_type, acl_name, perms, name, recursive=recurse, raise_err=True) ret.update({'comment': 'Updated permissions for ' '{0}'.format(acl_names), 'result': True, 'changes': changes}) except CommandExecutionError as exc: ret.update({'comment': 'Error updating permissions for ' '{0}: {1}'.format(acl_names, exc.strerror), 'result': False}) else: changes = {'new': {'acl_name': ', '.join(acl_names), 'acl_type': acl_type, 'perms': perms}} if __opts__['test']: ret.update({'comment': 'New permissions will be applied for ' '{0}: {1}'.format(acl_names, perms), 'result': None, 'pchanges': changes}) ret['result'] = None return ret try: if force: __salt__['acl.wipefacls'](name, recursive=recurse, raise_err=True) for acl_name in acl_names: __salt__['acl.modfacl'](acl_type, acl_name, perms, name, recursive=recurse, raise_err=True) ret.update({'comment': 'Applied new permissions for ' '{0}'.format(', '.join(acl_names)), 'result': True, 'changes': changes}) except CommandExecutionError as exc: ret.update({'comment': 'Error updating permissions for {0}: ' '{1}'.format(acl_names, exc.strerror), 'result': False}) else: changes = {'new': {'acl_name': ', '.join(acl_names), 'acl_type': acl_type, 'perms': perms}} if __opts__['test']: ret.update({'comment': 'New permissions will be applied for ' '{0}: {1}'.format(acl_names, perms), 'result': None, 'pchanges': changes}) ret['result'] = None return ret try: if force: __salt__['acl.wipefacls'](name, recursive=recurse, raise_err=True) for acl_name in acl_names: __salt__['acl.modfacl'](acl_type, acl_name, perms, name, recursive=recurse, raise_err=True) ret.update({'comment': 'Applied new permissions for ' '{0}'.format(', '.join(acl_names)), 'result': True, 'changes': changes}) except CommandExecutionError as exc: ret.update({'comment': 'Error updating permissions for {0}: ' '{1}'.format(acl_names, exc.strerror), 'result': False}) else: ret['comment'] = 'ACL Type does not exist' ret['result'] = False return ret def list_absent(name, acl_type, acl_names=None, recurse=False): ''' Ensure a Linux ACL list does not exist Takes a list of acl names and remove them from the given path name The acl path acl_type The type of the acl is used for, it can be 'user' or 'group' acl_names The list of users or groups perms Remove the permissions eg.: rwx recurse Set the permissions recursive in the path ''' if acl_names is None: acl_names = [] ret = {'name': name, 'result': True, 'changes': {}, 'comment': ''} if not os.path.exists(name): ret['comment'] = '{0} does not exist'.format(name) ret['result'] = False return ret __current_perms = __salt__['acl.getfacl'](name) if acl_type.startswith(('d:', 'default:')): _acl_type = ':'.join(acl_type.split(':')[1:]) _current_perms = __current_perms[name].get('defaults', {}) _default = True else: _acl_type = acl_type _current_perms = __current_perms[name] _default = False # The getfacl execution module lists default with empty names as being # applied to the user/group that owns the file, e.g., # default:group::rwx would be listed as default:group:root:rwx # In this case, if acl_name is empty, we really want to search for root # but still uses '' for other # We search through the dictionary getfacl returns for the owner of the # file if acl_name is empty. if not acl_names: _search_names = set(__current_perms[name].get('comment').get(_acl_type, '')) else: _search_names = set(acl_names) if _current_perms.get(_acl_type, None) or _default: try: users = {} for i in _current_perms[_acl_type]: if i and next(six.iterkeys(i)) in _search_names: users.update(i) except (AttributeError, KeyError): users = None if users: ret['comment'] = 'Removing permissions' if __opts__['test']: ret['result'] = None return ret for acl_name in acl_names: __salt__['acl.delfacl'](acl_type, acl_name, name, recursive=recurse) else: ret['comment'] = 'Permissions are in the desired state' else: ret['comment'] = 'ACL Type does not exist' ret['result'] = False return ret