Harden external file connector boundaries

This commit is contained in:
2026-07-21 12:10:23 +02:00
parent 3bc1d3489e
commit f2dfb6c90e
18 changed files with 1167 additions and 64 deletions
@@ -7,6 +7,10 @@ from dataclasses import dataclass, field
from typing import Any
from govoplan_core.core.policy import normalize_policy_scope_type, policy_source_path
from govoplan_files.backend.storage.connector_deployment import (
connector_secret_env_available,
validate_deployment_connector_references,
)
from govoplan_files.backend.storage.connector_policy import ConnectorPolicySource, connector_policy_sources_from_payload
@@ -82,9 +86,9 @@ class ConnectorProfile:
if self.secret_ref or self.has_inline_secret or self.password_value or self.token_value:
return True
if self.token_env:
return bool(os.environ.get(self.token_env))
return connector_secret_env_available(self.token_env, source_kind=self.source_kind)
if self.password_env:
return bool(os.environ.get(self.password_env))
return connector_secret_env_available(self.password_env, source_kind=self.source_kind)
return False
def to_response(self) -> dict[str, Any]:
@@ -106,7 +110,7 @@ class ConnectorProfile:
"username": self.username,
"capabilities": list(self.capabilities),
"policy_sources": [_policy_source_response(source) for source in self.policy_sources],
"metadata": dict(self.metadata),
"metadata": _response_metadata(self.metadata),
"source_kind": self.source_kind,
}
@@ -146,7 +150,7 @@ def _profile_from_mapping(value: Mapping[str, Any]) -> ConnectorProfile:
credential_mode=mode,
credentials=credentials,
)
return ConnectorProfile(
result = ConnectorProfile(
id=profile.id,
label=profile.label,
provider=profile.provider,
@@ -170,6 +174,13 @@ def _profile_from_mapping(value: Mapping[str, Any]) -> ConnectorProfile:
metadata=profile.metadata,
source_kind="settings",
)
validate_deployment_connector_references(
source_kind=result.source_kind,
password_env=result.password_env,
token_env=result.token_env,
metadata=result.metadata,
)
return result
def _profile_id_from_mapping(value: Mapping[str, Any]) -> str:
@@ -291,6 +302,16 @@ def _public_metadata(value: object) -> Mapping[str, Any]:
}
def _response_metadata(value: Mapping[str, Any]) -> dict[str, Any]:
return {
str(key): item
for key, item in value.items()
if str(key).strip().casefold() not in _INLINE_SECRET_FIELDS
and not str(key).strip().casefold().endswith("_env")
and str(key).strip().casefold() != "ca_bundle"
}
def _string_list(value: object) -> list[str]:
if value is None:
return []