Python pip:证书失败,但 curl 有效

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19377045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 13:36:14  来源:igfitidea点击:

pip: cert failed, but curl works

pythoncurlsslpip

提问by guettli

We installed the our root cert on the client, and the https connection works for curl.

我们在客户端安装了我们的根证书,并且 https 连接适用于curl.

But if we try to use pip, it fails:

但是如果我们尝试使用pip,它会失败:

Could not fetch URL https://installserver:40443/pypi/simple/pep8/:
There was a problem confirming the ssl certificate: 
<urlopen error [Errno 1] _ssl.c:499: error:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed>

The cert is on the client. See:

证书在客户端。看:

(foo_fm_qti)foo_fm_qti@vis-work:~$ curl -v https://installserver:40443/pypi/simple/pep8/
* About to connect() to installserver port 40443 (#0)
*   Trying 127.0.0.1... connected
* Connected to installserver (127.0.0.1) port 40443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs/
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS alert, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using DHE-RSA-AES256-SHA
* Server certificate:
*    subject: C=DE; ST=Sachsen; L=Chemnitz; O=FOO-COM GmbH; OU=DV; CN=gray.foo-com.lan; [email protected]
*    start date: 2013-09-09 10:47:50 GMT
*    expire date: 2019-05-24 10:47:50 GMT
*    subjectAltName: installserver matched
*    issuer: C=DE; ST=Sachsen; L=Chemnitz; O=FOO-COM GmbH; CN=FOO-COM Root CA; [email protected]
*    SSL certificate verify ok.
> GET /pypi/simple/pep8/ HTTP/1.1

Version: pip 1.4.1

版本:pip 1.4.1

采纳答案by guettli

Unfortunately pip does not use the system certs, but curl does.

不幸的是 pip 不使用系统证书,但 curl 使用。

I found a solution:

我找到了一个解决方案:

pip --cert /etc/ssl/certs/FOO_Root_CA.pem install pep8

This is not nice (curl and other libraries find the cert without adding a parameter) but works.

这不好(curl 和其他库在不添加参数的情况下找到证书)但有效。

If you don't want to use the command line argument, you can set the cert in ~/.pip/pip.conf:

如果不想使用命令行参数,可以在 ~/.pip/pip.conf 中设置证书:

[global]
cert = /etc/ssl/certs/Foo_Root_CA.pem

回答by user2200896

My solution is downloading cacert.pemfrom http://curl.haxx.se/ca/cacert.pemand add the path for cacert.pemto ~/.pip/pip.confas guettli suggested

我的解决办法是下载cacert.pemhttp://curl.haxx.se/ca/cacert.pem和路径添加cacert.pem~/.pip/pip.conf为guettli建议

[global]
cert = /path/to/cacert.pem

回答by arjenve

I use:

我用:

export PIP_CERT=`python -m pip._vendor.requests.certs`

pip install pep8

PIP always validates the certificate of HTTPS connections (and all pypi packages redirect to HTTPS).

PIP 始终验证 HTTPS 连接的证书(并且所有 pypi 包都重定向到 HTTPS)。

The algorithm for determining the CA file is based on 3 steps:

确定 CA 文件的算法基于 3 个步骤:

  1. Look in a list of default locations for different linux distributions (in my case this file turned out to be out of date, as I am building on a very old linux distribution)
  2. If available, override the value found in (1) from a value in the pip.conf file, the environment or the command-line (in that order),
  3. If both (1) and (2) did not result in a value, use a bundled file
  1. 查看不同 linux 发行版的默认位置列表(在我的例子中,这个文件已经过时了,因为我是在一个非常旧的 linux 发行版上构建的
  2. 如果可用,从 pip.conf 文件、环境或命令行(按该顺序)中的值覆盖在 (1) 中找到的值,
  3. 如果 (1) 和 (2) 都没有产生值,请使用捆绑文件

Note that pip does not use the default SSL directories and files (from ssl.get_default_verify_paths()). But only supports a bundled CA file.

请注意,pip 不使用默认的 SSL 目录和文件(来自 ssl.get_default_verify_paths())。但只支持捆绑的 CA 文件。

PIP does support a command-line action to list the bundled file from step 3 and that is what I use for this answer.

PIP 确实支持命令行操作来列出步骤 3 中的捆绑文件,这就是我用于此答案的内容。

回答by andzep

For me, none of the config-file workarounds worked. I'm using pip 1.5.4on Ubuntu 14.04

对我来说,没有一个配置文件解决方法有效。我在Ubuntu 14.04上使用pip 1.5.4

The command posted by @arjenve didn't work on my system either. I get: /usr/bin/python: No module named _vendor.requests

@arjenve 发布的命令也不适用于我的系统。我得到:/usr/bin/python: No module named _vendor.requests

UPDATE

更新

An even better solution than my first workaround is installing the certificate on the system first (for me on ubuntu this would be)

比我的第一个解决方法更好的解决方案是首先在系统上安装证书(对我来说在 ubuntu 上是这样)

sudo cp ~/my_cert.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

The previous automatically updates the bundle file (checking at the bottom of /etc/ssl/certs/ca-certificates.crtyou should now see the same certificate as in my_cert.crt)

以前的自动更新捆绑文件(检查底部/etc/ssl/certs/ca-certificates.crt现在应该看到与 中相同的证书my_cert.crt

Now export that path into PIP_CERTand add it to your .bashrc:

现在将该路径导出PIP_CERT并添加到您的.bashrc

echo export PIP_CERT=/etc/ssl/certs/ca-certificates.crt >> ~/.bashrc


OLDER WORKAROUND

较旧的解决方法

My workaround was to create a bundle file from /etc/ssl/certs/ca-certificates.crtand my corporate's crt (just concatenated both files). And then export a variable (put that on my .bashrc) like this:

我的解决方法是从/etc/ssl/certs/ca-certificates.crt我公司的 crt创建一个包文件(只是连接两个文件)。然后.bashrc像这样导出一个变量(把它放在 my 上):

export PIP_CERT=/my/path/to/the/bundle.crt