Skip to content

fix(backend): default SSL_CERT_FILE to certifi on macOS/Windows - #2289

Open
liujianyeey-oss wants to merge 1 commit into
TencentCloud:developfrom
liujianyeey-oss:fix/macos-tls-cert-file
Open

liujianyeey-oss wants to merge 1 commit into
TencentCloud:developfrom
liujianyeey-oss:fix/macos-tls-cert-file

Conversation

@liujianyeey-oss

Copy link
Copy Markdown

问题

macOS 上启动 Octop 后,模型 API 连接测试失败,界面提示「连接模型服务超时或网络异常」,底层错误为 OpenAIConnectionError('Connection error.'),TLS 握手返回 OSStatus -26276(errSSLBadCert)。curl、openssl s_client、标准 httpx(certifi 后端)访问同一地址均正常,只有 Octop 失败。

根因

OpenAI SDK 的 HTTP 传输层 httpcore2 在创建 SSL context 时,macOS / Windows 上使用 truststore(系统钥匙串)替代 certifi 做证书链验证(httpcore2/_ssl.py):

if platform.system() in ("Windows", "Darwin"):
    return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

macOS 钥匙串对部分合法的证书链验证失败——实测 api.kimi.com(DigiCert Global Root G2 → RapidSSL TLS RSA CA G1 → *.kimi.com,服务器完整下发三张证书)在 openssl 和 certifi 下均验证通过,经 Security framework 验证却返回 errSSLBadCert。于是 macOS 上 Octop 对该 API 的全部 HTTPS 调用都会失败。

httpcore2 自身留有逃生通道:设置了 SSL_CERT_FILE 环境变量后会跳过 truststore 分支,走标准 ssl.create_default_context(cafile=...)。

修复

在 OctopServer.start() 启动早期(apply_env_file 之后)新增 ensure_ssl_cert_file():仅在 macOS / Windows 且用户未自设 SSL_CERT_FILE 时,将其默认指向 certifi 的 CA 证书包。octop run 与 CLI 内嵌服务(如 octop provider test)都经过 OctopServer.start(),一处生效全覆盖;用户显式配置始终优先。

验证

  • 新增回归测试 tests/unit/infra/utils/test_ssl_cert_file.py:覆盖 macOS/Windows 默认设置、用户已设置时保留、Linux 不设置、无 certifi 时静默跳过 5 个场景
  • 本机(macOS)实测:修复前 POST /api/admin/providers/1/test 报连接错误;修复后返回 {"ok": true, "latency_ms": 1783}

(截图:修复前连接测试失败弹窗 / 修复后测试通过,见评论区)

PR Checklist

  • 📸 UI 截图/功能演示已提供(见评论区前后对比)
  • 🧪 测试用例已添加并通过(新增 5 个单测)
  • ✅ CI Workflow 全部通过
  • 🤖 已与 AI 对齐需求理解
  • 🎯 遵循最小修改原则,代码结构清晰(1 个新工具函数 + 1 处启动接线 + 测试 + CHANGELOG)
  • 📝 已询问并处理代码优化建议

httpcore2 (the OpenAI SDK's HTTP transport) builds its TLS context via
truststore on Darwin/Windows, so certificate chains are verified against
the OS keychain instead of certifi. The keychain rejects some valid
chains (e.g. api.kimi.com via RapidSSL) with errSSLBadCert, breaking all
model API calls on affected machines.

httpcore2 honors SSL_CERT_FILE with ssl.create_default_context() instead,
so default it to certifi's CA bundle at server startup. A user-provided
SSL_CERT_FILE always wins.
@liujianyeey-oss

Copy link
Copy Markdown
Author
octop-pr-before octop-pr-after

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant