9
8

More than 3 years have passed since last update.

requestsでAPIコールする際にSSL: CERTIFICATE_VERIFY_FAILEDが出ても、認証を切らない対処法

Last updated at Posted at 2021-02-12

requestsを使ってhttpsのエンドポイントにAPIコールしたらSSLErrorになった。

requests.exceptions.SSLError: HTTPSConnectionPool(host='example.com', port=443): Max retries exceeded with url: /exampleapi (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)'),))

あえてHTTPS接続をする必要がないテスト時などは、以下の方法でSSL認証をしないことで回避できる。

requests.get('https://example.com/exampleapi', verify=False)

そうできない場合にどうするか。

原因

今回接続したいAPIは、Root認証局の証明書と中間認証局の証明書が必要だった。
エラーの原因は、システムがRoot認証局の証明書については持っていたが、中間認証局の証明書を持っていなかったことだった。

対策

この場合の対策は、要するに中間認証局の証明書を渡すことだが、2通りある。

1. verifyにRoot認証局の証明書と中間認証局の証明書のあるフォルダパスを渡す

Ubuntu/Debianの場合、Root認証局の証明書は/etc/ssl/certs以下にある。
ここに中間認証局の証明書を配置する。
中間証明書は、ブラウザのURLバー脇の鍵アイコンをクリックし、証明書を見るとわかる。

今回は認証局としてEntrustを利用しているAPIであったため、Entrustのサイトから中間認証局の証明書を取得した。

その上で、c_rehashコマンドで中間証明書を処理しておく。
(なお、手元の中間証明書の拡張子は.cerでなく.crtにしないとc_rehashコマンドで処理されなかった。)

$ c_rehash /etc/ssl/certs

この状態で、コードを以下のように修正する。

requests.get('https://example.com/someapi', verify='/etc/ssl/certs')

これで、中間認証局の証明書も見てくれるのでSSLErrorがなくなる。

2. 中間認証局の証明書を含めた、単一の証明書ファイルを更新する

Ubuntu/Debianの場合、/etc/ssl/certs/ca-certificates.crtに、設定済みの証明書をすべてまとめたファイルがある。
これに、中間認証局の証明書を含めることでも対応できる。

中間証明書が/tmp/intermediate-ca.cer というパスにあるとして、以下のコマンドで行える。

$ mkdir /usr/share/ca-certificates/mylocal
$ cp /tmp/intermediate-ca.cer /usr/share/ca-certificates/mylocal
$ echo "mylocal/intermediate-ca.cer" >> /etc/ca-certificates.conf
$ sudo update-ca-certificates

これで/etc/ssl/certs/ca-certificates.crtに中間認証局の証明書が入るので、1と同様、requestsのverify引数に渡せる。

requests.get('https://example.com/someapi', verify='/etc/ssl/certs/ca-certificates.crt')

また、REQUESTS_CA_BUNDLEという環境変数にセットすれば、verify引数をセットしなくてもよくなる。
※requests公式docのSSL Cert Verification

$ REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt python
>> requests.get('https://example.com/someapi')

opensslコマンドでの確認方法

SSLErrorが出る原因を調べる際にopensslのコマンドが役に立った。

$ openssl s_client -connect example.com:443 -servername example.com

...


    Verify return code: 21 (unable to verify the first certificate)

このように、return codeで何が問題かわかる。(この場合は中間証明書かRoot証明書が悪い)

問題ないときは、以下のようなコードが表示される。

    Verify return code: 0 (ok)

参考にしたURL

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8