%PDF- %PDF-
Direktori : /proc/self/root/lib/python2.7/site-packages/salt/modules/ |
Current File : //proc/self/root/lib/python2.7/site-packages/salt/modules/pw_user.py |
# -*- coding: utf-8 -*- ''' Manage users with the pw command .. important:: If you feel that Salt should be using this module to manage users on a minion, and it is using a different module (or gives an error similar to *'user.info' is not available*), see :ref:`here <module-provider-override>`. ''' # Notes: # ------ # # Format of the master.passwd file: # # - name User's login name. # - password User's encrypted password. # - uid User's id. # - gid User's login group id. # - class User's login class. # - change Password change time. # - expire Account expiration time. # - gecos General information about the user. # - home_dir User's home directory. # - shell User's login shell. # # The usershow command allows viewing of an account in a format that is # identical to the format used in /etc/master.passwd (with the password field # replaced with a ‘*’.) # # Example: # % pw usershow -n someuser # someuser:*:1001:1001::0:0:SomeUser Name:/home/someuser:/bin/sh # Import python libs from __future__ import absolute_import, unicode_literals, print_function import copy import logging try: import pwd HAS_PWD = True except ImportError: HAS_PWD = False # Import 3rd party libs from salt.ext import six # Import salt libs import salt.utils.args import salt.utils.data import salt.utils.user from salt.exceptions import CommandExecutionError log = logging.getLogger(__name__) # Define the module's virtual name __virtualname__ = 'user' def __virtual__(): ''' Set the user module if the kernel is FreeBSD or DragonFly ''' if HAS_PWD and __grains__['kernel'] in ('FreeBSD', 'DragonFly'): return __virtualname__ return (False, 'The pw_user execution module cannot be loaded: the pwd python module is not available or the system is not FreeBSD.') def _get_gecos(name): ''' Retrieve GECOS field info and return it in dictionary form ''' try: gecos_field = pwd.getpwnam(name).pw_gecos.split(',', 3) except KeyError: raise CommandExecutionError( 'User \'{0}\' does not exist'.format(name) ) if not gecos_field: return {} else: # Assign empty strings for any unspecified trailing GECOS fields while len(gecos_field) < 4: gecos_field.append('') return {'fullname': salt.utils.data.decode(gecos_field[0]), 'roomnumber': salt.utils.data.decode(gecos_field[1]), 'workphone': salt.utils.data.decode(gecos_field[2]), 'homephone': salt.utils.data.decode(gecos_field[3])} def _build_gecos(gecos_dict): ''' Accepts a dictionary entry containing GECOS field names and their values, and returns a full GECOS comment string, to be used with pw usermod. ''' return u'{0},{1},{2},{3}'.format(gecos_dict.get('fullname', ''), gecos_dict.get('roomnumber', ''), gecos_dict.get('workphone', ''), gecos_dict.get('homephone', '')) def _update_gecos(name, key, value): ''' Common code to change a user's GECOS information ''' if not isinstance(value, six.string_types): value = six.text_type(value) pre_info = _get_gecos(name) if not pre_info: return False if value == pre_info[key]: return True gecos_data = copy.deepcopy(pre_info) gecos_data[key] = value cmd = ['pw', 'usermod', name, '-c', _build_gecos(gecos_data)] __salt__['cmd.run'](cmd, python_shell=False) post_info = info(name) return _get_gecos(name).get(key) == value def add(name, uid=None, gid=None, groups=None, home=None, shell=None, unique=True, fullname='', roomnumber='', workphone='', homephone='', createhome=True, loginclass=None, **kwargs): ''' Add a user to the minion CLI Example: .. code-block:: bash salt '*' user.add name <uid> <gid> <groups> <home> <shell> ''' kwargs = salt.utils.args.clean_kwargs(**kwargs) if salt.utils.data.is_true(kwargs.pop('system', False)): log.warning('pw_user module does not support the \'system\' argument') if kwargs: log.warning('Invalid kwargs passed to user.add') if isinstance(groups, six.string_types): groups = groups.split(',') cmd = ['pw', 'useradd'] if uid: cmd.extend(['-u', uid]) if gid: cmd.extend(['-g', gid]) if groups: cmd.extend(['-G', ','.join(groups)]) if home is not None: cmd.extend(['-d', home]) if createhome is True: cmd.append('-m') if loginclass: cmd.extend(['-L', loginclass]) if shell: cmd.extend(['-s', shell]) if not salt.utils.data.is_true(unique): cmd.append('-o') gecos_field = _build_gecos({'fullname': fullname, 'roomnumber': roomnumber, 'workphone': workphone, 'homephone': homephone}) cmd.extend(['-c', gecos_field]) cmd.extend(['-n', name]) return __salt__['cmd.retcode'](cmd, python_shell=False) == 0 def delete(name, remove=False, force=False): ''' Remove a user from the minion CLI Example: .. code-block:: bash salt '*' user.delete name remove=True force=True ''' if salt.utils.data.is_true(force): log.error('pw userdel does not support force-deleting user while ' 'user is logged in') cmd = ['pw', 'userdel'] if remove: cmd.append('-r') cmd.extend(['-n', name]) return __salt__['cmd.retcode'](cmd, python_shell=False) == 0 def getent(refresh=False): ''' Return the list of all info for all users CLI Example: .. code-block:: bash salt '*' user.getent ''' if 'user.getent' in __context__ and not refresh: return __context__['user.getent'] ret = [] for data in pwd.getpwall(): ret.append(info(data.pw_name)) __context__['user.getent'] = ret return ret def chuid(name, uid): ''' Change the uid for a named user CLI Example: .. code-block:: bash salt '*' user.chuid foo 4376 ''' pre_info = info(name) if not pre_info: raise CommandExecutionError( 'User \'{0}\' does not exist'.format(name) ) if uid == pre_info['uid']: return True cmd = ['pw', 'usermod', '-u', uid, '-n', name] __salt__['cmd.run'](cmd, python_shell=False) return info(name).get('uid') == uid def chgid(name, gid): ''' Change the default group of the user CLI Example: .. code-block:: bash salt '*' user.chgid foo 4376 ''' pre_info = info(name) if not pre_info: raise CommandExecutionError( 'User \'{0}\' does not exist'.format(name) ) if gid == pre_info['gid']: return True cmd = ['pw', 'usermod', '-g', gid, '-n', name] __salt__['cmd.run'](cmd, python_shell=False) return info(name).get('gid') == gid def chshell(name, shell): ''' Change the default shell of the user CLI Example: .. code-block:: bash salt '*' user.chshell foo /bin/zsh ''' pre_info = info(name) if not pre_info: raise CommandExecutionError( 'User \'{0}\' does not exist'.format(name) ) if shell == pre_info['shell']: return True cmd = ['pw', 'usermod', '-s', shell, '-n', name] __salt__['cmd.run'](cmd, python_shell=False) return info(name).get('shell') == shell def chhome(name, home, persist=False): ''' Set a new home directory for an existing user name Username to modify home New home directory to set persist : False Set to ``True`` to prevent configuration files in the new home directory from being overwritten by the files from the skeleton directory. CLI Example: .. code-block:: bash salt '*' user.chhome foo /home/users/foo True ''' pre_info = info(name) if not pre_info: raise CommandExecutionError( 'User \'{0}\' does not exist'.format(name) ) if home == pre_info['home']: return True cmd = ['pw', 'usermod', name, '-d', home] if persist: cmd.append('-m') __salt__['cmd.run'](cmd, python_shell=False) return info(name).get('home') == home def chgroups(name, groups, append=False): ''' Change the groups to which a user belongs name Username to modify groups List of groups to set for the user. Can be passed as a comma-separated list or a Python list. append : False Set to ``True`` to append these groups to the user's existing list of groups. Otherwise, the specified groups will replace any existing groups for the user. CLI Example: .. code-block:: bash salt '*' user.chgroups foo wheel,root True ''' if isinstance(groups, six.string_types): groups = groups.split(',') ugrps = set(list_groups(name)) if ugrps == set(groups): return True if append: groups += ugrps cmd = ['pw', 'usermod', '-G', ','.join(groups), '-n', name] return __salt__['cmd.retcode'](cmd, python_shell=False) == 0 def chfullname(name, fullname): ''' Change the user's Full Name CLI Example: .. code-block:: bash salt '*' user.chfullname foo "Foo Bar" ''' return _update_gecos(name, 'fullname', fullname) def chroomnumber(name, roomnumber): ''' Change the user's Room Number CLI Example: .. code-block:: bash salt '*' user.chroomnumber foo 123 ''' return _update_gecos(name, 'roomnumber', roomnumber) def chworkphone(name, workphone): ''' Change the user's Work Phone CLI Example: .. code-block:: bash salt '*' user.chworkphone foo "7735550123" ''' return _update_gecos(name, 'workphone', workphone) def chhomephone(name, homephone): ''' Change the user's Home Phone CLI Example: .. code-block:: bash salt '*' user.chhomephone foo "7735551234" ''' return _update_gecos(name, 'homephone', homephone) def chloginclass(name, loginclass, root=None): ''' Change the default login class of the user .. versionadded:: 2016.3.5 CLI Example: .. code-block:: bash salt '*' user.chloginclass foo staff ''' if loginclass == get_loginclass(name): return True cmd = ['pw', 'usermod', '-L', '{0}'.format(loginclass), '-n', '{0}'.format(name)] __salt__['cmd.run'](cmd, python_shell=False) return get_loginclass(name) == loginclass def info(name): ''' Return user information CLI Example: .. code-block:: bash salt '*' user.info root ''' ret = {} try: data = pwd.getpwnam(name) ret['gid'] = data.pw_gid ret['groups'] = list_groups(name) ret['home'] = data.pw_dir ret['name'] = data.pw_name ret['passwd'] = data.pw_passwd ret['shell'] = data.pw_shell ret['uid'] = data.pw_uid # Put GECOS info into a list gecos_field = data.pw_gecos.split(',', 3) # Assign empty strings for any unspecified GECOS fields while len(gecos_field) < 4: gecos_field.append('') ret['fullname'] = gecos_field[0] ret['roomnumber'] = gecos_field[1] ret['workphone'] = gecos_field[2] ret['homephone'] = gecos_field[3] except KeyError: return {} return ret def get_loginclass(name): ''' Get the login class of the user .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' user.get_loginclass foo ''' userinfo = __salt__['cmd.run_stdout'](['pw', 'usershow', '-n', name]) userinfo = userinfo.split(':') return userinfo[4] if len(userinfo) == 10 else '' def list_groups(name): ''' Return a list of groups the named user belongs to CLI Example: .. code-block:: bash salt '*' user.list_groups foo ''' return salt.utils.user.get_group_list(name) def list_users(): ''' Return a list of all users CLI Example: .. code-block:: bash salt '*' user.list_users ''' return sorted([user.pw_name for user in pwd.getpwall()]) def rename(name, new_name): ''' Change the username for a named user CLI Example: .. code-block:: bash salt '*' user.rename name new_name ''' current_info = info(name) if not current_info: raise CommandExecutionError('User \'{0}\' does not exist'.format(name)) new_info = info(new_name) if new_info: raise CommandExecutionError( 'User \'{0}\' already exists'.format(new_name) ) cmd = ['pw', 'usermod', '-l', new_name, '-n', name] __salt__['cmd.run'](cmd) post_info = info(new_name) if post_info['name'] != current_info['name']: return post_info['name'] == new_name return False