From f2086ef1c603f3bc3fdfe612cbd93fd4704e25d2 Mon Sep 17 00:00:00 2001 From: Srinivas Lingampalli Date: Fri, 8 May 2026 10:13:46 +0100 Subject: [PATCH 1/2] feat: updated flight client creation to include tls root certs for windows --- .../transport/arrow_flight/transport.py | 49 +++++++++++++++++-- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/dataconnect/transport/arrow_flight/transport.py b/dataconnect/transport/arrow_flight/transport.py index cd714ee..73bfa56 100644 --- a/dataconnect/transport/arrow_flight/transport.py +++ b/dataconnect/transport/arrow_flight/transport.py @@ -7,9 +7,12 @@ from __future__ import annotations +import base64 import json +import platform +import subprocess -from pyarrow import flight +import pyarrow.flight as flight from dataconnect.transport.base import Transport from dataconnect.transport.errors import ( @@ -55,17 +58,53 @@ def __init__( self._call_headers: list[tuple[bytes, bytes]] = [] scheme = "grpc+tls" if use_tls else "grpc" - location = f"{scheme}://{host}:{port}" + uri = f"{scheme}://{host}:{port}" try: - tls_root_certs = None # pending - self._client = flight.FlightClient(location, tls_root_certs=tls_root_certs) + self._client = self._get_client(uri, use_tls) except Exception as exc: - raise TransportConnectionError(f"Failed to connect to {location}: {exc}") from exc + raise TransportConnectionError(f"Failed to connect to {uri}: {exc}") from exc if token: self._call_headers.append((b"authorization", f"Bearer {token}".encode())) + def _get_client(self, uri: str, use_tls: bool) -> flight.FlightClient: + is_windows = platform.system() == "Windows" + + if use_tls and is_windows: + result = subprocess.run( + [ + "powershell.exe", + "-Command", + ( + "Get-ChildItem -Path Cert:\\LocalMachine\\Root | " + "ForEach-Object { [System.Convert]::ToBase64String($_.RawData) }" + ), + ], + capture_output=True, + text=True, + check=True, + ) + + pem_parts = [] + for b64 in result.stdout.splitlines(): + b64 = b64.strip() + if not b64: + continue + raw = base64.b64decode(b64) + encoded = base64.b64encode(raw).decode("ascii") + lines = ["-----BEGIN CERTIFICATE-----"] + lines += [encoded[i : i + 64] for i in range(0, len(encoded), 64)] + lines.append("-----END CERTIFICATE-----") + pem_parts.append("\n".join(lines)) + + pem_certs = "\n".join(pem_parts).encode("utf-8") + client = flight.FlightClient(uri, tls_root_certs=pem_certs) + else: + client = flight.FlightClient(uri) + + return client + def _options(self) -> flight.FlightCallOptions: return flight.FlightCallOptions(headers=self._call_headers) From 4cc65307bf0140f37403ca66b839a91dd6856e13 Mon Sep 17 00:00:00 2001 From: Srinivas Lingampalli Date: Fri, 8 May 2026 12:32:10 +0100 Subject: [PATCH 2/2] fix: removing redundant encoding/decoding --- dataconnect/transport/arrow_flight/transport.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dataconnect/transport/arrow_flight/transport.py b/dataconnect/transport/arrow_flight/transport.py index 73bfa56..b2050a4 100644 --- a/dataconnect/transport/arrow_flight/transport.py +++ b/dataconnect/transport/arrow_flight/transport.py @@ -63,7 +63,7 @@ def __init__( try: self._client = self._get_client(uri, use_tls) except Exception as exc: - raise TransportConnectionError(f"Failed to connect to {uri}: {exc}") from exc + raise TransportConnectionError(f"Failed to create FlightClient: {exc}") from exc if token: self._call_headers.append((b"authorization", f"Bearer {token}".encode())) @@ -91,10 +91,9 @@ def _get_client(self, uri: str, use_tls: bool) -> flight.FlightClient: b64 = b64.strip() if not b64: continue - raw = base64.b64decode(b64) - encoded = base64.b64encode(raw).decode("ascii") + base64.b64decode(b64, validate=True) lines = ["-----BEGIN CERTIFICATE-----"] - lines += [encoded[i : i + 64] for i in range(0, len(encoded), 64)] + lines += [b64[i : i + 64] for i in range(0, len(b64), 64)] lines.append("-----END CERTIFICATE-----") pem_parts.append("\n".join(lines))