From 36a3e9dcb383441ea4f702467c591c8d3acfca42 Mon Sep 17 00:00:00 2001 From: Tim Loyer Date: Thu, 11 Mar 2021 14:31:44 -0500 Subject: [PATCH] Improvements to env setup, datadog usage (#7) - Make Datadog optional - Enforce datadog>=0.36.0 to auto-tag `DD_*` environment variables - Move environment settings to config module - Start namespacing vaultpy env vars with VAULTPY_ to avoid collision extract environment variables to config module make datadog optional, simplify --- setup.cfg | 4 ++-- vault/__init__.py | 31 +++++++++++++------------------ vault/config.py | 23 +++++++++++++++++++++++ 3 files changed, 38 insertions(+), 20 deletions(-) create mode 100644 vault/config.py diff --git a/setup.cfg b/setup.cfg index 103e67b..789f8fc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = vaultpy -version = 0.0.5 +version = 0.0.6 author = Tim Loyer author_email = tloyer@apps.directemployers.org description = A module to parse injected Vault secrets and track their usage with Datadog. @@ -12,4 +12,4 @@ url = https://github.com/DirectEmployers/vaultpy packages = find: python_requires = >=3.6 install_requires = - datadog + datadog>=0.36.0 diff --git a/vault/__init__.py b/vault/__init__.py index 4d9fd8b..46438ce 100644 --- a/vault/__init__.py +++ b/vault/__init__.py @@ -2,11 +2,12 @@ from base64 import b64decode, b64encode from importlib import import_module from json import loads -from os import environ from typing import Dict from datadog import statsd +import config + logger = logging.getLogger(__name__) @@ -34,7 +35,7 @@ def _load_vault_secrets() -> Dict: base 64 decode followed by JSON decode on file contents. This function should not be called anywhere except within this module! """ - with open(environ["VAULT_SECRETS_PATH"]) as file: + with open(config.SECRETS_PATH) as file: contents = file.read().strip() if _is_base64(contents): @@ -59,7 +60,7 @@ def _get_secrets() -> Dict: located at path in VAULT_SECRETS_PATH. Performs base 64 decode followed by JSON decode on file contents. """ - if not environ.get("USE_VAULT"): + if not config.ENABLE_VAULT: # Use dev secrets when available. return _load_de_secrets() @@ -73,8 +74,6 @@ class VaultSecretsWrapper: def __init__(self, secrets: Dict): self._keys = secrets.keys() - self._env = environ.get("DD_ENV") - self._service = environ.get("DD_SERVICE") for key, value in secrets.items(): # Set baseline usage of 0 for all secrets. @@ -86,20 +85,16 @@ def _record_usage(self, key, value=0): """ Report secret usage to Datadog for evaluation and cleanup of old secrets. """ - try: - statsd.increment( - "vault.secrets.usage", - value=value, - tags=[ - f"env:{self._env}", - f"service:{self._service}", - f"secret_key:{key}", - ], - ) - except Exception: - if not hasattr(self, "_no_datadog"): + if config.ENABLE_DATADOG: + try: + statsd.increment( + "vault.secrets.usage", + value=value, + tags=[f"secret_key:{key}"], + ) + except Exception: logger.error("Vault secret usage could not be reported to Datadog!") - self._no_datadog = True + config.ENABLE_DATADOG = False def __getattribute__(self, key: str): """ diff --git a/vault/config.py b/vault/config.py new file mode 100644 index 0000000..c0401df --- /dev/null +++ b/vault/config.py @@ -0,0 +1,23 @@ +from os import environ + + +def parse_env_bool(env: str) -> bool: + return env.casefold() in ["true", "1"] + + +# We're defaulting this to False until everything using vaultpy uses Vault. +# When True, vaultpy will attempt to retrieve and parse Vault agent injected secrets. +# When False vaultpy fallback on loading secrets from the de_secrets module. +# TODO: Remove USE_VAULT when all code has been updated to use VAULTPY_* +ENABLE_VAULT = parse_env_bool( + environ.get("VAULTPY_ENABLE_VAULT", environ.get("USE_VAULT", "false")) +) + +# Absolute path to get secrets from when VAULTPY_ENABLE_VAULT=true +# TODO: Remove VAULT_SECRETS_PATH when all code has been updated to use VAULTPY_* +SECRETS_PATH = environ.get( + "VAULTPY_SECRETS_PATH", environ.get("VAULT_SECRETS_PATH", "/vault/secrets/secrets") +) + +# Enable or disable reporting of secret usage to Datadog. +ENABLE_DATADOG = parse_env_bool(environ.get("VAULTPY_ENABLE_DATADOG", "true"))