ssl Python请求-如何使用系统ca证书(debian/ubuntu)?

rqmkfv5c  于 2023-02-09  发布在  Python
关注(0)|答案(5)|浏览(196)

我已经在debian的/usr/share/ca-certificates/local中安装了一个自签名的根ca证书,并且和sudo dpkg-reconfigure ca-certificates一起安装了它们,此时true | gnutls-cli mysite.local很满意,true | openssl s_client -connect mysite.local:443也很满意,但是python 2和python3请求模块坚持它对证书不满意。
Python2:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/adapters.py", line 497, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)

Python3

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/bin/python3.5/site-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/adapters.py", line 497, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)

为什么python忽略系统ca-certificates包,我该如何集成它?

iyr7buue

iyr7buue1#

https://stackoverflow.com/a/33717517/1695680开始
要使python请求使用system ca-certificates包,需要告知它在自己的嵌入包上使用它

export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt

Requests在此嵌入了它的包,以供参考:

/usr/local/lib/python2.7/site-packages/requests/cacert.pem
/usr/lib/python3/dist-packages/requests/cacert.pem

或在较新版本中使用附加软件包从以下位置获取证书:https://github.com/certifi/python-certifi
要验证从哪个文件加载证书,您可以尝试:

Python 3.8.5 (default, Jul 28 2020, 12:59:40) 
>>> import certifi
>>> certifi.where()
'/etc/ssl/certs/ca-certificates.crt'
1hdlvixo

1hdlvixo2#

最近一周左右,我一直在纠结这个问题,最后终于找到了在Python中验证自签名或私人签名证书的方法,你需要创建自己的证书包文件,不需要在每次更新库或向系统证书库添加任何内容时都更新晦涩难懂的证书包。
首先运行openssl命令,你之前运行过,但添加-showcerts. openssl s_client -connect mysite.local:443 -showcerts这将给予你一个很长的输出,在顶部你会看到整个证书链,通常,这意味着三个证书,网站的证书,中间证书,根证书的顺序,我们只需要把根证书和中间证书放入下一个文件中,顺序相反.
复制最后一个证书,根证书,到一个新的文本文件中。只抓取中间的内容,包括:

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

将中间证书复制到根证书下的新文本文件中,再次获取开始和End Certificate行以及中间的所有内容。
将这个文本文件保存到Python脚本所在的目录中,我建议将其命名为CertBundle.pem(如果您给予它一个不同的名称,或者将其放在文件夹结构中的其他位置,请确保验证行反映了这一点)。更新脚本以引用新的证书包:

response = requests.post("https://www.example.com/", headers=headerContents, json=bodyContents, verify="CertBundle.pem")

就是这样,如果你只有根证书或者只有中间证书,那么Python就不能验证整个证书链,但是,如果你在创建的证书包中包含了这两个证书,那么Python就可以验证中间证书是由根证书签署的,然后当它访问网站时,它就可以验证网站的证书是由中间证书签署的。
修改了证书包的文件扩展名。2同时,修改了一些语法错误。

x9ybnkn6

x9ybnkn63#

我的意见是:
多亏了另一个答案,让我检查了实际的请求代码,我发现您不必使用env变量,而只需在请求中设置"verify"参数即可:

requests.get("https://whatever", verify="/my/path/to/cacert.crt", ...)

它也有文档,尽管我只能在发现之后才能找到文档(pypi项目指向doc的死链接):D

z0qdvdin

z0qdvdin4#

requests使用certifi作为默认的根证书包,它内置了很多好的CA,但无法修改。
Debian(和Ubuntu)的维护者修改了certifi的行为,使其不同于默认值:

def where():
    return "/etc/ssl/certs/ca-certificates.crt"

因此,如果您使用apt安装的requestscertifi,则没有问题。
但是pip3在虚拟环境中安装的证书使用内置CA。因此无法使用update-ca-certificates机制。除了在应用代码中手动指定根证书(如果通过第三方接口间接调用request,则可能无法手动指定根证书),它还可以使用环境变量REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt进行覆盖,以模拟Debianized行为。

kmynzznz

kmynzznz5#

在尝试了所有的方法之后,我发现这个方法在Ubuntu上很有效

export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt

即使certifi显示了相同的路径,我也不得不这样做。

相关问题