diff --git a/secret_loader/__index__.py b/secret_loader/__init__.py similarity index 64% rename from secret_loader/__index__.py rename to secret_loader/__init__.py index 1b1d0ef..ba97cbf 100644 --- a/secret_loader/__index__.py +++ b/secret_loader/__init__.py @@ -1,5 +1,6 @@ import logging import os +from frozendict import frozendict logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -9,33 +10,39 @@ try: except ImportError: hvac = None +ENV_KEY_VAULT_URL = 'VAULT_URL' +ENV_KEY_VAULT_TOKEN = 'VAULT_TOKEN' +ENV_KEY_VAULT_MOUNT_POINT = 'VAULT_MOUNT_POINT' + class SecretLoader: - ''' + """ Priority order: - 1. Files pointed to by environment variables - 2. Secrets folder - 3. Vault instance if configured - ''' + 0. Hardcoded values. This is purely for prototyping. + 1. Files pointed to by environment variables. + 2. Secrets folder. + 3. Vault instance if configured. Most suited for production environments. + """ - def __init__(self, env_key_prefix: str): + def __init__(self, env_key_prefix: str, hardcoded: dict[str,str] | None = None): assert not env_key_prefix.endswith('_') self.env_key_prefix = env_key_prefix + self.hardcoded: dict[str,str] = hardcoded if hardcoded is not None else {} # Setup vault self.vault_client = None if hvac: self.vault_client = hvac.Client( - url=self._load_or_none('VAULT_URL'), - token=self._load_or_none('VAULT_TOKEN'), + url=self._load_or_none(ENV_KEY_VAULT_URL), + token=self._load_or_none(ENV_KEY_VAULT_TOKEN), + vault_mount_point=self._load_or_none(ENV_KEY_VAULT_MOUNT_POINT), ) - self.vault_mount_point=self._load_or_none('VAULT_MOUNT_POINT') def load_or_fail(self, env_key: str) -> str: value = self._load_or_none(env_key) if value is None: - msg = 'Could not load secret {}'.format(env_key) + msg = f'Could not load secret {env_key}' raise Exception(msg) logger.info('Loaded secret: %s', env_key) return value @@ -48,7 +55,7 @@ class SecretLoader: return value def _load_or_none(self, env_key: str) -> str | None: - return self._load_or_none(env_key) + return self.hardcoded.get(env_key) or self._load_or_none_path_or_file(env_key) or self._load_or_none_vault(env_key) def _load_or_none_path_or_file(self, env_key: str) -> str | None: # 1. & 2. diff --git a/test/test_init.py b/test/test_init.py index de2f8f9..d76e1ed 100644 --- a/test/test_init.py +++ b/test/test_init.py @@ -2,5 +2,5 @@ import secret_loader def test_init(): - secret_loader.SecretLoader('TEST') - + loader = secret_loader.SecretLoader('TEST', hardcoded = {'KEY': 'VALUE'}) + assert loader.load('KEY') == 'VALUE'