Pythonのrequestsでverify=Falseを使わずにSSLの検証を無効化する


社内ネットワークを使って開発をしていると、Proxyをはじめとしたさまざまなトラップに引っ掛かります。
先日、Pythonで某モジュールを使おうとしたらモジュール内部のrequestsでSSLサーバ証明書の検証に失敗し、requests.exceptions.SSLErrorが発生しました。

通常、requestsでSSLサーバ証明書の検証を無効化するには、次のように書きます。

requests.get("https://www.google.com", verify=False)

ただし、このやり方はコードの修正が必要なので、モジュール内部のrequestsには使えません。
調べたところ、次のrequestsをハックするやり方が見つかりましたので、紹介します。

やり方

環境変数CURL_CA_BUNDLEに空文字を設定します。

import os
os.environ['CURL_CA_BUNDLE'] = ''

仕組み

requestsには次のように環境変数CURL_CA_BUNDLEREQUESTS_CA_BUNDLEverifyを上書きする処理があります。これをハックしてverifyFalseにします。

requests/session.py
            if verify is True or verify is None:
                verify = (os.environ.get('REQUESTS_CA_BUNDLE') or
                          os.environ.get('CURL_CA_BUNDLE'))

実際にはFalseにするのではなく、Falseと評価される空文字にします。なぜ同様にFalseと評価されるNoneではダメで空文字にするかというと、Noneだと後にTrueで上書きされるからです。

ここでPythonのorの仕組みを簡単に説明すると、A or BA == TrueのときAA == FalseのときBを返します。よって

>>> None or None
None
>>> '' or None
None
>>> None or ''
''

となります。これを利用すれば環境変数CURL_CA_BUNDLEに空文字を設定してverifyを空文字、つまりFalseにすることができます。