我有一个可以通过多个 URL 访问的网站,其中 2 个具有 SSL 证书,这些证书使用 SSL SNI 提供(整个事情都是使用 nginx 提供的)。
只要两个证书都有效,此设置对于浏览器以及监视网站的 Python 2.7.11 代码都可以正常工作。
最近,其中一个证书过期 - 没有用于任何事情(不用于入站流量,也不用于监控)的证书。这对访问该网站的浏览器没有影响,但它开始导致监控 Python 脚本出现故障,如下所示:
2016-12-24 02:09:49,351 - foo.__main__(140582120666944) - app_monitoring.py:90 - ERROR - Call to <lambda> Failed 1 times
Traceback (most recent call last):
File "devops/monitoring/app_monitoring.py", line 88, in call_with_retry
func(*args, **kwargs)
File "devops/monitoring/app_monitoring.py", line 116, in <lambda>
test_func=lambda: yapi_calls.test_api_on_all_datasets(Flags.yapi_url)),
File "/usr/src/app/system_tests/yapi_calls.py", line 158, in test_api_on_all_datasets
datasets = send(yapi_url, 'list_datasets', {})
File "/usr/src/app/system_tests/yapi_calls.py", line 48, in send
return gcloud.get_yapi(yapi_url).execute(api_call, req)
File "/usr/src/app/cloudapi/yapi.py", line 23, in execute
return self._execute(api_call, req, True)
File "/usr/src/app/cloudapi/yapi.py", line 36, in _execute
headers=headers)
File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 631, in new_request
redirections, connection_type)
File "/usr/local/lib/python2.7/dist-packages/httplib2/__init__.py", line 1609, in request
(response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
File "/usr/local/lib/python2.7/dist-packages/httplib2/__init__.py", line 1351, in _request
(response, content) = self._conn_request(conn, request_uri, method, body, headers)
File "/usr/local/lib/python2.7/dist-packages/httplib2/__init__.py", line 1272, in _conn_request
conn.connect()
File "/usr/local/lib/python2.7/dist-packages/httplib2/__init__.py", line 1059, in connect
raise SSLHandshakeError(e)
SSLHandshakeError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
注意:我有一个有效证书和一个过期证书,问题是由于证书过期而引发异常,即使我通过有效证书的 URL。
我检查了requests
,访问“好”的 URL 没有问题,但如果我访问过期的 URL,则会出现预期的 SSL 错误 - 所以我怀疑这是 httplib2 处理 SNI 证书的特定问题。
不幸的是,我无法切换到requests
这个流程,因为这是一个外部库(在堆栈跟踪中可见 - oauth2client
)。
除了安装新的有效 SNI 证书(或切换到非 SNI 证书)之外,我还能做些什么吗?
更新:我找到了一种适用于这种情况的解决方法。
使用 nginx 提供 SSL SNI 时,仍然需要设置默认证书。事实证明,在这种情况下,默认证书是过期的。通过将默认证书更改为有效证书,错误消失了。
这种解决方法让我认为 httplib2 SSL SNI 实现中存在错误 - 它似乎需要验证默认证书,即使它不是所请求域的证书。