如何在 Windows 中的 pip 使用的 CA 存储区中添加自定义 CA 根证书?

我刚刚从 python.org 上安装了 Python 3,在用 pip安装软件包时遇到了麻烦。根据设计,这里的网络上有一个中间人(man-in-the-Middle)数据包检查设备,它通过使用自己的证书重新签署所有 ssl 连接来检查所有数据包(包括 ssl)。GPO 的一部分将自定义根证书推送到 Windows Keystore。

在使用 Java 时,如果需要访问任何外部 https 站点,则需要手动更新 JVM 中的 ccerts 以信任 Self-Signed CA 证书。

我如何为 python 实现这一点?现在,当我尝试使用 pip安装软件包时,可以理解的是,我得到了很棒的 [SSL: CERTIFICATE_VERIFY_FAILED]错误。

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

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

244418 次浏览

运行: python -c "import ssl; print(ssl.get_default_verify_paths())"检查用于验证证书的当前路径。把你公司的根证书加进去。

路径 abc0指向环境变量: SSL_CERT_DIR

如果 SSL_CERT_DIR不存在,则需要创建它并将其指向文件系统中的有效文件夹。然后,可以将证书添加到此文件夹以使用它。

这不是最佳答案,但是您可以使用 pip--cert选项重用已经创建的 ca bundle,例如:

pip install SQLAlchemy==1.1.15 --cert="C:\Users\myUser\certificates\my_ca-bundle.crt"

在 Windows 上,我通过在% APPDATA% pip 中创建 pip.ini 文件来解决这个问题

例如 C: 用户使用 AppData 漫游 pip.ini

在 pip.ini 中,我将证书的路径放在:

[global]
cert=C:\Users\asmith\SSL\teco-ca.crt

Https://pip.pypa.io/en/stable/user_guide/#configuration 有更多关于配置文件的信息。

自签名证书颁发机构 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

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 发布与 MozillaFirefox 绑定的证书颁发机构的摘录

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

通过浏览器获得自签名证书授权

由于这个答案和链接的 blog,它显示了(在 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 有效地完成了以下三个步骤:

  • 找到我的 CA 商店,
  • 阅读所有条目,
  • 查一下我信托商店的这张证书。

如果其中任何一个失败,您将从经验中得到这个错误消息。

检查 这个答案从下面链接起来来显示和检查你的 ssl_cert_dir使用:

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

参考文献

打开水蟒导航器。

转到文件首选项。

启用 SSL 验证禁用(不推荐)

或启用并指示 SSL 证书路径(可选)

将软件包更新为特定版本:

选择右上角安装

选择软件包,点击打勾

标记更新

标记特定版本的安装

点击应用

Windows 上的另一种解决方案是安装 Python-Certificate-win32,这将允许 Python 使用 Windows 证书存储。

pip install python-certifi-win32

我认为 nt86的解决方案是最合适的,因为它利用了底层的 Windows 基础设施(证书存储)。 但是它没有解释如何从安装 python-證 i-win32开始,因为 pip 是非功能性的。

诀窍是使用 --trustedhost安装 python-certificate-win32,然后 pip 将自动使用 Windows 证书存储来加载代理使用的证书。

简而言之,你应该这样做:

pip install python-certifi-win32 -trustedhost pypi.org

然后你就可以走了

在我的场景中,在使用 python 3.8的 Ubuntu 上,我想看看我可以在我的本地系统中改变什么(而不是编码或者安装一个新的软件包) ,这将允许我使用我的自定义 CA 和我的自签名证书。

所以我追踪了巨蟒的目的地:

strace python my_prog 2> out.txt

然后对 pem 的输出进行 grep (您可能需要查找“ crt”“ cert”)

grep -i pem out.txt

尽管凭证从未被显式安装过,但它正在寻找的文件是:

/path/to/virtualenv/for/project/lib/python3.8/site-packages/certifi/cacert.pem

因此,我重命名了旧文件,并将其链接到系统的 ca 包(例如,/etc/ssl/certs/ca-securities. crt)

现在成功了。