diff --git a/pyproject.toml b/pyproject.toml index 0c9fb25..40a76e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,10 @@ [project] name = "lib-secret-manager" -version = "0.2.0" +version = "0.3.0" description = "Shared secret manager that consumes secrets" readme = "README.md" requires-python = ">=3.10" authors = [{ name = "Florian Gänsejunge" }] -dependencies = ["simple-logger-handler"] [project.optional-dependencies] encryption = ["cryptography==46.0.2"] diff --git a/secret_manager/__init__.py b/secret_manager/__init__.py index e8bb4ab..62cd64f 100644 --- a/secret_manager/__init__.py +++ b/secret_manager/__init__.py @@ -1,6 +1,5 @@ -from .credentials_loader import return_credentials, cleanup_secret_files +import logging +from .credentials_loader import get_secret, cleanup_secret_files, MissingCredentialError -__all__ = [ - "return_credentials", - "cleanup_secret_files", -] \ No newline at end of file +logging.getLogger(__name__).addHandler(logging.NullHandler()) +__all__ = ["get_secret","cleanup_secret_files","MissingCredentialError"] \ No newline at end of file diff --git a/secret_manager/credentials_loader.py b/secret_manager/credentials_loader.py index 8e1271a..a3734c5 100644 --- a/secret_manager/credentials_loader.py +++ b/secret_manager/credentials_loader.py @@ -1,9 +1,35 @@ -from simple_logger_handler import setup_logger +import logging import os from typing import Set -logger = setup_logger(__name__) +logger = logging.getLogger(__name__) +class MissingCredentialError(RuntimeError): + """Neither the environment variable nor the secret file provided a value.""" + +def get_secret(env_var: str, path: str | None = None) -> str: + """Resolve a secret from an environment variable, falling back to a file. + + Resolution order: + 1. The environment variable ``env_var`` (if set and non-empty). + 2. The file at ``path`` (if given and it exists). + + Raises: + MissingCredentialError: If neither source provides a value. + """ + value = os.getenv(env_var, "").strip() + if value: + logger.debug(f"Loaded secret from environment variable {env_var}") + return value + + if path: + try: + return return_credentials(path) + except FileNotFoundError: + pass + + sources = f"environment variable {env_var}" + (f" or file {path}" if path else "") + raise MissingCredentialError(f"No credential found: set {sources}") def return_credentials(path: str) -> str: """Read and return credentials from a file."""