requestsの独自証明書エラーの解決法をCopilotに教えてもらった
!注意
こちらはCopilotの回答を基に情報をまとめたものであり、内容のすべてについて検証できているものではありません。誤った情報が含まれている可能性もゼロではないため、リンク先の参考情報も合わせて確認することをお勧めします。
エラー内容
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)
エラーの原因と解決方法
エラーの原因
このエラーは、SSL/TLS接続を確立する際に、ローカルの証明書ストアに信頼できる証明書が見つからない場合に発生します。具体的な原因としては以下が考えられます:
※Pythonのrequestsライブラリがデフォルトで参照するローカル証明書のパスは、システムに依存します。一般的には、requestsライブラリはcertifi
パッケージを使用して、信頼できるCA証明書のバンドルを提供します。
デフォルトの証明書バンドルのパスは、以下のように確認できます:
import certifi
print(certifi.where())
このコードを実行すると、certifi
が使用するCA証明書バンドルのパスが表示されます。通常、このパスはPythonの仮想環境やシステムのPythonインストールディレクトリ内にあります[3][4][5]。
例えば、Windowsでは以下のようなパスが表示されることがあります:
C:\Users\<ユーザー名>\AppData\Local\Programs\Python\Python<バージョン>\lib\site-packages\certifi\cacert.pem
解決方法 ※ 3、6のみ検証済み
-
証明書ファイルを指定する:
独自の証明書ファイルを使用する場合、PythonのSSLコンテキストにその証明書を追加します。import ssl import urllib.request url = "https://example.com" context = ssl.create_default_context() context.load_verify_locations(cafile="path/to/my_cert.pem") response = urllib.request.urlopen(url, context=context) print(response.read())
-
requestsライブラリを使用する場合:
requests
ライブラリを使用している場合も、証明書ファイルを指定できます。import requests url = "https://example.com" response = requests.get(url, verify="path/to/my_cert.pem") print(response.text)
-
環境変数を設定する:
REQUESTS_CA_BUNDLE
環境変数を設定して、requestsライブラリが使用する証明書ファイルを指定します。set REQUESTS_CA_BUNDLE=path/to/my_cert.pem
-
ファイル形式を変換する:
証明書ファイルの形式が正しくない場合、OpenSSLを使用して変換します。openssl x509 -in path/to/certificate.crt -out path/to/certificate.pem -outform PEM
-
システムに証明書をインストールする:
システム全体に証明書をインストールすることで、すべてのアプリケーションがその証明書を使用できるようにします。# macOS sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain path/to/my_cert.pem # Linux sudo cp path/to/my_cert.pem /usr/local/share/ca-certificates/ sudo update-ca-certificates
-
certifiライブラリを更新する[6]:
certifi
ライブラリが持つルート証明書のリストに独自の証明書を追加します。import certifi import requests # certifiの証明書バンドルに独自の証明書を追加 with open(certifi.where(), 'a') as cert_file: cert_file.write(open("path/to/my_cert.pem").read()) # requestsで使用 url = "https://example.com" response = requests.get(url) print(response.text)
REQUESTS_CA_BUNDLE
と証明書参照先requests
ライブラリのデフォルト設定では、certifi
パッケージが提供するCA証明書バンドルを使用します。具体的には、certifi
のcacert.pem
ファイルを参照します。REQUESTS_CA_BUNDLE
環境変数を設定しない場合、requests
ライブラリは自動的にcertifi
の証明書バンドルを使用します[7][8]。デフォルトの動作
-
デフォルトでは、
certifi
の証明書バンドルを使用:
import requests import certifi print(certifi.where()) # certifiの証明書バンドルのパスを表示 response = requests.get("https://example.com") print(response.text)
REQUESTS_CA_BUNDLE
環境変数の設定-
REQUESTS_CA_BUNDLE
環境変数を設定することで、カスタム証明書バンドルを使用:
export REQUESTS_CA_BUNDLE=path/to/my_cert.pem
この環境変数が設定されている場合、
requests
ライブラリはcertifi
の証明書バンドルではなく、指定された証明書バンドルを使用します。設定されていない場合は、デフォルトでcertifi
の証明書バンドルを使用します[8:1][9]。まとめ
-
デフォルト値:
certifi
のcacert.pem
ファイルを参照。 -
環境変数が設定されている場合:
REQUESTS_CA_BUNDLE
で指定された証明書バンドルを使用。
1: Advanced Usage — Requests Documentation
2: How to Get Python Requests to Trust a Self-Signed SSL Certificate
3: GitHub Issue on REQUESTS_CA_BUNDLE -
デフォルトでは、
注意点
- パスの確認: 証明書ファイルのパスが正しいことを確認してください。
- ファイルの存在確認: 指定したパスに証明書ファイルが存在するか確認してください。
- バックアップ: 変更前に元のファイルのバックアップを取っておくことをお勧めします。
-
https://qiita.com/ground0state/items/c4d7caa274b6e3d99e27 ↩︎
-
https://rakuraku-engineer.com/posts/python-request-get-error-ssl/ ↩︎
-
https://docs.python-requests.org/en/latest/api/?highlight=tls+authentication ↩︎
-
https://pytutorial.com/python-requests-ssl-verification-a-complete-guide/ ↩︎
-
https://www.pythonrequests.com/python-requests-verify-certificate-path/ ↩︎
-
pemファイルに対し、独自証明書の中身を直接コピペすることでも対応可能 ↩︎
-
https://docs.python-requests.org/en/master/user/advanced.html ↩︎ ↩︎
-
https://sqlpey.com/python/solved-how-to-get-python-requests-to-trust-a-self-signed-ssl-certificate/ ↩︎
Discussion