问题 AppEngine urlfetch validate_certificate = False / None未被遵守


在AppEngine开发人员应用程序服务器中,我收到如下错误:

SSLCertificateError: Invalid and/or missing SSL certificate for URL ...

当我像这样取一个 https 带有自签名证书的服务器(几乎总是如此 localhost 通过ssh端口转发到vm):

result = urlfetch.fetch(url=url, method=method, payload=payload,
                        deadline=DEADLINE, validate_certificate=None)

人们不会指望无效证书的SSL失败在哪里 validate_certificate 是 False虽然这很可能是Python中2.7.9策略的副作用,总是验证ssl证书。

注意通过 False (代替 None)为 validate_certificate 也不起作用。

这个问题在Python 2.7.9-10上通过OS X 10.10.2-4上的Homebrew / XCode以及AppEngine 1.9.18到1.19.26发生。

存在问题(例如 12096)关于谷歌App Engine的这个,但我正在寻找一个解决方法。

这是我试图解决的问题:

  1. 将证书添加到Mac的登录密钥链(在浏览器中工作,而不是从Python工作)

  2. 添加证书到 app-engine-python/lib/cacerts/cacerts.txt 和/或 ./lib/cacerts/urlfetch_cacerts.txt  (尽管这可能需要进行验证  因为它似乎是唯一使用它们的情况,例如

    $ echo >> /usr/local/share/app-engine-python/lib/cacerts/urlfetch_cacerts.txt

    $ openssl x509 -subject -in server.crt >> /usr/local/share/app-engine-python/lib/cacerts/urlfetch_cacerts.txt

  3. 禁用ssl HTTPs检查 PEP-0476 解决方法即

    ssl._create_default_https_context = ssl._create_unverified_context

    在...之后 import ssl (1149行左右) google/appengine/dist27/python_std_lib/httplib.py

这在Mac上尤其成问题,因为从XCode 7 / OS X El Capital降级不再是一个实用的选择。

每次更新开发应用程序服务器时,更好的解决方法都不会涉及对AppEngine代码进行猴子修补。


编辑

请注意,Mac内置OpenSSL证书存储在 /System/Library/OpenSSL,受到保护 SIP /无所归依如果可以的话,坦白地说这是一种痛苦的事情,并且值得保留。

我已验证证书通过使用验证 openssl s_client -connect localhost:7500 -CAfile server.pem

它被添加到Keychain和 /usr/local/etc/openssl/certs 随着 hash.# 哈希来自的格式 openssl x509 -subject_hash -in server.pem (或自制软件ssl,即 /usr/local/Cellar/openssl/1.0.2d_1/bin/openssl)。在这种情况下 /usr/local/Cellar/openssl/1.0.2d_1/bin/openssl s_client -connect localhost:7500 验证证书(但python仍然没有)。

我曾尝试使用自制版本的python和openssl,但无济于事。在Python中运行以下似乎总是失败;

./pve/bin/python -c "import requests; requests.get('https://localhost:7500')"

这也失败了 SSL_CERT_FILE 被设置为服务器的证书(即,对于添加的度量,人们可能期望它可以工作,因为 openssl 命令基本上像这样工作),也失败在哪里 SSL_CERT_PATH 被设定为 /usr/local/etc/openssl/certs

注意, pve 是一个虚拟的环境 help(ssl) 显示一个 FILE 的 /usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py

进一步验证自制软件的Python _ssl.so 链接到homebrew的openssl我跑了:

xcrun otool -L /usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/_ssl.so

返回

./Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/_ssl.so:

/usr/local/opt/openssl/lib/libssl.1.0.0.dylib(兼容性版本1.0.0,当前版本1.0.0)

/usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib(compatibility版本1.0.0,当前版本1.0.0)

/usr/lib/libSystem.B.dylib(兼容版本1.0.0,当前版本1225.1.1)

如果运行 brew info openssl 它的评论在 CAVEATS

已使用系统中的证书引导CA文件   钥匙扣。要添加其他证书,请将.pem文件放入     在/ usr / local / etc中/ OpenSSL的/证书

但显然由于某种原因,python没有使用自制软件的openssl算法来查找证书。

所以我仍然不知道为什么Python标准库没有验证文档中指定的OpenSSL目录中的证书以及Keychain(两者都在 .pem 和 .p12 格式,“永远信任” Secure Sockets Layer (SSL))。


12881
2018-03-04 23:00


起源



答案:


这是一个 dev_appserver 由...引起的错误 httplib.HTTPSConnection 最近一些Python版本中的行为更改(默认情况下打开证书检查)(我相信2.7.9)。

因为bug在内部 dev_appserver 代码(文件 google_appengine/google/appengine/api/urlfetch_stub.py 独立于被测试的应用程序运行的appengine SDK),没有办法在SDK更新后继续进行修复。

我能想到的唯一永久性解决方法是启用 validate_certificate 并添加 CA 证书到 urlfetch_cacerts.txt 文件。作为临时修复,您可以修补 urlfetch_stub.py 解决方法#3。


8
2017-09-30 01:14



谢谢@Alex。如果无法将证书添加到Mac的系统中,那么Python的Httplib将会使用吗? - Brian M. Hunt
Brian,我不太熟悉python ssl lib如何在Mac上运行,我会检查 ssl doc页面 并查看默认路径字符串是什么: ssl.get_default_verify_paths()。可能有一种方法可以使用 env变量,用于设置您的证书文件的路径。 - Alex
这是相关的文档 关于如何为openssl添加自签名证书。 - Alex
谢谢Alex。我已经尝试过,但尚未成功,将我的证书添加到钥匙串中。以下是对如何操作的另一种描述,您可能有兴趣在您的答案中包含: apple.stackexchange.com/questions/8993 - Brian M. Hunt
目前我通过添加证书来解决这个问题 urlfetch_cacerts.txt 并启用 validate_certificate。 - Brian M. Hunt


答案:


这是一个 dev_appserver 由...引起的错误 httplib.HTTPSConnection 最近一些Python版本中的行为更改(默认情况下打开证书检查)(我相信2.7.9)。

因为bug在内部 dev_appserver 代码(文件 google_appengine/google/appengine/api/urlfetch_stub.py 独立于被测试的应用程序运行的appengine SDK),没有办法在SDK更新后继续进行修复。

我能想到的唯一永久性解决方法是启用 validate_certificate 并添加 CA 证书到 urlfetch_cacerts.txt 文件。作为临时修复,您可以修补 urlfetch_stub.py 解决方法#3。


8
2017-09-30 01:14



谢谢@Alex。如果无法将证书添加到Mac的系统中,那么Python的Httplib将会使用吗? - Brian M. Hunt
Brian,我不太熟悉python ssl lib如何在Mac上运行,我会检查 ssl doc页面 并查看默认路径字符串是什么: ssl.get_default_verify_paths()。可能有一种方法可以使用 env变量,用于设置您的证书文件的路径。 - Alex
这是相关的文档 关于如何为openssl添加自签名证书。 - Alex
谢谢Alex。我已经尝试过,但尚未成功,将我的证书添加到钥匙串中。以下是对如何操作的另一种描述,您可能有兴趣在您的答案中包含: apple.stackexchange.com/questions/8993 - Brian M. Hunt
目前我通过添加证书来解决这个问题 urlfetch_cacerts.txt 并启用 validate_certificate。 - Brian M. Hunt


我在Windows上遇到了同样的问题。我使用的是旧版本的Python(2.7)。当我升级到Python 2.7.11时,问题就消失了。


1
2018-06-11 21:37