如何将自定义 CA Root 证书添加到 Windows 中 pip 使用的 CA Store?

新手上路,请多包涵

我刚刚从 python.org 安装了 Python3,但在使用 pip 安装软件包时遇到了问题。按照设计,这里的网络上有一个中间人数据包检测设备,它通过使用自己的证书重新签署所有 ssl 连接来检查所有数据包(包括 ssl)。 GPO 的一部分将自定义根证书推送到 Windows 密钥库中。

使用 Java 时,如果我需要访问任何外部 https 站点,我需要手动更新 JVM 中的 cacerts 以信任自签名 CA 证书。

我如何为 python 完成它?现在,当我尝试使用 pip 安装软件包时,可以理解,我得到了美妙的 [SSL: CERTIFICATE_VERIFY_FAILED] 错误。

我意识到我可以使用 --trusted-host 参数忽略它们,但我不想对我尝试安装的每个包都这样做。

有没有办法更新 python 使用的 CA 证书存储?

原文由 Eric B. 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
1 个回答

自签名证书颁发机构 pip / conda

在广泛记录了 Git 的类似问题( 如何让 git 接受自签名证书? )之后,我们再次处于公司防火墙的后面,代理给我们提供了我们应该信任的 MitM“攻击” ,并且:

切勿禁用所有 SSL 验证!

这会造成不良的安全文化。不要成为那个人。

更新 2022 Python 3.10

可以实验使用系统 truststorehttps://pip.pypa.io/en/latest/user_guide/#using-system-trust-stores-for-verifying-https

 # Requires Python 3.10 or later
python --version
Python 3.10.4

# Install the 'truststore' package from PyPI
python -m pip install truststore

# Use '--use-feature=truststore' flag to enable
python -m pip install SomePackage --use-feature=truststore

tl;dr:配置您自己的信任库 CA 捆绑包

pip config set global.cert path/to/ca-bundle.crt
pip config list
conda config --set ssl_verify path/to/ca-bundle.crt
conda config --show ssl_verify

# Bonus while we are here...
git config --global http.sslVerify true
git config --global http.sslCAInfo path/to/ca-bundle.crt

但是我们从哪里得到 ca-bundle.crt


获取最新的 CA Bundle

cURL 发布了与 Mozilla Firefox 捆绑在一起的证书颁发机构的摘录

https://curl.haxx.se/docs/caextract.html

我建议您在文本编辑器中打开这个 cacert.pem 文件,因为我们需要将我们的自签名 CA 添加到该文件中。

证书是符合 X.509 的文档,但它们可以通过几种方式编码到磁盘。下面的文章很好读,但简短的版本是我们正在处理 base64 编码,在文件扩展名中通常称为 PEM。您会看到它具有以下格式:

 ----BEGIN CERTIFICATE----
....
base64 encoded binary data
....
----END CERTIFICATE----

https://support.ssl.com/Knowledgebase/Article/View/19/0/der-vs-crt-vs-cer-vs-pem-certificates-and-how-to-convert-them


获取我们的自签名证书

以下是有关如何获取我们的自签名证书的几个选项:

  • 通过 OpenSSL CLI
  • 通过浏览器
  • 通过 Python 脚本

通过 OpenSSL CLI 获取我们的自签名证书

https://unix.stackexchange.com/questions/451207/how-to-trust-self-signed-certificate-in-curl-command-line/468360#468360

 echo quit | openssl s_client -showcerts -servername "curl.haxx.se" -connect curl.haxx.se:443 > cacert.pem

通过浏览器获取我们的自签名证书颁发机构

感谢这个答案和链接的博客,它显示了(在 Windows 上)如何查看证书然后使用 base64 PEM 编码选项复制到文件的步骤。

复制此导出文件的内容并将其粘贴到 cacerts.pem 文件的末尾。

为了保持一致性重命名此文件 cacerts.pem –> ca-bundle.crt 并将其放在容易的地方,例如:

 # Windows
%USERPROFILE%\certs\ca-bundle.crt

# Linux/macOS
$HOME/certs/cabundle.crt

通过 Python 获取我们的自签名证书颁发机构

感谢所有出色的答案:

如何从 python 中的请求中获取响应 SSL 证书?

我整理了以下内容以尝试更进一步。

https://github.com/neozenith/get-ca-py


最后

在 pip 和 conda 中设置配置,以便它知道这个 CA 存储所在的位置以及我们额外的自签名 CA。

 # Windows
pip config set global.cert %USERPROFILE%\certs\ca-bundle.crt
conda config --set ssl_verify %USERPROFILE%\certs\ca-bundle.crt

要么

# Linux / macOS
pip config set global.cert $HOME/certs/ca-bundle.crt
conda config --set ssl_verify $HOME/certs/ca-bundle.crt

然后

pip config list
conda config --show ssl_verify

# Hot tip: use -v to show where your pip config file is...
pip config list -v
# Example output for macOS and homebrew installed python
For variant 'global', will try loading '/Library/Application Support/pip/pip.conf'
For variant 'user', will try loading '/Users/jpeak/.pip/pip.conf'
For variant 'user', will try loading '/Users/jpeak/.config/pip/pip.conf'
For variant 'site', will try loading '/usr/local/Cellar/python/3.7.4/Frameworks/Python.framework/Versions/3.7/pip.conf'

故障排除

基于下面的一个很好的评论

我已经试过了,但仍然出现 SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)')) 错误。有什么建议么?

这是故障排除指南:

当证书颁发机构尚未正确设置时,这是正常的错误消息。

可能需要检查多种因素:

  • 你的 ca-bundle.crt 的路径有适合你的操作系统的正确路径分隔符(这让我很生气),
  • 您可能没有最新的 CA 来验证普通证书,
  • 您可能没有以正确的编码添加您的 CA。

Python 有效地执行了这 3 个步骤:

  • 找到我的 CA 商店,
  • 阅读所有条目,
  • 根据我的信任库查找此证书。

如果其中任何一个失败,您将根据经验收到此错误消息。

检查 从下面链接的这个答案 以显示和检查您的 ssl_cert_dir 使用:

 python -c "import ssl; print(ssl.get_default_verify_paths())"

参考

原文由 Josh Peak 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题