首页 > 解决方案 > Python 使用内部 CA 请求 SSLError

问题描述

我的公司为内部服务运营自己的内部 CA,我需要访问连接 Ansible AWX [python] 以与我们使用由该 CA 签名的证书的内部服务之一进行通信。基本上:

  1. AWX 启动了一个安装在其中的容器awx_task/etc/pki/ca-trust/source/anchors其中包含根 CA 证书。[双重检查]
  2. update-ca-trust运行,将 CA 证书捆绑到各种东西中,包括/etc/pki/tls/certs/ca-bundle.crt. [双重检查]
  3. requests 应该使用这个捆绑包。我无法在容器内或主机上找到与 CA 相关的环境变量来覆盖它。

但是,当我触发在其中运行的 Ansible 游戏的测试运行时,awx_task我得到了错误:

requests.exceptions.SSLError: HTTPSConnectionPool(host='vault.example.com', port=443): 最大重试次数超出了 url: / (由 SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败) _ssl.c:618)'),))

在主机上我可以运行

import requests
requests.get("https://vault.example.com")

并得到200回应,如果strace我可以看到它正在阅读的过程/etc/pki/tls/certs/ca-bundle.crt。但从里面awx_task我得到的requests.exceptions.SSLError和上面一样。不幸的是,Docker 不允许我在容器内运行 strace,所以我看不到它试图读取的内容。

但是,如果我将代码修改为:

import requests
requests.get("https://vault.example.com", verify="/etc/pki/tls/certs/ca-bundle.crt")

200我从容器内部得到响应。

我在这里想念什么?

标签: pythonsslansible

解决方案


问题是@Will 指出的,当前版本的 Requests 使用完全独立于 OpenSSL 的 Certifi 包。捆绑包 PEM 实际上位于 Python 站点包目录中的某个位置。

在不修改代码的情况下,您可以使用环境变量覆盖它:

REQUESTS_CA_BUNDLE=/etc/pki/tls/certs/ca-bundle.crt

社论:这是强制执行 CA 信任的绝对荒谬的方式。如果您想减少系统信任,请在系统级别减少它。我真的厌倦了追逐分散在源代码树中的随机 PEM 包 [可能永远不会更新] 只是因为一些#devoops nutbag 认为他知道如何比实际操作更好地运行系统,并将他们的坏主意分流给毫无戒心的系统。

(ノಠ益ಠ)ノ彡┻━┻</p>


推荐阅读