security: harden connector policy and add dashboard widget

This commit is contained in:
2026-07-29 14:16:29 +02:00
parent 93eea839c8
commit 5b868272b9
9 changed files with 416 additions and 32 deletions
@@ -246,11 +246,11 @@ def _applied_fields(policy: Mapping[str, Any]) -> tuple[str, ...]:
def _matches_field(request: ConnectorAccessRequest, field: str, patterns: list[str]) -> bool:
if field == "connectors":
return _matches_exact(request.connector_id, patterns)
return _matches_reference(request.connector_id, patterns)
if field == "credentials":
return _matches_exact(request.credential_id, patterns)
return _matches_reference(request.credential_id, patterns)
if field == "providers":
return _matches_exact(request.provider, patterns)
return _matches_reference(request.provider, patterns)
if field == "external_ids":
return _matches_glob(request.external_id, patterns)
if field == "external_paths":
@@ -260,11 +260,11 @@ def _matches_field(request: ConnectorAccessRequest, field: str, patterns: list[s
return False
def _matches_exact(value: str | None, patterns: list[str]) -> bool:
def _matches_reference(value: str | None, patterns: list[str]) -> bool:
if value is None:
return False
clean = value.casefold()
return any(pattern == "*" or clean == pattern.casefold() for pattern in patterns)
return any(fnmatchcase(clean, pattern.casefold()) for pattern in patterns)
def _matches_glob(value: str | None, patterns: list[str]) -> bool:
@@ -185,15 +185,23 @@ class _OutboundPolicyHTTPTransport(httpx.BaseTransport):
self._connection_pool.close()
_CONNECTOR_HTTP_CLIENT = httpx.Client(
transport=_OutboundPolicyHTTPTransport(),
follow_redirects=False,
timeout=15.0,
)
@contextmanager
def _stream_connector_request(method: str, url: str, **kwargs: Any) -> Iterator[httpx.Response]:
with httpx.Client(
transport=_OutboundPolicyHTTPTransport(),
follow_redirects=False,
timeout=kwargs.pop("timeout", 15.0),
) as client:
with client.stream(method, url, **kwargs) as response:
yield response
timeout = kwargs.pop("timeout", 15.0)
with _CONNECTOR_HTTP_CLIENT.stream(
method,
url,
timeout=timeout,
**kwargs,
) as response:
yield response
def request_connector_bytes(