%PDF- %PDF-
| Direktori : /proc/self/root/proc/self/root/usr/lib/python2.7/site-packages/salt/modules/ |
| Current File : //proc/self/root/proc/self/root/usr/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()])