secrets-engine/src/secrets_engine/config.py
tegwick f4b4dd6b17
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 2s
Use bounded Railiance time for protected validity checks
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a09cbb-87c6-7900-a145-4ce53ba9f1a6
2026-09-15 22:16:31 +02:00

99 lines
4.3 KiB
Python

"""Runtime configuration resolved from environment and repo layout.
Nothing here is a secret. Backend auth (named providers in engine_auth) is
resolved lazily inside the backend adapter, never cached on disk by this module.
"""
from __future__ import annotations
import os
from dataclasses import dataclass
from pathlib import Path
def repo_root() -> Path:
"""Repo root = nearest ancestor containing pyproject.toml (fallback: cwd)."""
here = Path(__file__).resolve()
for parent in (here, *here.parents):
if (parent / "pyproject.toml").exists():
return parent
return Path.cwd()
def _positive_int(raw: str, default: int = 1) -> int:
"""Parse a positive approval threshold. Anything malformed keeps the default."""
try:
value = int(raw)
except (TypeError, ValueError):
return default
return value if value >= 1 else default
@dataclass(frozen=True)
class Config:
catalog_dir: Path
policy_dir: Path
evidence_dir: Path
hub_url: str
bao_addr: str
topic_id: str
approval_url: str = ""
approval_token_file: Path | None = None
approval_client_secret_file: Path | None = None
keycape_token_url: str = ""
keycape_issuer: str = ""
keycape_client_secret_file: Path | None = None
openbao_jwt_login_file: Path | None = None
# PIP/PDP join (SECRETS-WP-0007-T04 / SECRETS-WP-0008-T02). All absent by
# default: an unset value fails production closed exactly as before.
authorization_subject_id: str = ""
authorization_subject_type: str = ""
authorization_policy_package: str = ""
authorization_policy_version: str = ""
authorization_min_approvals: int = 1
pdp_url: str = ""
pdp_token_file: Path | None = None
clock_trust_file: Path | None = None
@classmethod
def load(cls) -> "Config":
root = repo_root()
token_file = os.environ.get("SECRETS_ENGINE_APPROVAL_TOKEN_FILE", "")
approval_secret = os.environ.get("SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE", "")
keycape_secret = os.environ.get("SECRETS_ENGINE_KEYCAPE_CLIENT_SECRET_FILE", "")
jwt_login = os.environ.get("SECRETS_ENGINE_OPENBAO_JWT_LOGIN", "")
pdp_token = os.environ.get("SECRETS_ENGINE_PDP_TOKEN_FILE", "")
return cls(
catalog_dir=Path(os.environ.get("SECRETS_ENGINE_CATALOG", root / "catalog")),
policy_dir=Path(os.environ.get("SECRETS_ENGINE_POLICIES", root / "policies")),
evidence_dir=Path(os.environ.get("SECRETS_ENGINE_EVIDENCE", root / ".evidence")),
hub_url=os.environ.get("SECRETS_ENGINE_HUB_URL", "http://127.0.0.1:8000"),
bao_addr=os.environ.get("BAO_ADDR", os.environ.get("VAULT_ADDR", "http://127.0.0.1:8200")),
topic_id=os.environ.get(
"SECRETS_ENGINE_TOPIC_ID", "cee7bedf-2b48-46ef-8601-006474f2ad7a"
),
approval_url=os.environ.get("SECRETS_ENGINE_APPROVAL_URL", ""),
approval_token_file=Path(token_file) if token_file else None,
approval_client_secret_file=Path(approval_secret) if approval_secret else None,
keycape_token_url=os.environ.get("SECRETS_ENGINE_KEYCAPE_TOKEN_URL", ""),
keycape_issuer=os.environ.get("SECRETS_ENGINE_KEYCAPE_ISSUER", ""),
keycape_client_secret_file=Path(keycape_secret) if keycape_secret else None,
openbao_jwt_login_file=Path(jwt_login) if jwt_login else None,
authorization_subject_id=os.environ.get(
"SECRETS_ENGINE_AUTHORIZATION_SUBJECT_ID", ""
),
authorization_subject_type=os.environ.get(
"SECRETS_ENGINE_AUTHORIZATION_SUBJECT_TYPE", ""
),
authorization_policy_package=os.environ.get(
"SECRETS_ENGINE_AUTHORIZATION_POLICY_PACKAGE", ""
),
authorization_policy_version=os.environ.get(
"SECRETS_ENGINE_AUTHORIZATION_POLICY_VERSION", ""
),
authorization_min_approvals=_positive_int(
os.environ.get("SECRETS_ENGINE_AUTHORIZATION_MIN_APPROVALS", "")
),
pdp_url=os.environ.get("SECRETS_ENGINE_PDP_URL", ""),
pdp_token_file=Path(pdp_token) if pdp_token else None,
clock_trust_file=Path(os.environ["SECRETS_ENGINE_CLOCK_TRUST_FILE"]) if os.environ.get("SECRETS_ENGINE_CLOCK_TRUST_FILE") else None,
)