58 lines
1.4 KiB
Python
58 lines
1.4 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import logging
|
||
|
|
import os
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
|
||
|
|
def read_secret_file(filepath: str) -> str:
|
||
|
|
if not filepath:
|
||
|
|
raise ValueError("filepath cannot be empty")
|
||
|
|
|
||
|
|
real_path = os.path.realpath(filepath)
|
||
|
|
if real_path != os.path.abspath(filepath):
|
||
|
|
raise ValueError("Secret file path contains symlinks, which is not allowed")
|
||
|
|
|
||
|
|
try:
|
||
|
|
with open(filepath, encoding="utf-8") as f:
|
||
|
|
content = f.read()
|
||
|
|
except FileNotFoundError:
|
||
|
|
raise ValueError(f"Secret file not found: {filepath}")
|
||
|
|
except PermissionError:
|
||
|
|
raise ValueError(f"Permission denied reading secret file: {filepath}")
|
||
|
|
|
||
|
|
return content.strip()
|
||
|
|
|
||
|
|
|
||
|
|
def resolve_credential(
|
||
|
|
direct_value: str | None,
|
||
|
|
file_path: str | None,
|
||
|
|
env_var: str | None = None,
|
||
|
|
) -> str:
|
||
|
|
if direct_value:
|
||
|
|
return direct_value
|
||
|
|
if file_path:
|
||
|
|
return read_secret_file(file_path)
|
||
|
|
if env_var:
|
||
|
|
val = os.getenv(env_var, "")
|
||
|
|
if val:
|
||
|
|
return val
|
||
|
|
return ""
|
||
|
|
|
||
|
|
|
||
|
|
def resolve_credential_with_source(
|
||
|
|
direct_value: str | None,
|
||
|
|
file_path: str | None,
|
||
|
|
env_var: str | None = None,
|
||
|
|
) -> tuple[str, str]:
|
||
|
|
if direct_value:
|
||
|
|
return direct_value, "config"
|
||
|
|
if file_path:
|
||
|
|
return read_secret_file(file_path), "secretFile"
|
||
|
|
if env_var:
|
||
|
|
val = os.getenv(env_var, "")
|
||
|
|
if val:
|
||
|
|
return val, "env"
|
||
|
|
return "", "none"
|