AppEngine 開発者 appserver で、次のようなエラーが発生します。
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
) forを渡すことvalidate_certificate
も機能しないことに注意してください。
この問題は、AppEngine 1.9.18 ~ 1.19.26 を搭載した OS X 10.10.2-4 上の Homebrew/XCode を介して Python 2.7.9-10 で発生します。
Google App Engine ではこれに関する問題 (例: 12096 ) がありますが、回避策を探しています。
これを回避するために私が試みたのは次のとおりです。
証明書を Mac のログイン キーチェーンに追加します (Python からではなく、ブラウザーで機能します)。
app-engine-python/lib/cacerts/cacerts.txt
証明書をand/orに追加します(ただし、これが機能する./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
PEP-0476回避策で ssl HTTPS チェックを無効にします。
ssl._create_default_https_context = ssl._create_unverified_context
の前後
import ssl
(1149行目あたり)google/appengine/dist27/python_std_lib/httplib.py
XCode 7/OS X El Capital の時点でのダウングレードは実用的なオプションではなくなったため、これは Mac では特に問題になります。
推奨される回避策は、開発アプリケーション サーバーが更新されるたびに適切な AppEngine コードにモンキー パッチを適用しないことです。
編集
Mac 組み込みの OpenSSL 証明書は、 SIP/rootlessness/System/Library/OpenSSL
で保護されている に保存されていることに注意してください。これは、率直に言って、いじるのが面倒で、できれば維持する価値のある機能です。
を使用して、証明書が有効であることを確認しましたopenssl s_client -connect localhost:7500 -CAfile server.pem
。
これは、キーチェーンに追加され、ハッシュが由来する形式/usr/local/etc/openssl/certs
(または自作の ssl、つまり) に追加されました。その場合、証明書を検証します (ただし、python は検証しません)。hash.#
openssl x509 -subject_hash -in server.pem
/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 と 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
_ssl.so
自作のPythonの自作の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 (互換バージョン 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/certs に配置します。
しかし、明らかに何らかの理由で、Pythonは証明書を見つけるために自作のopensslアルゴリズムを使用していません。
そのため、ドキュメントとキーチェーンで指定された OpenSSL ディレクトリにある証明書を Python 標準ライブラリが検証しない理由について、私は途方に暮れています ( と の両方.pem
の.p12
形式で、 を「常に信頼」しSecure Sockets Layer (SSL)
ます)。