mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-09 14:37:59 -05:00
Resolving some connection issues (#4129)
* fix: use CREWAI_PLUS_URL env var in precedence over PlusAPI configured value * feat: bypass TLS certificate verification when calling platform * test: fix test
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
"""Crewai Enterprise Tools."""
|
"""Crewai Enterprise Tools."""
|
||||||
|
import os
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
from typing import Any, Optional, Union, cast, get_origin
|
from typing import Any, Optional, Union, cast, get_origin
|
||||||
@@ -432,7 +432,11 @@ class CrewAIPlatformActionTool(BaseTool):
|
|||||||
payload = cleaned_kwargs
|
payload = cleaned_kwargs
|
||||||
|
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
url=api_url, headers=headers, json=payload, timeout=60
|
url=api_url,
|
||||||
|
headers=headers,
|
||||||
|
json=payload,
|
||||||
|
timeout=60,
|
||||||
|
verify=os.environ.get("CREWAI_FACTORY", "false").lower() != "true",
|
||||||
)
|
)
|
||||||
|
|
||||||
data = response.json()
|
data = response.json()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
import os
|
||||||
from crewai.tools import BaseTool
|
from crewai.tools import BaseTool
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
@@ -37,6 +37,7 @@ class CrewaiPlatformToolBuilder:
|
|||||||
headers=headers,
|
headers=headers,
|
||||||
timeout=30,
|
timeout=30,
|
||||||
params={"apps": ",".join(self._apps)},
|
params={"apps": ",".join(self._apps)},
|
||||||
|
verify=os.environ.get("CREWAI_FACTORY", "false").lower() != "true",
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
from typing import Union, get_args, get_origin
|
from typing import Union, get_args, get_origin
|
||||||
|
from unittest.mock import patch, Mock
|
||||||
|
import os
|
||||||
|
|
||||||
from crewai_tools.tools.crewai_platform_tools.crewai_platform_action_tool import (
|
from crewai_tools.tools.crewai_platform_tools.crewai_platform_action_tool import (
|
||||||
CrewAIPlatformActionTool,
|
CrewAIPlatformActionTool,
|
||||||
@@ -249,3 +251,109 @@ class TestSchemaProcessing:
|
|||||||
result_type = tool._process_schema_type(test_schema, "TestFieldAllOfMixed")
|
result_type = tool._process_schema_type(test_schema, "TestFieldAllOfMixed")
|
||||||
|
|
||||||
assert result_type is str
|
assert result_type is str
|
||||||
|
|
||||||
|
class TestCrewAIPlatformActionToolVerify:
|
||||||
|
"""Test suite for SSL verification behavior based on CREWAI_FACTORY environment variable"""
|
||||||
|
|
||||||
|
def setup_method(self):
|
||||||
|
self.action_schema = {
|
||||||
|
"function": {
|
||||||
|
"name": "test_action",
|
||||||
|
"parameters": {
|
||||||
|
"properties": {
|
||||||
|
"test_param": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Test parameter"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def create_test_tool(self):
|
||||||
|
return CrewAIPlatformActionTool(
|
||||||
|
description="Test action tool",
|
||||||
|
action_name="test_action",
|
||||||
|
action_schema=self.action_schema
|
||||||
|
)
|
||||||
|
|
||||||
|
@patch.dict("os.environ", {"CREWAI_PLATFORM_INTEGRATION_TOKEN": "test_token"}, clear=True)
|
||||||
|
@patch("crewai_tools.tools.crewai_platform_tools.crewai_platform_action_tool.requests.post")
|
||||||
|
def test_run_with_ssl_verification_default(self, mock_post):
|
||||||
|
"""Test that _run uses SSL verification by default when CREWAI_FACTORY is not set"""
|
||||||
|
mock_response = Mock()
|
||||||
|
mock_response.ok = True
|
||||||
|
mock_response.json.return_value = {"result": "success"}
|
||||||
|
mock_post.return_value = mock_response
|
||||||
|
|
||||||
|
tool = self.create_test_tool()
|
||||||
|
tool._run(test_param="test_value")
|
||||||
|
|
||||||
|
mock_post.assert_called_once()
|
||||||
|
call_args = mock_post.call_args
|
||||||
|
assert call_args.kwargs["verify"] is True
|
||||||
|
|
||||||
|
@patch.dict("os.environ", {"CREWAI_PLATFORM_INTEGRATION_TOKEN": "test_token", "CREWAI_FACTORY": "false"}, clear=True)
|
||||||
|
@patch("crewai_tools.tools.crewai_platform_tools.crewai_platform_action_tool.requests.post")
|
||||||
|
def test_run_with_ssl_verification_factory_false(self, mock_post):
|
||||||
|
"""Test that _run uses SSL verification when CREWAI_FACTORY is 'false'"""
|
||||||
|
mock_response = Mock()
|
||||||
|
mock_response.ok = True
|
||||||
|
mock_response.json.return_value = {"result": "success"}
|
||||||
|
mock_post.return_value = mock_response
|
||||||
|
|
||||||
|
tool = self.create_test_tool()
|
||||||
|
tool._run(test_param="test_value")
|
||||||
|
|
||||||
|
mock_post.assert_called_once()
|
||||||
|
call_args = mock_post.call_args
|
||||||
|
assert call_args.kwargs["verify"] is True
|
||||||
|
|
||||||
|
@patch.dict("os.environ", {"CREWAI_PLATFORM_INTEGRATION_TOKEN": "test_token", "CREWAI_FACTORY": "FALSE"}, clear=True)
|
||||||
|
@patch("crewai_tools.tools.crewai_platform_tools.crewai_platform_action_tool.requests.post")
|
||||||
|
def test_run_with_ssl_verification_factory_false_uppercase(self, mock_post):
|
||||||
|
"""Test that _run uses SSL verification when CREWAI_FACTORY is 'FALSE' (case-insensitive)"""
|
||||||
|
mock_response = Mock()
|
||||||
|
mock_response.ok = True
|
||||||
|
mock_response.json.return_value = {"result": "success"}
|
||||||
|
mock_post.return_value = mock_response
|
||||||
|
|
||||||
|
tool = self.create_test_tool()
|
||||||
|
tool._run(test_param="test_value")
|
||||||
|
|
||||||
|
mock_post.assert_called_once()
|
||||||
|
call_args = mock_post.call_args
|
||||||
|
assert call_args.kwargs["verify"] is True
|
||||||
|
|
||||||
|
@patch.dict("os.environ", {"CREWAI_PLATFORM_INTEGRATION_TOKEN": "test_token", "CREWAI_FACTORY": "true"}, clear=True)
|
||||||
|
@patch("crewai_tools.tools.crewai_platform_tools.crewai_platform_action_tool.requests.post")
|
||||||
|
def test_run_without_ssl_verification_factory_true(self, mock_post):
|
||||||
|
"""Test that _run disables SSL verification when CREWAI_FACTORY is 'true'"""
|
||||||
|
mock_response = Mock()
|
||||||
|
mock_response.ok = True
|
||||||
|
mock_response.json.return_value = {"result": "success"}
|
||||||
|
mock_post.return_value = mock_response
|
||||||
|
|
||||||
|
tool = self.create_test_tool()
|
||||||
|
tool._run(test_param="test_value")
|
||||||
|
|
||||||
|
mock_post.assert_called_once()
|
||||||
|
call_args = mock_post.call_args
|
||||||
|
assert call_args.kwargs["verify"] is False
|
||||||
|
|
||||||
|
@patch.dict("os.environ", {"CREWAI_PLATFORM_INTEGRATION_TOKEN": "test_token", "CREWAI_FACTORY": "TRUE"}, clear=True)
|
||||||
|
@patch("crewai_tools.tools.crewai_platform_tools.crewai_platform_action_tool.requests.post")
|
||||||
|
def test_run_without_ssl_verification_factory_true_uppercase(self, mock_post):
|
||||||
|
"""Test that _run disables SSL verification when CREWAI_FACTORY is 'TRUE' (case-insensitive)"""
|
||||||
|
mock_response = Mock()
|
||||||
|
mock_response.ok = True
|
||||||
|
mock_response.json.return_value = {"result": "success"}
|
||||||
|
mock_post.return_value = mock_response
|
||||||
|
|
||||||
|
tool = self.create_test_tool()
|
||||||
|
tool._run(test_param="test_value")
|
||||||
|
|
||||||
|
mock_post.assert_called_once()
|
||||||
|
call_args = mock_post.call_args
|
||||||
|
assert call_args.kwargs["verify"] is False
|
||||||
|
|||||||
@@ -258,3 +258,98 @@ class TestCrewaiPlatformToolBuilder(unittest.TestCase):
|
|||||||
assert "simple_string" in description_text
|
assert "simple_string" in description_text
|
||||||
assert "nested_object" in description_text
|
assert "nested_object" in description_text
|
||||||
assert "array_prop" in description_text
|
assert "array_prop" in description_text
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TestCrewaiPlatformToolBuilderVerify(unittest.TestCase):
|
||||||
|
"""Test suite for SSL verification behavior in CrewaiPlatformToolBuilder"""
|
||||||
|
|
||||||
|
@patch.dict("os.environ", {"CREWAI_PLATFORM_INTEGRATION_TOKEN": "test_token"}, clear=True)
|
||||||
|
@patch(
|
||||||
|
"crewai_tools.tools.crewai_platform_tools.crewai_platform_tool_builder.requests.get"
|
||||||
|
)
|
||||||
|
def test_fetch_actions_with_ssl_verification_default(self, mock_get):
|
||||||
|
"""Test that _fetch_actions uses SSL verification by default when CREWAI_FACTORY is not set"""
|
||||||
|
mock_response = Mock()
|
||||||
|
mock_response.raise_for_status.return_value = None
|
||||||
|
mock_response.json.return_value = {"actions": {}}
|
||||||
|
mock_get.return_value = mock_response
|
||||||
|
|
||||||
|
builder = CrewaiPlatformToolBuilder(apps=["github"])
|
||||||
|
builder._fetch_actions()
|
||||||
|
|
||||||
|
mock_get.assert_called_once()
|
||||||
|
call_args = mock_get.call_args
|
||||||
|
assert call_args.kwargs["verify"] is True
|
||||||
|
|
||||||
|
@patch.dict("os.environ", {"CREWAI_PLATFORM_INTEGRATION_TOKEN": "test_token", "CREWAI_FACTORY": "false"}, clear=True)
|
||||||
|
@patch(
|
||||||
|
"crewai_tools.tools.crewai_platform_tools.crewai_platform_tool_builder.requests.get"
|
||||||
|
)
|
||||||
|
def test_fetch_actions_with_ssl_verification_factory_false(self, mock_get):
|
||||||
|
"""Test that _fetch_actions uses SSL verification when CREWAI_FACTORY is 'false'"""
|
||||||
|
mock_response = Mock()
|
||||||
|
mock_response.raise_for_status.return_value = None
|
||||||
|
mock_response.json.return_value = {"actions": {}}
|
||||||
|
mock_get.return_value = mock_response
|
||||||
|
|
||||||
|
builder = CrewaiPlatformToolBuilder(apps=["github"])
|
||||||
|
builder._fetch_actions()
|
||||||
|
|
||||||
|
mock_get.assert_called_once()
|
||||||
|
call_args = mock_get.call_args
|
||||||
|
assert call_args.kwargs["verify"] is True
|
||||||
|
|
||||||
|
@patch.dict("os.environ", {"CREWAI_PLATFORM_INTEGRATION_TOKEN": "test_token", "CREWAI_FACTORY": "FALSE"}, clear=True)
|
||||||
|
@patch(
|
||||||
|
"crewai_tools.tools.crewai_platform_tools.crewai_platform_tool_builder.requests.get"
|
||||||
|
)
|
||||||
|
def test_fetch_actions_with_ssl_verification_factory_false_uppercase(self, mock_get):
|
||||||
|
"""Test that _fetch_actions uses SSL verification when CREWAI_FACTORY is 'FALSE' (case-insensitive)"""
|
||||||
|
mock_response = Mock()
|
||||||
|
mock_response.raise_for_status.return_value = None
|
||||||
|
mock_response.json.return_value = {"actions": {}}
|
||||||
|
mock_get.return_value = mock_response
|
||||||
|
|
||||||
|
builder = CrewaiPlatformToolBuilder(apps=["github"])
|
||||||
|
builder._fetch_actions()
|
||||||
|
|
||||||
|
mock_get.assert_called_once()
|
||||||
|
call_args = mock_get.call_args
|
||||||
|
assert call_args.kwargs["verify"] is True
|
||||||
|
|
||||||
|
@patch.dict("os.environ", {"CREWAI_PLATFORM_INTEGRATION_TOKEN": "test_token", "CREWAI_FACTORY": "true"}, clear=True)
|
||||||
|
@patch(
|
||||||
|
"crewai_tools.tools.crewai_platform_tools.crewai_platform_tool_builder.requests.get"
|
||||||
|
)
|
||||||
|
def test_fetch_actions_without_ssl_verification_factory_true(self, mock_get):
|
||||||
|
"""Test that _fetch_actions disables SSL verification when CREWAI_FACTORY is 'true'"""
|
||||||
|
mock_response = Mock()
|
||||||
|
mock_response.raise_for_status.return_value = None
|
||||||
|
mock_response.json.return_value = {"actions": {}}
|
||||||
|
mock_get.return_value = mock_response
|
||||||
|
|
||||||
|
builder = CrewaiPlatformToolBuilder(apps=["github"])
|
||||||
|
builder._fetch_actions()
|
||||||
|
|
||||||
|
mock_get.assert_called_once()
|
||||||
|
call_args = mock_get.call_args
|
||||||
|
assert call_args.kwargs["verify"] is False
|
||||||
|
|
||||||
|
@patch.dict("os.environ", {"CREWAI_PLATFORM_INTEGRATION_TOKEN": "test_token", "CREWAI_FACTORY": "TRUE"}, clear=True)
|
||||||
|
@patch(
|
||||||
|
"crewai_tools.tools.crewai_platform_tools.crewai_platform_tool_builder.requests.get"
|
||||||
|
)
|
||||||
|
def test_fetch_actions_without_ssl_verification_factory_true_uppercase(self, mock_get):
|
||||||
|
"""Test that _fetch_actions disables SSL verification when CREWAI_FACTORY is 'TRUE' (case-insensitive)"""
|
||||||
|
mock_response = Mock()
|
||||||
|
mock_response.raise_for_status.return_value = None
|
||||||
|
mock_response.json.return_value = {"actions": {}}
|
||||||
|
mock_get.return_value = mock_response
|
||||||
|
|
||||||
|
builder = CrewaiPlatformToolBuilder(apps=["github"])
|
||||||
|
builder._fetch_actions()
|
||||||
|
|
||||||
|
mock_get.assert_called_once()
|
||||||
|
call_args = mock_get.call_args
|
||||||
|
assert call_args.kwargs["verify"] is False
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from urllib.parse import urljoin
|
from urllib.parse import urljoin
|
||||||
|
import os
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from crewai.cli.config import Settings
|
from crewai.cli.config import Settings
|
||||||
@@ -33,9 +33,7 @@ class PlusAPI:
|
|||||||
if settings.org_uuid:
|
if settings.org_uuid:
|
||||||
self.headers["X-Crewai-Organization-Id"] = settings.org_uuid
|
self.headers["X-Crewai-Organization-Id"] = settings.org_uuid
|
||||||
|
|
||||||
self.base_url = (
|
self.base_url = os.getenv("CREWAI_PLUS_URL") or str(settings.enterprise_base_url) or DEFAULT_CREWAI_ENTERPRISE_URL
|
||||||
str(settings.enterprise_base_url) or DEFAULT_CREWAI_ENTERPRISE_URL
|
|
||||||
)
|
|
||||||
|
|
||||||
def _make_request(
|
def _make_request(
|
||||||
self, method: str, endpoint: str, **kwargs: Any
|
self, method: str, endpoint: str, **kwargs: Any
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import ANY, MagicMock, patch
|
from unittest.mock import ANY, MagicMock, patch
|
||||||
|
|
||||||
from crewai.cli.constants import DEFAULT_CREWAI_ENTERPRISE_URL
|
|
||||||
from crewai.cli.plus_api import PlusAPI
|
from crewai.cli.plus_api import PlusAPI
|
||||||
|
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ class TestPlusAPI(unittest.TestCase):
|
|||||||
):
|
):
|
||||||
mock_make_request.assert_called_once_with(
|
mock_make_request.assert_called_once_with(
|
||||||
method,
|
method,
|
||||||
f"{DEFAULT_CREWAI_ENTERPRISE_URL}{endpoint}",
|
f"{os.getenv('CREWAI_PLUS_URL')}{endpoint}",
|
||||||
headers={
|
headers={
|
||||||
"Authorization": ANY,
|
"Authorization": ANY,
|
||||||
"Content-Type": ANY,
|
"Content-Type": ANY,
|
||||||
@@ -53,7 +53,7 @@ class TestPlusAPI(unittest.TestCase):
|
|||||||
):
|
):
|
||||||
mock_settings = MagicMock()
|
mock_settings = MagicMock()
|
||||||
mock_settings.org_uuid = self.org_uuid
|
mock_settings.org_uuid = self.org_uuid
|
||||||
mock_settings.enterprise_base_url = DEFAULT_CREWAI_ENTERPRISE_URL
|
mock_settings.enterprise_base_url = os.getenv('CREWAI_PLUS_URL')
|
||||||
mock_settings_class.return_value = mock_settings
|
mock_settings_class.return_value = mock_settings
|
||||||
# re-initialize Client
|
# re-initialize Client
|
||||||
self.api = PlusAPI(self.api_key)
|
self.api = PlusAPI(self.api_key)
|
||||||
@@ -84,7 +84,7 @@ class TestPlusAPI(unittest.TestCase):
|
|||||||
def test_get_agent_with_org_uuid(self, mock_make_request, mock_settings_class):
|
def test_get_agent_with_org_uuid(self, mock_make_request, mock_settings_class):
|
||||||
mock_settings = MagicMock()
|
mock_settings = MagicMock()
|
||||||
mock_settings.org_uuid = self.org_uuid
|
mock_settings.org_uuid = self.org_uuid
|
||||||
mock_settings.enterprise_base_url = DEFAULT_CREWAI_ENTERPRISE_URL
|
mock_settings.enterprise_base_url = os.getenv('CREWAI_PLUS_URL')
|
||||||
mock_settings_class.return_value = mock_settings
|
mock_settings_class.return_value = mock_settings
|
||||||
# re-initialize Client
|
# re-initialize Client
|
||||||
self.api = PlusAPI(self.api_key)
|
self.api = PlusAPI(self.api_key)
|
||||||
@@ -115,7 +115,7 @@ class TestPlusAPI(unittest.TestCase):
|
|||||||
def test_get_tool_with_org_uuid(self, mock_make_request, mock_settings_class):
|
def test_get_tool_with_org_uuid(self, mock_make_request, mock_settings_class):
|
||||||
mock_settings = MagicMock()
|
mock_settings = MagicMock()
|
||||||
mock_settings.org_uuid = self.org_uuid
|
mock_settings.org_uuid = self.org_uuid
|
||||||
mock_settings.enterprise_base_url = DEFAULT_CREWAI_ENTERPRISE_URL
|
mock_settings.enterprise_base_url = os.getenv('CREWAI_PLUS_URL')
|
||||||
mock_settings_class.return_value = mock_settings
|
mock_settings_class.return_value = mock_settings
|
||||||
# re-initialize Client
|
# re-initialize Client
|
||||||
self.api = PlusAPI(self.api_key)
|
self.api = PlusAPI(self.api_key)
|
||||||
@@ -163,7 +163,7 @@ class TestPlusAPI(unittest.TestCase):
|
|||||||
def test_publish_tool_with_org_uuid(self, mock_make_request, mock_settings_class):
|
def test_publish_tool_with_org_uuid(self, mock_make_request, mock_settings_class):
|
||||||
mock_settings = MagicMock()
|
mock_settings = MagicMock()
|
||||||
mock_settings.org_uuid = self.org_uuid
|
mock_settings.org_uuid = self.org_uuid
|
||||||
mock_settings.enterprise_base_url = DEFAULT_CREWAI_ENTERPRISE_URL
|
mock_settings.enterprise_base_url = os.getenv('CREWAI_PLUS_URL')
|
||||||
mock_settings_class.return_value = mock_settings
|
mock_settings_class.return_value = mock_settings
|
||||||
# re-initialize Client
|
# re-initialize Client
|
||||||
self.api = PlusAPI(self.api_key)
|
self.api = PlusAPI(self.api_key)
|
||||||
@@ -320,6 +320,7 @@ class TestPlusAPI(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@patch("crewai.cli.plus_api.Settings")
|
@patch("crewai.cli.plus_api.Settings")
|
||||||
|
@patch.dict(os.environ, {"CREWAI_PLUS_URL": ""})
|
||||||
def test_custom_base_url(self, mock_settings_class):
|
def test_custom_base_url(self, mock_settings_class):
|
||||||
mock_settings = MagicMock()
|
mock_settings = MagicMock()
|
||||||
mock_settings.enterprise_base_url = "https://custom-url.com/api"
|
mock_settings.enterprise_base_url = "https://custom-url.com/api"
|
||||||
@@ -329,3 +330,11 @@ class TestPlusAPI(unittest.TestCase):
|
|||||||
custom_api.base_url,
|
custom_api.base_url,
|
||||||
"https://custom-url.com/api",
|
"https://custom-url.com/api",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@patch.dict(os.environ, {"CREWAI_PLUS_URL": "https://custom-url-from-env.com"})
|
||||||
|
def test_custom_base_url_from_env(self):
|
||||||
|
custom_api = PlusAPI("test_key")
|
||||||
|
self.assertEqual(
|
||||||
|
custom_api.base_url,
|
||||||
|
"https://custom-url-from-env.com",
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user