%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/shadow.py |
# -*- coding: utf-8 -*- ''' Manage the shadow file on Linux systems .. important:: If you feel that Salt should be using this module to manage passwords on a minion, and it is using a different module (or gives an error similar to *'shadow.info' is not available*), see :ref:`here <module-provider-override>`. ''' from __future__ import absolute_import, unicode_literals, print_function # Import python libs import os import datetime try: import spwd except ImportError: pass # Import salt libs import salt.utils.data import salt.utils.files import salt.utils.stringutils from salt.exceptions import CommandExecutionError from salt.ext import six try: import salt.utils.pycrypto HAS_CRYPT = True except ImportError: HAS_CRYPT = False def __virtual__(): return __grains__.get('kernel', '') == 'Linux' def default_hash(): ''' Returns the default hash used for unset passwords CLI Example: .. code-block:: bash salt '*' shadow.default_hash ''' return '!' def info(name): ''' Return information for the specified user CLI Example: .. code-block:: bash salt '*' shadow.info root ''' try: data = spwd.getspnam(name) ret = { 'name': data.sp_nam, 'passwd': data.sp_pwd, 'lstchg': data.sp_lstchg, 'min': data.sp_min, 'max': data.sp_max, 'warn': data.sp_warn, 'inact': data.sp_inact, 'expire': data.sp_expire} except KeyError: return { 'name': '', 'passwd': '', 'lstchg': '', 'min': '', 'max': '', 'warn': '', 'inact': '', 'expire': ''} return ret def set_inactdays(name, inactdays): ''' Set the number of days of inactivity after a password has expired before the account is locked. See man chage. CLI Example: .. code-block:: bash salt '*' shadow.set_inactdays username 7 ''' pre_info = info(name) if inactdays == pre_info['inact']: return True cmd = 'chage -I {0} {1}'.format(inactdays, name) __salt__['cmd.run'](cmd, python_shell=False) post_info = info(name) if post_info['inact'] != pre_info['inact']: return post_info['inact'] == inactdays return False def set_maxdays(name, maxdays): ''' Set the maximum number of days during which a password is valid. See man chage. CLI Example: .. code-block:: bash salt '*' shadow.set_maxdays username 90 ''' pre_info = info(name) if maxdays == pre_info['max']: return True cmd = 'chage -M {0} {1}'.format(maxdays, name) __salt__['cmd.run'](cmd, python_shell=False) post_info = info(name) if post_info['max'] != pre_info['max']: return post_info['max'] == maxdays return False def set_mindays(name, mindays): ''' Set the minimum number of days between password changes. See man chage. CLI Example: .. code-block:: bash salt '*' shadow.set_mindays username 7 ''' pre_info = info(name) if mindays == pre_info['min']: return True cmd = 'chage -m {0} {1}'.format(mindays, name) __salt__['cmd.run'](cmd, python_shell=False) post_info = info(name) if post_info['min'] != pre_info['min']: return post_info['min'] == mindays return False def gen_password(password, crypt_salt=None, algorithm='sha512'): ''' .. versionadded:: 2014.7.0 Generate hashed password .. note:: When called this function is called directly via remote-execution, the password argument may be displayed in the system's process list. This may be a security risk on certain systems. password Plaintext password to be hashed. crypt_salt Crpytographic salt. If not given, a random 8-character salt will be generated. algorithm The following hash algorithms are supported: * md5 * blowfish (not in mainline glibc, only available in distros that add it) * sha256 * sha512 (default) CLI Example: .. code-block:: bash salt '*' shadow.gen_password 'I_am_password' salt '*' shadow.gen_password 'I_am_password' crypt_salt='I_am_salt' algorithm=sha256 ''' if not HAS_CRYPT: raise CommandExecutionError( 'gen_password is not available on this operating system ' 'because the "crypt" python module is not available.' ) return salt.utils.pycrypto.gen_hash(crypt_salt, password, algorithm) def del_password(name): ''' .. versionadded:: 2014.7.0 Delete the password from name user CLI Example: .. code-block:: bash salt '*' shadow.del_password username ''' cmd = 'passwd -d {0}'.format(name) __salt__['cmd.run'](cmd, python_shell=False, output_loglevel='quiet') uinfo = info(name) return not uinfo['passwd'] and uinfo['name'] == name def lock_password(name): ''' .. versionadded:: 2016.11.0 Lock the password from specified user CLI Example: .. code-block:: bash salt '*' shadow.lock_password username ''' pre_info = info(name) if pre_info['name'] == '': return False if pre_info['passwd'].startswith('!'): return True cmd = 'passwd -l {0}'.format(name) __salt__['cmd.run'](cmd, python_shell=False) post_info = info(name) return post_info['passwd'].startswith('!') def unlock_password(name): ''' .. versionadded:: 2016.11.0 Unlock the password from name user CLI Example: .. code-block:: bash salt '*' shadow.unlock_password username ''' pre_info = info(name) if pre_info['name'] == '': return False if pre_info['passwd'][0] != '!': return True cmd = 'passwd -u {0}'.format(name) __salt__['cmd.run'](cmd, python_shell=False) post_info = info(name) return post_info['passwd'][0] != '!' def set_password(name, password, use_usermod=False): ''' Set the password for a named user. The password must be a properly defined hash. The password hash can be generated with this command: ``python -c "import crypt; print crypt.crypt('password', '\\$6\\$SALTsalt')"`` ``SALTsalt`` is the 8-character crpytographic salt. Valid characters in the salt are ``.``, ``/``, and any alphanumeric character. Keep in mind that the $6 represents a sha512 hash, if your OS is using a different hashing algorithm this needs to be changed accordingly CLI Example: .. code-block:: bash salt '*' shadow.set_password root '$1$UYCIxa628.9qXjpQCjM4a..' ''' if not salt.utils.data.is_true(use_usermod): # Edit the shadow file directly # ALT Linux uses tcb to store password hashes. More information found # in manpage (http://docs.altlinux.org/manpages/tcb.5.html) if __grains__['os'] == 'ALT': s_file = '/etc/tcb/{0}/shadow'.format(name) else: s_file = '/etc/shadow' ret = {} if not os.path.isfile(s_file): return ret lines = [] with salt.utils.files.fopen(s_file, 'rb') as fp_: for line in fp_: line = salt.utils.stringutils.to_unicode(line) comps = line.strip().split(':') if comps[0] != name: lines.append(line) continue changed_date = datetime.datetime.today() - datetime.datetime(1970, 1, 1) comps[1] = password comps[2] = six.text_type(changed_date.days) line = ':'.join(comps) lines.append('{0}\n'.format(line)) with salt.utils.files.fopen(s_file, 'w+') as fp_: lines = [salt.utils.stringutils.to_str(_l) for _l in lines] fp_.writelines(lines) uinfo = info(name) return uinfo['passwd'] == password else: # Use usermod -p (less secure, but more feature-complete) cmd = 'usermod -p {0} {1}'.format(password, name) __salt__['cmd.run'](cmd, python_shell=False, output_loglevel='quiet') uinfo = info(name) return uinfo['passwd'] == password def set_warndays(name, warndays): ''' Set the number of days of warning before a password change is required. See man chage. CLI Example: .. code-block:: bash salt '*' shadow.set_warndays username 7 ''' pre_info = info(name) if warndays == pre_info['warn']: return True cmd = 'chage -W {0} {1}'.format(warndays, name) __salt__['cmd.run'](cmd, python_shell=False) post_info = info(name) if post_info['warn'] != pre_info['warn']: return post_info['warn'] == warndays return False def set_date(name, date): ''' Sets the value for the date the password was last changed to days since the epoch (January 1, 1970). See man chage. CLI Example: .. code-block:: bash salt '*' shadow.set_date username 0 ''' cmd = ['chage', '-d', date, name] return __salt__['cmd.retcode'](cmd, python_shell=False) == 0 def set_expire(name, expire): ''' .. versionchanged:: 2014.7.0 Sets the value for the date the account expires as days since the epoch (January 1, 1970). Using a value of -1 will clear expiration. See man chage. CLI Example: .. code-block:: bash salt '*' shadow.set_expire username -1 ''' cmd = ['chage', '-E', expire, name] return __salt__['cmd.retcode'](cmd, python_shell=False) == 0 def list_users(): ''' .. versionadded:: 2018.3.0 Return a list of all shadow users CLI Example: .. code-block:: bash salt '*' shadow.list_users ''' return sorted([user.sp_nam for user in spwd.getspall()])