Python 使用内部 CA 请求 SSLError

Sam*_*tch 5 python ssl ansible

我的公司为内部服务运营着自己的内部 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): Max retries exceeded with url: / (Caused by SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed ( _ssl.c:618)'),))

在主机上我可以运行

import requests
requests.get("https://vault.example.com")
Run Code Online (Sandbox Code Playgroud)

并得到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")
Run Code Online (Sandbox Code Playgroud)

200从容器内部得到响应。

我在这里缺少什么?

Sam*_*tch 2

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

\n\n

无需修改代码,您可以使用环境变量覆盖它:

\n\n
REQUESTS_CA_BUNDLE=/etc/pki/tls/certs/ca-bundle.crt\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

(\xe3\x83\x8e\xe0\xb2\xa0\xe7\x9b\x8a\xe0\xb2\xa0)\xe3\x83\x8e\xe5\xbd\xa1\xe2\x94\xbb\xe2\x94\x81 \xe2\x94\xbb

\n