%PDF- %PDF-
Direktori : /lib/python2.7/site-packages/salt/auth/ |
Current File : //lib/python2.7/site-packages/salt/auth/file.py |
# -*- coding: utf-8 -*- ''' Provide authentication using local files .. versionadded:: 2018.3.0 The `file` auth module allows simple authentication via local files. Different filetypes are supported, including: 1. Text files, with passwords in plaintext or hashed 2. Apache-style htpasswd files 3. Apache-style htdigest files .. note:: The ``python-passlib`` library is required when using a ``^filetype`` of ``htpasswd`` or ``htdigest``. The simplest example is a plaintext file with usernames and passwords: .. code-block:: yaml external_auth: file: ^filename: /etc/insecure-user-list.txt gene: - .* dean: - test.* In this example the ``/etc/insecure-user-list.txt`` file would be formatted as so: .. code-block:: text dean:goneFishing gene:OceanMan ``^filename`` is the only required parameter. Any parameter that begins with a ``^`` is passed directly to the underlying file authentication function via ``kwargs``, with the leading ``^`` being stripped. The text file option is configurable to work with legacy formats: .. code-block:: yaml external_auth: file: ^filename: /etc/legacy_users.txt ^filetype: text ^hashtype: md5 ^username_field: 2 ^password_field: 3 ^field_separator: '|' trey: - .* This would authenticate users against a file of the following format: .. code-block:: text 46|trey|16a0034f90b06bf3c5982ed8ac41aab4 555|mike|b6e02a4d2cb2a6ef0669e79be6fd02e4 2001|page|14fce21db306a43d3b680da1a527847a 8888|jon|c4e94ba906578ccf494d71f45795c6cb .. note:: The :py:func:`hashutil.digest <salt.modules.hashutil.digest>` execution function is used for comparing hashed passwords, so any algorithm supported by that function will work. There is also support for Apache-style ``htpasswd`` and ``htdigest`` files: .. code-block:: yaml external_auth: file: ^filename: /var/www/html/.htusers ^filetype: htpasswd cory: - .* When using ``htdigest`` the ``^realm`` must be set: .. code-block:: yaml external_auth: file: ^filename: /var/www/html/.htdigest ^filetype: htdigest ^realm: MySecureRealm cory: - .* ''' # Import python libs from __future__ import absolute_import, print_function, unicode_literals import logging import os # Import salt utils import salt.utils.files import salt.utils.versions log = logging.getLogger(__name__) __virtualname__ = 'file' def __virtual__(): return __virtualname__ def _get_file_auth_config(): ''' Setup defaults and check configuration variables for auth backends ''' config = { 'filetype': 'text', 'hashtype': 'plaintext', 'field_separator': ':', 'username_field': 1, 'password_field': 2, } for opt in __opts__['external_auth'][__virtualname__]: if opt.startswith('^'): config[opt[1:]] = __opts__['external_auth'][__virtualname__][opt] if 'filename' not in config: log.error('salt.auth.file: An authentication file must be specified ' 'via external_auth:file:^filename') return False if not os.path.exists(config['filename']): log.error('salt.auth.file: The configured external_auth:file:^filename (%s)' 'does not exist on the filesystem', config['filename']) return False config['username_field'] = int(config['username_field']) config['password_field'] = int(config['password_field']) return config def _text(username, password, **kwargs): ''' The text file function can authenticate plaintext and digest methods that are available in the :py:func:`hashutil.digest <salt.modules.hashutil.digest>` function. ''' filename = kwargs['filename'] hashtype = kwargs['hashtype'] field_separator = kwargs['field_separator'] username_field = kwargs['username_field']-1 password_field = kwargs['password_field']-1 with salt.utils.files.fopen(filename, 'r') as pwfile: for line in pwfile.readlines(): fields = line.strip().split(field_separator) try: this_username = fields[username_field] except IndexError: log.error('salt.auth.file: username field (%s) does not exist ' 'in file %s', username_field, filename) return False try: this_password = fields[password_field] except IndexError: log.error('salt.auth.file: password field (%s) does not exist ' 'in file %s', password_field, filename) return False if this_username == username: if hashtype == 'plaintext': if this_password == password: return True else: # Exceptions for unknown hash types will be raised by hashutil.digest if this_password == __salt__['hashutil.digest'](password, hashtype): return True # Short circuit if we've already found the user but the password was wrong return False return False def _htpasswd(username, password, **kwargs): ''' Provide authentication via Apache-style htpasswd files ''' from passlib.apache import HtpasswdFile pwfile = HtpasswdFile(kwargs['filename']) # passlib below version 1.6 uses 'verify' function instead of 'check_password' if salt.utils.versions.version_cmp(kwargs['passlib_version'], '1.6') < 0: return pwfile.verify(username, password) else: return pwfile.check_password(username, password) def _htdigest(username, password, **kwargs): ''' Provide authentication via Apache-style htdigest files ''' realm = kwargs.get('realm', None) if not realm: log.error('salt.auth.file: A ^realm must be defined in ' 'external_auth:file for htdigest filetype') return False from passlib.apache import HtdigestFile pwfile = HtdigestFile(kwargs['filename']) # passlib below version 1.6 uses 'verify' function instead of 'check_password' if salt.utils.versions.version_cmp(kwargs['passlib_version'], '1.6') < 0: return pwfile.verify(username, realm, password) else: return pwfile.check_password(username, realm, password) def _htfile(username, password, **kwargs): ''' Gate function for _htpasswd and _htdigest authentication backends ''' filetype = kwargs.get('filetype', 'htpasswd').lower() try: import passlib kwargs['passlib_version'] = passlib.__version__ except ImportError: log.error('salt.auth.file: The python-passlib library is required ' 'for %s filetype', filetype) return False if filetype == 'htdigest': return _htdigest(username, password, **kwargs) else: return _htpasswd(username, password, **kwargs) FILETYPE_FUNCTION_MAP = { 'text': _text, 'htpasswd': _htfile, 'htdigest': _htfile } def auth(username, password): ''' File based authentication ^filename The path to the file to use for authentication. ^filetype The type of file: ``text``, ``htpasswd``, ``htdigest``. Default: ``text`` ^realm The realm required by htdigest authentication. .. note:: The following parameters are only used with the ``text`` filetype. ^hashtype The digest format of the password. Can be ``plaintext`` or any digest available via :py:func:`hashutil.digest <salt.modules.hashutil.digest>`. Default: ``plaintext`` ^field_separator The character to use as a delimiter between fields in a text file. Default: ``:`` ^username_field The numbered field in the text file that contains the username, with numbering beginning at 1 (one). Default: ``1`` ^password_field The numbered field in the text file that contains the password, with numbering beginning at 1 (one). Default: ``2`` ''' config = _get_file_auth_config() if not config: return False auth_function = FILETYPE_FUNCTION_MAP.get(config['filetype'], 'text') return auth_function(username, password, **config)