Skip to content

Commit 6fe25d1

Browse files
authored
Revert PR #1754: Environment-based cert discovery (#1758)
This reverts commit 7092618. Reverting due to WCA SSL failure observed after the introduction of environment-based certificate discovery functionality. Changes reverted: - Removed SERVICE_CA_PATH setting from base.py - Removed _setup_ssl_context() and get_ssl_verification() methods from pipelines.py - Restored original SSL verification logic using ca_cert_file precedence - Reverted SSL/TLS documentation changes in README.md - Reverted test files to their pre-PR state This restores the previous SSL verification behavior: verify=(self.config.ca_cert_file if self.config.ca_cert_file else self.config.verify_ssl)
1 parent eb7f605 commit 6fe25d1

File tree

6 files changed

+64
-868
lines changed

6 files changed

+64
-868
lines changed

README.md

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ ENABLE_ARI_POSTPROCESS="False"
2727
WCA_SECRET_BACKEND_TYPE="dummy"
2828
# configure model server
2929
ANSIBLE_AI_MODEL_MESH_CONFIG="..."
30-
# configure SSL certificate path (optional)
31-
# ANSIBLE_AI_SERVICE_CA_PATH="/etc/ssl/certs/ca-certificates.crt"
3230
```
3331
See the example [ANSIBLE_AI_MODEL_MESH_CONFIG](./docs/config/examples/README-ANSIBLE_AI_MODEL_MESH_CONFIG.md).
3432

@@ -63,29 +61,6 @@ podman compose -f tools/docker-compose/compose.yaml down
6361

6462
### Service configuration
6563

66-
### SSL/TLS Certificate Configuration
67-
68-
For SSL communication with model servers and external services, you can configure the certificate authority (CA) certificate path:
69-
70-
```bash
71-
# Default: Uses OpenShift/Kubernetes service account certificate
72-
# Path: /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt
73-
74-
# Custom certificate path (for containerized installations outside OpenShift)
75-
export ANSIBLE_AI_SERVICE_CA_PATH="/etc/ssl/certs/ca-certificates.crt"
76-
77-
# Disable service CA certificate discovery (rely on system certificates only)
78-
export ANSIBLE_AI_SERVICE_CA_PATH=""
79-
```
80-
81-
**ANSIBLE_AI_SERVICE_CA_PATH**
82-
- **Default**: `/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt` (OpenShift/Kubernetes)
83-
- **Purpose**: Specifies the path to the CA certificate file for SSL verification
84-
- **Use Cases**:
85-
- **OpenShift/Kubernetes**: Default path works automatically
86-
- **Containerized deployments**: Set to `/etc/ssl/certs/ca-certificates.crt` or your custom path
87-
- **Development/Testing**: Set to empty string to disable custom CA and use system certificates
88-
8964
### Secret storage
9065
For most development usages, you can skip the call to AWS Secrets Manager
9166
and always use the dummy `WCA_SECRET_BACKEND_TYPE` by setting the following in your

ansible_ai_connect/ai/api/model_pipelines/http/pipelines.py

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import copy
1616
import json
1717
import logging
18-
import os
1918
import ssl
2019
from json import JSONDecodeError
2120
from typing import Any, AsyncGenerator
@@ -71,34 +70,10 @@ def __init__(self, config: HttpConfiguration):
7170
self.headers = {"Content-Type": "application/json"}
7271
i = self.config.timeout
7372
self._timeout = int(i) if i is not None else None
74-
# Help ssl.create_default_context() find mounted certificates
75-
self._setup_ssl_context()
7673

7774
def task_gen_timeout(self, task_count=1):
7875
return self._timeout * task_count if self._timeout else None
7976

80-
def _setup_ssl_context(self):
81-
"""Let ssl.create_default_context() discover certs.
82-
Following container best practices - use environment variables to help
83-
Python's default SSL context find mounted certificates automatically.
84-
This avoids explicit certificate path management in application code.
85-
"""
86-
if self.config.verify_ssl:
87-
# Check for mounted service-ca certificate (container/K8s pattern)
88-
service_ca = settings.SERVICE_CA_PATH
89-
if os.path.exists(service_ca):
90-
os.environ.setdefault("REQUESTS_CA_BUNDLE", service_ca)
91-
os.environ.setdefault("SSL_CERT_FILE", service_ca)
92-
logger.info("Configured SSL context to use mounted service-ca certificate")
93-
94-
def get_ssl_verification(self):
95-
"""Just return verify_ssl boolean.
96-
ssl.create_default_context() will automatically discover certificates
97-
via environment variables set in _setup_ssl_context().
98-
No explicit certificate path management needed.
99-
"""
100-
return self.config.verify_ssl
101-
10277

10378
@Register(api_type="http")
10479
class HttpCompletionsPipeline(HttpMetaData, ModelPipelineCompletions[HttpConfiguration]):
@@ -122,7 +97,9 @@ def invoke(self, params: CompletionsParameters) -> CompletionsResponse:
12297
headers=self.headers,
12398
json=model_input,
12499
timeout=self.task_gen_timeout(task_count),
125-
verify=self.get_ssl_verification(),
100+
verify=(
101+
self.config.ca_cert_file if self.config.ca_cert_file else self.config.verify_ssl
102+
),
126103
)
127104
result.raise_for_status()
128105
response = json.loads(result.text)
@@ -142,7 +119,9 @@ def self_test(self) -> HealthCheckSummary:
142119
try:
143120
res = requests.get(
144121
url,
145-
verify=self.get_ssl_verification(),
122+
verify=(
123+
self.config.ca_cert_file if self.config.ca_cert_file else self.config.verify_ssl
124+
),
146125
timeout=1,
147126
)
148127
res.raise_for_status()
@@ -176,7 +155,9 @@ def self_test(self) -> HealthCheckSummary:
176155
self.config.inference_url + "/readiness",
177156
headers=headers,
178157
timeout=1,
179-
verify=self.get_ssl_verification(),
158+
verify=(
159+
self.config.ca_cert_file if self.config.ca_cert_file else self.config.verify_ssl
160+
),
180161
)
181162
r.raise_for_status()
182163

@@ -233,7 +214,7 @@ def invoke(self, params: ChatBotParameters) -> ChatBotResponse:
233214
headers=self.headers,
234215
json=data,
235216
timeout=self.task_gen_timeout(1),
236-
verify=self.get_ssl_verification(),
217+
verify=self.config.ca_cert_file if self.config.ca_cert_file else self.config.verify_ssl,
237218
)
238219

239220
if response.status_code == 200:
@@ -296,8 +277,9 @@ def send_schema1_event(self, ev):
296277

297278
async def async_invoke(self, params: StreamingChatBotParameters) -> AsyncGenerator:
298279

299-
if self.config.verify_ssl:
300-
ssl_context = ssl.create_default_context()
280+
# Configure SSL context based on verify_ssl setting
281+
if self.config.ca_cert_file:
282+
ssl_context = ssl.create_default_context(cafile=self.config.ca_cert_file)
301283
connector = aiohttp.TCPConnector(ssl=ssl_context)
302284
else:
303285
connector = aiohttp.TCPConnector(ssl=self.config.verify_ssl)

ansible_ai_connect/ai/api/model_pipelines/http/tests/test_pipelines.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
# limitations under the License.
1515
import json
1616
import logging
17-
import ssl
1817
from typing import cast
1918
from unittest import IsolatedAsyncioTestCase
2019
from unittest.mock import MagicMock, patch
@@ -247,11 +246,8 @@ async def test_ssl_context_verify_ssl_true(self, mock_tcp_connector, mock_post):
247246
params = self.get_params()
248247
async for _ in pipeline.async_invoke(params):
249248
pass
250-
# Verify TCPConnector was created with SSL context when verify_ssl=True
251-
mock_tcp_connector.assert_called_once()
252-
call_args = mock_tcp_connector.call_args[1]["ssl"]
253-
# Should be an SSLContext object when verify_ssl=True
254-
self.assertIsInstance(call_args, ssl.SSLContext)
249+
# Verify TCPConnector was created with ssl=True
250+
mock_tcp_connector.assert_called_once_with(ssl=True)
255251

256252
@patch("aiohttp.ClientSession.post")
257253
@patch("aiohttp.TCPConnector")
@@ -298,13 +294,7 @@ async def test_ssl_context_integration_with_existing_flow(self, mock_tcp_connect
298294
# Verify that streaming still works
299295
self.assertGreater(result_count, 0, "Streaming should return data")
300296
# Verify SSL configuration is correct
301-
call_args = mock_tcp_connector.call_args[1]["ssl"]
302-
if verify_ssl_value:
303-
# When verify_ssl=True, should get an SSLContext object
304-
self.assertIsInstance(call_args, ssl.SSLContext)
305-
else:
306-
# When verify_ssl=False, should get False
307-
self.assertEqual(call_args, False)
297+
mock_tcp_connector.assert_called_with(ssl=verify_ssl_value)
308298
# Reset mocks for next iteration
309299
mock_tcp_connector.reset_mock()
310300
mock_post.reset_mock()

0 commit comments

Comments
 (0)