在两个基本相同的系统(都运行Fedora 25,都安装了相似的软件包版本)的情况下,一个系统发生SSL证书验证错误,而另一个系统则没有。也就是说,如果我运行:
import requests
r = requests.get('https://insidehost.corp.example.com')
一个系统可以运行,而另一个系统则可以失败:
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)
起初,我发现我只是缺少必要的CA证书,但是在
strace
下运行python时发现,在发生故障的系统上,python从未尝试打开ca bundle。也就是说,在有效的系统上:strace -e trace=open,stat python testscript.py |& grep /etc/pki
仅产量:
open("/etc/pki/tls/legacy-settings", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/etc/pki/tls/certs/ca-bundle.crt", {st_mode=S_IFREG|0444, st_size=257079, ...}) = 0
open("/etc/pki/tls/certs/ca-bundle.crt", O_RDONLY) = 4
但是在出现故障的系统上会产生:
open("/etc/pki/tls/legacy-settings", O_RDONLY) = -1 ENOENT (No such file or directory)
此外,在出现故障的系统上使用
python3
运行相同的测试脚本...行得通!在这两种情况下,
python
是/usr/bin/python
中的python-2.7.13-1.fc25.x86_64
。两个系统都未设置任何*_CA_BUNDLE
环境变量。 最佳答案
经过一些额外的调查,我发现了这一点,并且我想将解决方案发布在这里,因为它不一定很明显。requests
模块包括其自己的证书捆绑包,如果找不到另一个证书捆绑包,它将依赖于此。查找证书捆绑包的方式是这样的,位于request / certs.py中:
try:
from certifi import where
except ImportError:
def where():
"""Return the preferred certificate bundle."""
# vendored bundle inside Requests
return os.path.join(os.path.dirname(__file__), 'cacert.pem')
您可以通过运行以下命令查看结果:
$ python -m requests.certs
/etc/pki/tls/certs/ca-bundle.crt
从上面的代码中可以看到,
requests
使用certifi
模块来找到适当的包。在发生故障的系统上,certifi
模块是通过pip
安装的,而不是使用系统软件包安装的,这意味着它缺少适当的配置。解决方案是
yum install python2-certifi
。关于python - Python抛出SSL证书验证错误而没有咨询系统CA捆绑包吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43284821/