使用虚拟环境时的证书验证

Certificate verification when using virtual environments

我的机器上安装了根 CA 证书,在使用请求库的系统安装时发出请求时一切正常:

$ python -c 'import requests; print requests.get("https://example.com")'
<Response [200]>

但是,如果我从虚拟环境中发出相同的请求,证书验证将失败:

$ python -c 'import requests; print requests.get("https://example.com")'
requests.exceptions.SSLError: [Errno 1] _ssl.c:510: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

使用 requests.certs.where 我可以看到系统安装使用系统 CA 包,虚拟环境使用随请求一起提供的 CA 包:

$ python -c "import requests; print requests.certs.where()"
/etc/ssl/certs/ca-certificates.crt

$ (venv) python -c "import requests; print requests.certs.where()"                                                            
.../venv/local/lib/python2.7/site-packages/requests/cacert.pem

在使用 virtualenv 时,是否有另一种获取系统证书而不提供每个请求路径的解决方案,即:

>>> requests.get("https://example.com" verify="/etc/ssl/certs/ca-certificates.crt")

系统包已通过系统包管理器安装并进行了修改,因此 requests.certs.where 返回了系统 CA 包 /etc/ssl/certs/ca-certificates.crt。在虚拟环境中 requests 是通过 pip 安装的,因此使用捆绑的 cacert.pem.

正在查看 requests.certs pointed me at python-certifi 的来源。我用来解决我的问题的解决方案是创建一个 python-certifi 样式的包,其中包含我需要的站点的根证书。

from my_certifi import where
requests.get("https://example.com" verify=where())

现在,对 https://example.com 的任何请求都将得到验证,而无需任何依赖于系统的修改或配置。

如果你想将特定的 CA 证书插入到你的 virtualenv 的 CA 包中,你可以附加到它:

openssl x509 -in $specific_ca.crt -text >> $virtualenv/lib/python2.7/site-packages/certifi/cacert.pem