【问题标题】:pip: cert failed, but curl workspip:证书失败,但 curl 有效
【发布时间】:2013-10-23 00:15:37
【问题描述】:

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

但是如果我们尝试使用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>

证书在客户端。见:

(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; emailAddress=info@foo-com.de
*    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; emailAddress=info@foo-com.de
*    SSL certificate verify ok.
> GET /pypi/simple/pep8/ HTTP/1.1

版本:pip 1.4.1

【问题讨论】:

    标签: python curl ssl pip


    【解决方案1】:

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

    我找到了解决办法:

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

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

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

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

    【讨论】:

    • +1 --cert 参数对我不起作用,但配置文件解决方案起作用(OS X,anaconda 安装)
    【解决方案2】:

    我的解决方案是从http://curl.haxx.se/ca/cacert.pem 下载cacert.pem 并按照 guettli 的建议将 cacert.pem 的路径添加到 ~/.pip/pip.conf

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

    【讨论】:

    • 我把它放在 /etc/pip.conf 中(证书是 /etc/ssl/certs/DigiCert_High_Assurance_EV_Root_CA.pem),它现在适用于所有用户
    【解决方案3】:

    对我来说,配置文件的解决方法都不起作用。我在 Ubuntu 14.04

    上使用 pip 1.5.4

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

    更新

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

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

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

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

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

    较旧的解决方法

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

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

    【讨论】:

      【解决方案4】:

      我用:

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

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

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

      1. 查看不同 Linux 发行版的默认位置列表 (在我的例子中,这个文件已经过时了,因为我是在一个非常老的 linux 发行版上构建的
      2. 如果可用,从 pip.conf 文件、环境或命令行(按此顺序)中的值覆盖 (1) 中找到的值,
      3. 如果 (1) 和 (2) 均未生成值,请使用捆绑文件

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

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

      【讨论】:

      • 为什么需要pip install pep8 行?
      • 这只是一个例子,我是从其他答案中拿来的
      • 哦,抱歉,星期五来晚了。周末时间:-)