fix: harden evidence secret file handoff
This commit is contained in:
+18
-7
@@ -49,13 +49,17 @@ def _expand_env(value: Any) -> Any:
|
||||
_MAX_SIGNED_URL_FILE_BYTES = 1024 * 1024
|
||||
|
||||
|
||||
def _resolve_http_signed_url_files(value: Any) -> Any:
|
||||
def _resolve_evidence_secret_files(value: Any) -> Any:
|
||||
"""Resolve only signed HTTP URL arrays, keeping their values out of public errors."""
|
||||
if isinstance(value, dict):
|
||||
resolved = {
|
||||
key: _resolve_http_signed_url_files(item)
|
||||
key: _resolve_evidence_secret_files(item)
|
||||
for key, item in value.items()
|
||||
}
|
||||
if resolved.get("type") == "s3" and any(
|
||||
name in resolved for name in ("access_key", "secret_key", "session_token")
|
||||
):
|
||||
raise ConfigError("S3 Evidence credentials require *_file references")
|
||||
if resolved.get("type") != "http" or "signed_urls_file" not in resolved:
|
||||
return resolved
|
||||
if "urls" in resolved:
|
||||
@@ -94,10 +98,13 @@ def _resolve_http_signed_url_files(value: Any) -> Any:
|
||||
resolved["urls"] = parsed
|
||||
return resolved
|
||||
if isinstance(value, list):
|
||||
return [_resolve_http_signed_url_files(item) for item in value]
|
||||
return [_resolve_evidence_secret_files(item) for item in value]
|
||||
return value
|
||||
|
||||
|
||||
_MAX_SCALAR_SECRET_FILE_BYTES = 64 * 1024
|
||||
|
||||
|
||||
def _resolve_secret_files(value: Any) -> Any:
|
||||
if isinstance(value, dict):
|
||||
resolved = {key: _resolve_secret_files(item) for key, item in value.items()}
|
||||
@@ -109,9 +116,13 @@ def _resolve_secret_files(value: Any) -> Any:
|
||||
raise ConfigError(f"{secret_name} and {file_name} are mutually exclusive")
|
||||
path = Path(resolved.pop(file_name))
|
||||
try:
|
||||
secret = path.read_text()
|
||||
except (OSError, UnicodeError) as exc:
|
||||
raise ConfigError(f"Cannot read secret file: {path}") from exc
|
||||
with path.open("rb") as stream:
|
||||
payload = stream.read(_MAX_SCALAR_SECRET_FILE_BYTES + 1)
|
||||
if len(payload) > _MAX_SCALAR_SECRET_FILE_BYTES:
|
||||
raise OSError
|
||||
secret = payload.decode("utf-8")
|
||||
except (OSError, UnicodeError):
|
||||
raise ConfigError(f"Cannot read secret file: {path}") from None
|
||||
if not secret or any(char.isspace() for char in secret) or "\x00" in secret:
|
||||
raise ConfigError(f"Invalid secret file: {path}")
|
||||
resolved[secret_name] = secret
|
||||
@@ -532,7 +543,7 @@ def load_config(path: Path) -> Config:
|
||||
raise ConfigError(f"Configurazione YAML non valida: {path}") from exc
|
||||
if not isinstance(raw, dict):
|
||||
raise ConfigError(f"Configurazione non valida (atteso un mapping YAML): {path}")
|
||||
expanded = _resolve_secret_files(_resolve_http_signed_url_files(_expand_env(raw)))
|
||||
expanded = _resolve_secret_files(_resolve_evidence_secret_files(_expand_env(raw)))
|
||||
_validate_internal_embedding_contract(expanded, path)
|
||||
_validate_internal_vector_contract(expanded, path)
|
||||
translated, used_legacy = translate_legacy_config(expanded)
|
||||
|
||||
Reference in New Issue
Block a user