mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 09:40:20 +00:00
Make the pass renderer more configurable
1. Allow us to make the pass renderer fail during pillar rendering when a secret corresponding with a pass path cannot be fetched. For this we add a master config variable pass_strict_fetch. 2. Allow to have prefix for variables that should be processed with the pass renderer. For this we add a master config variable pass_variable_prefix. 3. Allow us to configure pass' GNUPGHOME and PASSWORD_STORE_DIR environmental variables. For this we add master config variables pass_gnupghome and pass_dir.
This commit is contained in:
parent
b327996cf5
commit
bcf5dd82ed
3 changed files with 82 additions and 3 deletions
4
changelog/62120.added
Normal file
4
changelog/62120.added
Normal file
|
@ -0,0 +1,4 @@
|
|||
Config option pass_variable_prefix allows to distinguish variables that contain paths to pass secrets.
|
||||
Config option pass_strict_fetch allows to error out when a secret cannot be fetched from pass.
|
||||
Config option pass_dir allows setting the PASSWORD_STORE_DIR env for pass.
|
||||
Config option pass_gnupghome allows setting the $GNUPGHOME env for pass.
|
|
@ -964,6 +964,14 @@ VALID_OPTS = immutabletypes.freeze(
|
|||
# The port to be used when checking if a master is connected to a
|
||||
# minion
|
||||
"remote_minions_port": int,
|
||||
# pass renderer: Fetch secrets only for the template variables matching the prefix
|
||||
"pass_variable_prefix": str,
|
||||
# pass renderer: Whether to error out when unable to fetch a secret
|
||||
"pass_strict_fetch": bool,
|
||||
# pass renderer: Set GNUPGHOME env for Pass
|
||||
"pass_gnupghome": str,
|
||||
# pass renderer: Set PASSWORD_STORE_DIR env for Pass
|
||||
"pass_dir": str,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -1604,6 +1612,10 @@ DEFAULT_MASTER_OPTS = immutabletypes.freeze(
|
|||
"fips_mode": False,
|
||||
"detect_remote_minions": False,
|
||||
"remote_minions_port": 22,
|
||||
"pass_variable_prefix": "",
|
||||
"pass_strict_fetch": False,
|
||||
"pass_gnupghome": "",
|
||||
"pass_dir": "",
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -45,6 +45,34 @@ Install pass binary
|
|||
|
||||
pass:
|
||||
pkg.installed
|
||||
|
||||
Salt master configuration options
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# If the prefix is *not* set (default behavior), all template variables are
|
||||
# considered for fetching secrets from Pass. Those that cannot be resolved
|
||||
# to a secret are passed through.
|
||||
#
|
||||
# If the prefix is set, only the template variables with matching prefix are
|
||||
# considered for fetching the secrets, other variables are passed through.
|
||||
#
|
||||
# For ease of use it is recommended to set the following options as well:
|
||||
# renderer: 'jinja|yaml|pass'
|
||||
# pass_strict_fetch: true
|
||||
#
|
||||
pass_variable_prefix: 'pass:'
|
||||
|
||||
# If set to 'true', error out when unable to fetch a secret for a template variable.
|
||||
pass_strict_fetch: true
|
||||
|
||||
# Set GNUPGHOME env for Pass.
|
||||
# Defaults to: ~/.gnupg
|
||||
pass_gnupghome: <path>
|
||||
|
||||
# Set PASSWORD_STORE_DIR env for Pass.
|
||||
# Defaults to: ~/.password-store
|
||||
pass_dir: <path>
|
||||
"""
|
||||
|
||||
|
||||
|
@ -54,7 +82,7 @@ from os.path import expanduser
|
|||
from subprocess import PIPE, Popen
|
||||
|
||||
import salt.utils.path
|
||||
from salt.exceptions import SaltRenderError
|
||||
from salt.exceptions import SaltConfigurationError, SaltRenderError
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -80,6 +108,23 @@ def _fetch_secret(pass_path):
|
|||
# Make a backup in case we want to return the original value without stripped whitespaces
|
||||
original_pass_path = pass_path
|
||||
|
||||
# Remove the optional prefix from pass path
|
||||
pass_prefix = __opts__["pass_variable_prefix"]
|
||||
if pass_prefix:
|
||||
# If we do not see our prefix we do not want to process this variable
|
||||
# and we return the unmodified pass path
|
||||
if not pass_path.startswith(pass_prefix):
|
||||
return pass_path
|
||||
|
||||
# strip the prefix from the start of the string
|
||||
pass_path = pass_path[len(pass_prefix) :]
|
||||
|
||||
# The pass_strict_fetch option must be used with pass_variable_prefix
|
||||
pass_strict_fetch = __opts__["pass_strict_fetch"]
|
||||
if pass_strict_fetch and not pass_prefix:
|
||||
msg = "The 'pass_strict_fetch' option requires 'pass_variable_prefix' option enabled"
|
||||
raise SaltConfigurationError(msg)
|
||||
|
||||
# Remove whitespaces from the pass_path
|
||||
pass_path = pass_path.strip()
|
||||
|
||||
|
@ -91,14 +136,32 @@ def _fetch_secret(pass_path):
|
|||
env = os.environ.copy()
|
||||
env["HOME"] = expanduser("~")
|
||||
|
||||
pass_dir = __opts__["pass_dir"]
|
||||
if pass_dir:
|
||||
env["PASSWORD_STORE_DIR"] = pass_dir
|
||||
|
||||
pass_gnupghome = __opts__["pass_gnupghome"]
|
||||
if pass_gnupghome:
|
||||
env["GNUPGHOME"] = pass_gnupghome
|
||||
|
||||
proc = Popen(cmd, stdout=PIPE, stderr=PIPE, env=env)
|
||||
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)
|
||||
return original_pass_path
|
||||
try:
|
||||
pass_error = pass_error.decode("utf-8")
|
||||
except (AttributeError, ValueError):
|
||||
pass
|
||||
msg = "Could not fetch secret '{}' from the password store: {}".format(
|
||||
pass_path, pass_error
|
||||
)
|
||||
if pass_strict_fetch:
|
||||
raise SaltRenderError(msg)
|
||||
else:
|
||||
log.warning(msg)
|
||||
return original_pass_path
|
||||
return pass_data.rstrip("\r\n")
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue