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

Posted

技术标签:

【中文标题】如何将自定义 CA Root 证书添加到 Windows 中 pip 使用的 CA Store?【英文标题】:How to add a custom CA Root certificate to the CA Store used by pip in Windows? 【发布时间】:2017-01-14 08:21:54 【问题描述】:

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

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

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

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

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

【问题讨论】:

@rfkortekaas 所有这些选项都涉及在流程中添加新内容。 Python 必须使用存储在系统某处的默认信任库。我想修改那个信任库。我不想添加额外的变量、不同的 ca 存储等。在 java 中,jvm 依赖于自己的信任存储(与操作系统分开)。我怀疑 python 一定在做类似的事情,因为我的根证书在我的 Windows 商店中并且不被 python 识别。 @eric_b 你应该接受答案。 【参考方案1】:

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

在用 Git (How can I make git accept a self signed certificate?) 大量记录类似问题后,我们再次位于公司防火墙后面,该代理提供了我们应该信任的MitM“攻击”,并且: p>

切勿禁用所有 SSL 验证!

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

tl;博士

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 捆绑包

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

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

Direct Download SHA256

我建议您在文本编辑器中打开此 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

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

获取您的 CA:https://***.com/a/50486128/622276 http://blog.majcica.com/2016/12/27/installing-self-signed-certificates-into-git-cert-store/

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

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

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

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

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

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

感谢所有精彩的答案:

How to get response SSL certificate from requests in python?

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

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 商店, 阅读所有条目, 在我的信任库中查找此证书。

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

检查this answer linked from below 以显示并检查您的ssl_cert_dir 使用:

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

参考文献

点 SSL:https://pip.pypa.io/en/stable/user_guide/#configuration 康达 SSL:https://***.com/a/35804869/622276 获取您的 CA:https://***.com/a/50486128/622276 http://blog.majcica.com/2016/12/27/installing-self-signed-certificates-into-git-cert-store/ 使用 Python 自动获取您的 Peer CA:How to get response SSL certificate from requests in python?

【讨论】:

有史以来最伟大的答案之一 @DanielArgüelles 是的,没错。大多数情况下,您可以不合并证书颁发机构捆绑包,但我已经有足够的时间需要完整的捆绑包,以便 pip 或 conda 可以验证其他服务器的证书。最终,一个包仍然是一个包含大量 pem 文件内容的文本文件。很高兴它有效,您不需要禁用验证! :D 恶魔伴侣 太棒了!必须将代理所需的自签名证书和 pypi.org 包存储站点证书组合到 ONE 证书文件中是我几天来一直试图找到的解决方案! @beneM 是的,我尝试了多个文件,看起来它应该可以识别一个 CA 文件夹,但是将它们全部附加到一个文件中是唯一对我有用的文件。【参考方案2】:

我认为 nt86 的解决方案是最合适的,因为它利用了底层的 Windows 基础架构(证书存储)。 但它没有解释如何安装 python-certifi-win32 开始,因为 pip 不起作用。

诀窍是使用--trustedhost安装python-certifi-win32,然后pip会自动使用windows证书存储加载代理使用的证书。

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

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

然后你应该好好去

【讨论】:

【参考方案3】:

Windows 上的替代解决方案是安装 python-certifi-win32,这将允许 Python 使用 Windows 证书存储。

pip install python-certifi-win32

【讨论】:

第一次想做pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org python-certifi-win32 简单,但拯救了我的一天!【参考方案4】:

打开 Anaconda 导航器。

转到文件\首选项。

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

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

将包更新到特定版本:

选择右上角安装

选择包点击打勾

标记为更新

标记为特定版本安装

点击应用

【讨论】:

【参考方案5】:

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

例如C:\Users\asmith\AppData\Roaming\pip\pip.ini

在 pip.ini 中,我输入了证书的路径:

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

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

【讨论】:

嗨,Alex,您是如何将证书的路径“放入”到 pip.ini 文件中的?从命令行?您是否将文件路径输入到记事本之类的东西中并将其保存为文本文件?我用的是anaconda提示,不过我觉得跟windows差不多。 我用记事本创建了一个文本文件,然后将文件扩展名从“txt”更改为“ini”。 啊。好的。您是否还必须在路径上方输入“[gobal]”?你知道我在哪里可以找到这种类型的教程吗?谢谢。 是的,您也需要输入“[global]”。抱歉,我不知道任何教程,但pip.pypa.io/en/stable/user_guide/#configuration 有更多信息。 谢谢,两种方法我都试过了,是的,“[global]”没有坏处。【参考方案6】:

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

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

【讨论】:

【参考方案7】:

运行:python -c "import ssl; print(ssl.get_default_verify_paths())" 检查用于验证证书的当前路径。将贵公司的根证书添加到其中之一。

路径openssl_capath_env指向环境变量:SSL_CERT_DIR

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

【讨论】:

在我的 Windows 系统上,这将返回 '/usr/local/ssl/certs',这在 Windows 上不可用。 在被拉到另一个项目之后,我终于也开始这样做了,类似于@ColinTalbert,它指向一个不存在的文件夹/usr/local/ssl/certs 我已经编辑了我的问题,希望这能解决这个问题。 @rfkortekaas 更新 SSL_CERT_FILE 或 SSL_CERT_DIR 变量不起作用。我刚刚为这个问题创建了一个new SO question,因为它可能不仅仅是如何更新 PEM 文件的问题,而是如何让 python 访问 cygwin/Windows 中的正确路径。 我试过了。我最终在~/.config/pip/pip.conf 中创建了一个带有必要设置的 pip.conf 文件。 See this answer.

以上是关于如何将自定义 CA Root 证书添加到 Windows 中 pip 使用的 CA Store?的主要内容,如果未能解决你的问题,请参考以下文章

如何生成CA证书

C# 如何验证 Root-CA-Cert 证书 (x509) 链?

C#如何验证Root-CA-Cert证书(x509)链?

ROOT CA 如何验证签名?

如何强制旧版 debian 忘记 DST Root CA X3 Expiration 并使用 ISRG Root X1 - SSL 证书问题:证书已过期

将自签名证书链添加到密钥库