from __future__ import annotations import os import subprocess from typing import Any from yuxi.utils.logging_config import logger def resolve_secret(config: dict[str, Any], key: str, env_key: str = "") -> str: env_val = os.environ.get(env_key or key.upper(), "") if env_val: return env_val value = config.get(key, "") if isinstance(value, dict): source = value.get("source", "") path = value.get("path", "") command = value.get("command", "") env = value.get("env", "") if source == "file" and path: return _read_file_secret(path) if source == "exec" and command: return _exec_secret(command) if source == "env" and env: return os.environ.get(env, "") if source == "raw": return value.get("value", "") return str(value) if value else "" def _read_file_secret(path: str) -> str: try: with open(path, encoding="utf-8") as f: return f.read().strip() except OSError as e: logger.warning(f"[SecretResolver] Failed to read file '{path}': {e}") return "" def _exec_secret(command: str) -> str: try: result = subprocess.run( command, shell=True, capture_output=True, text=True, timeout=10, ) if result.returncode == 0: return result.stdout.strip() logger.warning(f"[SecretResolver] Command failed (exit={result.returncode}): {command}") return "" except subprocess.TimeoutExpired: logger.warning(f"[SecretResolver] Command timed out: {command}") return "" except Exception as e: logger.warning(f"[SecretResolver] Command execution failed: {e}") return ""