%PDF- %PDF-
Direktori : /usr/lib/python2.7/site-packages/salt/renderers/ |
Current File : //usr/lib/python2.7/site-packages/salt/renderers/pass.py |
# -*- coding: utf-8 -*- ''' Pass Renderer for Salt ====================== pass_ is an encrypted on-disk password store. .. _pass: https://www.passwordstore.org/ .. versionadded:: 2017.7.0 Setup ----- *Note*: ``<user>`` needs to be replaced with the user salt-master will be running as. Have private gpg loaded into ``user``'s gpg keyring .. code-block:: yaml load_private_gpg_key: cmd.run: - name: gpg --import <location_of_private_gpg_key> - unless: gpg --list-keys '<gpg_name>' Said private key's public key should have been used when encrypting pass entries that are of interest for pillar data. Fetch and keep local pass git repo up-to-date .. code-block:: yaml update_pass: git.latest: - force_reset: True - name: <git_repo> - target: /<user>/.password-store - identity: <location_of_ssh_private_key> - require: - cmd: load_private_gpg_key Install pass binary .. code-block:: yaml pass: pkg.installed ''' # Import python libs from __future__ import absolute_import, print_function, unicode_literals import logging import os from os.path import expanduser from subprocess import Popen, PIPE # Import salt libs import salt.utils.path from salt.exceptions import SaltRenderError # Import 3rd-party libs from salt.ext import six log = logging.getLogger(__name__) def _get_pass_exec(): ''' Return the pass executable or raise an error ''' pass_exec = salt.utils.path.which('pass') if pass_exec: return pass_exec else: raise SaltRenderError('pass unavailable') def _fetch_secret(pass_path): ''' Fetch secret from pass based on pass_path. If there is any error, return back the original pass_path value ''' cmd = "pass show {0}".format(pass_path.strip()) log.debug('Fetching secret: %s', cmd) proc = Popen(cmd.split(' '), stdout=PIPE, stderr=PIPE) pass_data, pass_error = proc.communicate() # The version of pass used during development sent output to # stdout instead of stderr even though its returncode was non zero. if proc.returncode or not pass_data: log.warning('Could not fetch secret: %s %s', pass_data, pass_error) pass_data = pass_path return pass_data.strip() def _decrypt_object(obj): ''' Recursively try to find a pass path (string) that can be handed off to pass ''' if isinstance(obj, six.string_types): return _fetch_secret(obj) elif isinstance(obj, dict): for pass_key, pass_path in six.iteritems(obj): obj[pass_key] = _decrypt_object(pass_path) elif isinstance(obj, list): for pass_key, pass_path in enumerate(obj): obj[pass_key] = _decrypt_object(pass_path) return obj def render(pass_info, saltenv='base', sls='', argline='', **kwargs): ''' Fetch secret from pass based on pass_path ''' try: _get_pass_exec() except SaltRenderError: raise # Make sure environment variable HOME is set, since Pass looks for the # password-store under ~/.password-store. os.environ['HOME'] = expanduser('~') return _decrypt_object(pass_info)