【问题标题】:How to download server SSL certificate with urllib3?如何使用 urllib3 下载服务器 SSL 证书?
【发布时间】:2021-11-28 23:10:20
【问题描述】:

标题确实是个问题——在尝试建立 HTTPS 连接时,如何让urllib3 从远程服务器下载 SSL 证书?

背景 在 ServerVault 领域,我正试图了解a problem with AWS autoscaling groups 无法在其初始化过程中下载 phpMyAdmin 的问题。作为尝试诊断的一部分,我现在在 StackOverflow 领域,使用 python 脚本。我在这里:

#! /usr/bin/python3
import cfnbootstrap
from cfnbootstrap.packages import requests
from requests import utils
from requests.utils import DEFAULT_CA_BUNDLE_PATH
from requests.packages import urllib3

conn = urllib3.connection_from_url("https://dev.mysql.com/", retries=False)
conn.cert_reqs = 'CERT_REQUIRED'
conn.ca_certs = DEFAULT_CA_BUNDLE_PATH
response = conn.request("GET", "/get/")
conn.close()
print(response.status)

效果很好:

$ ./urltest.py 
404

但是,如果我将其更改为

conn = urllib3.connection_from_url("https://www.phpmyadmin.net", retries=False)
response = conn.request("GET", "/downloads/")

我遇到了我的问题:

$ ./urltest.py 
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/cfnbootstrap/packages/requests/packages/urllib3/connectionpool.py", line 544, in urlopen
    body=body, headers=headers)
  File "/usr/lib/python3.7/site-packages/cfnbootstrap/packages/requests/packages/urllib3/connectionpool.py", line 341, in _make_request
    self._validate_conn(conn)
  File "/usr/lib/python3.7/site-packages/cfnbootstrap/packages/requests/packages/urllib3/connectionpool.py", line 762, in _validate_conn
    conn.connect()
  File "/usr/lib/python3.7/site-packages/cfnbootstrap/packages/requests/packages/urllib3/connection.py", line 238, in connect
    ssl_version=resolved_ssl_version)
  File "/usr/lib/python3.7/site-packages/cfnbootstrap/packages/requests/packages/urllib3/util/ssl_.py", line 265, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/lib64/python3.7/ssl.py", line 423, in wrap_socket
    session=session
  File "/usr/lib64/python3.7/ssl.py", line 870, in _create
    self.do_handshake()
  File "/usr/lib64/python3.7/ssl.py", line 1139, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1091)

证书似乎不太可能过期,好像我用网络浏览器手动检查,一切都很好;但是,我想确切地了解urllib3 看到的证书已过期。我该怎么做?

NB:我没有直接打电话给certify.where(),因为我不确定 shananigans AWS 在后台执行什么操作,但是因为它们的脚本是作为启动的一部分自动安装的例如,我对此无能为力,所以我正在尝试使用他们的内部流程。

【问题讨论】:

  • 它在我的 Mac 上运行良好。在我的 linux 机器上测试它,我得到了和你一样的证书错误。
  • 嗯。我正要问你运行的是哪个内核和工具版本。为了将来参考,以防其他人想知道,我在 Linux 4.14.243-185.433.amzn2.x86_64 和 aws-cfn-bootstrap.noarch 2.0-6.amzn2
  • 我想这意味着,在 Linux 上下载证书的方式存在一些损坏问题,在这种情况下,我仍然需要回答这个问题;或者 Mac 与 Linux 上的 DEFAULT_CA_BUNDLE_PATH 存在一些差异(也许证书本身没问题,但在 Linux 版本而不是 Mac 版本上,链条上的某处已过期?)
  • 尝试:openssl s_client -showcerts -connect www.phpmyadmin.net:443 | grep "证书已过期"
  • 它说CONNECTED(00000003) depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1 verify return:1 depth=1 C = US, O = Let's Encrypt, CN = R3 验证返回:1 depth=0 CN = www.cdn77.com 验证返回:1

标签: python ssl amazon-cloudformation urllib3


【解决方案1】:

问题是 9 月 30 日发生的 Let's Encrypt DST Root CA X3 到期 -- https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021/。 requests 包不信任 ISRG Root X1 证书,并尝试使用过期证书对其进行验证。

https://letsencrypt.org/certificates/ 下载 ISRG X1 PEM 并将其添加到 cfnbootstrap 库的 cacert.pem 文件中。

cat isgrootx1.pem >> /path/to/your/python/env/lib/python3.9/site-packages/cfnbootstrap/packages/requests/cacert.pem

您可以通过以下方式找到您的 cacert.pem 的位置:

from cfnbootstrap.packages.requests.certs import where
print(where())

另外...我会更改您的代码以确保您实际使用的是 cfn 打包请求模块而不是独立请求。否则,您可能必须在这两个地方都更新它。

from cfnbootstrap.packages.requests.utils import DEFAULT_CA_BUNDLE_PATH
from cfnbootstrap.packages.requests.packages import urllib3

conn = urllib3.connection_from_url("https://www.phpmyadmin.net/", retries=False)
conn.cert_reqs = 'CERT_REQUIRED'
conn.ca_certs = DEFAULT_CA_BUNDLE_PATH
response = conn.request("GET", "/get/")
conn.close()
print(response.status)

如果您确实要更新独立请求和使用 cfnbootstrap 打包的请求,请使用以下命令查找并更新两个 cacert 路径:

import requests
import cfnbootstrap.packages.requests

print(requests.certs.where())
print(cfnbootstrap.packages.requests.certs.where())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-09
    • 2015-11-15
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 2012-11-14
    相关资源
    最近更新 更多