fix: improve certifi error message and docs for SOAR (#191) - #308
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
|
Hi @Som0111, thank you for contributing and tackling #191! Before we can review or merge contributions, Google requires a signed Contributor License Agreement (CLA). Please follow the steps in the CLA check to sign it. Once signed, please address the following review items: PowerShell Syntax in README: In server/secops-soar/README.md, $Env:SSL_CERT_FILE = python -m certifi causes a PowerShell parser error. Please update it to enclose the command in parentheses: $Env:SSL_CERT_FILE = (python -m certifi)Catch aiohttp.ClientSSLError in addition to ssl.SSLError: In http_client.py, some aiohttp SSL handshake failures raise aiohttp.ClientSSLError (which does not inherit from Python's ssl.SSLError). Please catch (ssl.SSLError, aiohttp.ClientSSLError) so all SSL failures are consistently reported. Fix Ruff Lint Errors: Please run ruff check on the modified files and combine the nested with statements in tests/unit/test_certificate_error_handling.py (Rule SIM117). Include Before/After Evidence: As noted in #191, please attach before/after execution logs or screenshots demonstrating the old error message versus the new actionable diagnostic message. |
dandye
left a comment
There was a problem hiding this comment.
Thanks for addressing the PowerShell syntax, ruff lint, and adding aiohttp.ClientSSLError to http_client.py in the latest commit.
There is one spot remaining in bindings.py:
In server/secops-soar/secops_soar_mcp/bindings.py:47, _get_valid_scopes() still catches only ssl.SSLError:
async def _get_valid_scopes():
try:
valid_scopes_list = await http_client.get(consts.Endpoints.GET_SCOPES)
except ssl.SSLError as e:
raise RuntimeError(_CERTIFICATE_ERROR_MESSAGE) from eBecause aiohttp.ClientSSLError does not inherit from ssl.SSLError (issubclass(aiohttp.ClientSSLError, ssl.SSLError) == False), any ClientSSLError re-raised by http_client.get() escapes _get_valid_scopes() without being wrapped in _CERTIFICATE_ERROR_MESSAGE.
We can reproduce this with a quick test:
@pytest.mark.asyncio
async def test_get_valid_scopes_reports_certificate_issue_on_client_ssl_error():
conn_key = aiohttp.client_reqrep.ConnectionKey("example.com", 443, True, True, None, None, None)
client_ssl_err = aiohttp.ClientSSLError(conn_key, OSError("handshake failed"))
with (
mock.patch.object(
bindings,
"http_client",
new=mock.AsyncMock(get=mock.AsyncMock(side_effect=client_ssl_err)),
),
pytest.raises(RuntimeError) as exc_info,
):
await bindings._get_valid_scopes()
assert "certificate" in str(exc_info.value).lower()To resolve this, import aiohttp in bindings.py and catch both:
import aiohttp
...
except (ssl.SSLError, aiohttp.ClientSSLError) as e:
raise RuntimeError(_CERTIFICATE_ERROR_MESSAGE) from eMinor note on the error message text in bindings.py:38-40:
"See the 'Additionally, for the secops-soar MCP server...' note in README.md / docs/usage_guide.md" only appears verbatim in docs/usage_guide.md (in README.md it is under ## Troubleshooting). Suggest tweaking the string:
See the 'Troubleshooting' section in README.md or setup notes in docs/usage_guide.md for setup steps.
Once bindings.py catches aiohttp.ClientSSLError, all unit tests pass cleanly and this is ready to merge.
|
Fixed — bindings.py now catches (ssl.SSLError, aiohttp.ClientSSLError) |
dandye
left a comment
There was a problem hiding this comment.
LGTM! Thank you @Som0111 for quickly addressing the review comments, updating the exception handling in bindings.py to catch aiohttp.ClientSSLError, and updating the test copyright headers. Verified locally that all 5 unit tests pass hermetically and CI checks are green.
|
Merged! Thanks again @Som0111 for the contribution and the quick turnaround on the review feedback. |
|
Thank you for the thorough review and guidance, @dandye ! |
Fixes #191
Problem
When the secops-soar MCP server fails due to an SSL/certifi certificate
issue, it shows a misleading message blaming SOAR credentials instead of
the real cause.
Changes
http_client.py— re-raises ssl.SSLError instead of swallowing itbindings.py— catches ssl.SSLError around scope fetch and raises adistinct RuntimeError explaining the certifi fix
server/secops-soar/README.md— added Troubleshooting section withcertifi setup instructions for macOS/Linux/Windows
tests/unit/— tests covering SSL error re-raising vs credential errorsBefore
"Failed to fetch valid scopes from SOAR, please make sure you have
configured the right SOAR credentials."
After
Distinct error explaining it's a local CA/certifi issue with fix instructions.
docs/usage_guide.md untouched.
AI Assistance
Used Claude Code to implement the fix. Reviewed full diff and take
responsibility for the submitted work.