Skip to content

Commit 46ef483

Browse files
authored
fix: pass sys ssl certificates to bedrock client (#718)
1 parent e7a7c33 commit 46ef483

4 files changed

Lines changed: 95 additions & 8 deletions

File tree

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
[project]
22
name = "uipath-langchain"
3-
version = "0.9.3"
3+
version = "0.9.4"
44
description = "Python SDK that enables developers to build and deploy LangGraph agents to the UiPath Cloud Platform"
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"
77
dependencies = [
88
"uipath>=2.10.22, <2.11.0",
99
"uipath-core>=0.5.2, <0.6.0",
10-
"uipath-platform>=0.1.5, <0.2.0",
10+
"uipath-platform>=0.1.7, <0.2.0",
1111
"uipath-runtime>=0.9.1, <0.10.0",
1212
"langgraph>=1.0.0, <2.0.0",
1313
"langchain-core>=1.2.11, <2.0.0",

src/uipath_langchain/chat/bedrock.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
from langchain_core.messages import BaseMessage
88
from langchain_core.outputs import ChatGenerationChunk, ChatResult
99
from tenacity import AsyncRetrying, Retrying
10-
from uipath.platform.common import EndpointManager, resource_override
10+
from uipath.platform.common import (
11+
EndpointManager,
12+
get_ca_bundle_path,
13+
resource_override,
14+
)
1115

1216
from .http_client import build_uipath_headers, resolve_gateway_url
1317
from .http_client.header_capture import HeaderCapture
@@ -110,8 +114,10 @@ def _unsigned_config(self, **overrides):
110114

111115
def get_client(self):
112116
session = self._build_session()
117+
ca_bundle = get_ca_bundle_path()
113118
client = session.client(
114119
"bedrock-runtime",
120+
verify=ca_bundle if ca_bundle is not None else False,
115121
config=self._unsigned_config(
116122
retries={"total_max_attempts": 1},
117123
read_timeout=300,
@@ -127,8 +133,10 @@ def get_client(self):
127133

128134
def get_bedrock_client(self):
129135
session = self._build_session()
136+
ca_bundle = get_ca_bundle_path()
130137
return session.client(
131138
"bedrock",
139+
verify=ca_bundle if ca_bundle is not None else False,
132140
config=self._unsigned_config(),
133141
)
134142

tests/chat/test_bedrock.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,82 @@ def test_generate_converts_file_blocks(self, mock_session_cls):
167167
},
168168
}
169169
assert result == fake_result
170+
171+
172+
class TestBedrockSslConfiguration:
173+
def _make_passthrough(self):
174+
return AwsBedrockCompletionsPassthroughClient(
175+
model="anthropic.claude-haiku-4-5-20251001",
176+
token="test-token",
177+
api_flavor="converse",
178+
)
179+
180+
@patch("uipath_langchain.chat.bedrock.boto3.Session")
181+
@patch.dict(os.environ, {"SSL_CERT_FILE": "/tmp/test-ca-bundle.pem"}, clear=False)
182+
def test_get_client_uses_ssl_cert_file(self, mock_session_cls):
183+
os.environ.pop("REQUESTS_CA_BUNDLE", None)
184+
os.environ.pop("UIPATH_DISABLE_SSL_VERIFY", None)
185+
mock_session = mock_session_cls.return_value
186+
187+
self._make_passthrough().get_client()
188+
189+
mock_session.client.assert_called_once()
190+
_, kwargs = mock_session.client.call_args
191+
assert kwargs["verify"] == "/tmp/test-ca-bundle.pem"
192+
193+
@patch("uipath_langchain.chat.bedrock.boto3.Session")
194+
@patch.dict(os.environ, {"SSL_CERT_FILE": "/tmp/test-ca-bundle.pem"}, clear=False)
195+
def test_get_bedrock_client_uses_ssl_cert_file(self, mock_session_cls):
196+
os.environ.pop("REQUESTS_CA_BUNDLE", None)
197+
os.environ.pop("UIPATH_DISABLE_SSL_VERIFY", None)
198+
mock_session = mock_session_cls.return_value
199+
200+
self._make_passthrough().get_bedrock_client()
201+
202+
mock_session.client.assert_called_once()
203+
_, kwargs = mock_session.client.call_args
204+
assert kwargs["verify"] == "/tmp/test-ca-bundle.pem"
205+
206+
@patch("uipath_langchain.chat.bedrock.boto3.Session")
207+
@patch.dict(
208+
os.environ,
209+
{
210+
"SSL_CERT_FILE": "/tmp/ssl-cert.pem",
211+
"REQUESTS_CA_BUNDLE": "/tmp/requests-ca.pem",
212+
},
213+
clear=False,
214+
)
215+
def test_ssl_cert_file_takes_priority_over_requests_ca_bundle(
216+
self, mock_session_cls
217+
):
218+
os.environ.pop("UIPATH_DISABLE_SSL_VERIFY", None)
219+
mock_session = mock_session_cls.return_value
220+
221+
self._make_passthrough().get_client()
222+
223+
_, kwargs = mock_session.client.call_args
224+
assert kwargs["verify"] == "/tmp/ssl-cert.pem"
225+
226+
@patch("uipath_langchain.chat.bedrock.boto3.Session")
227+
@patch.dict(os.environ, {"UIPATH_DISABLE_SSL_VERIFY": "true"}, clear=False)
228+
def test_disable_ssl_verify(self, mock_session_cls):
229+
mock_session = mock_session_cls.return_value
230+
231+
self._make_passthrough().get_client()
232+
233+
_, kwargs = mock_session.client.call_args
234+
assert kwargs["verify"] is False
235+
236+
@patch("uipath_langchain.chat.bedrock.boto3.Session")
237+
def test_default_uses_certifi(self, mock_session_cls):
238+
import certifi
239+
240+
os.environ.pop("SSL_CERT_FILE", None)
241+
os.environ.pop("REQUESTS_CA_BUNDLE", None)
242+
os.environ.pop("UIPATH_DISABLE_SSL_VERIFY", None)
243+
mock_session = mock_session_cls.return_value
244+
245+
self._make_passthrough().get_client()
246+
247+
_, kwargs = mock_session.client.call_args
248+
assert kwargs["verify"] == certifi.where()

uv.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)