web-dev-qa-db-ja.com

Pythonリクエスト-システムCA証明書(debian / ubuntu)の使用方法は?

自己署名ルートCA証明書をdebianの/usr/share/ca-certificates/localにインストールし、Sudo dpkg-reconfigure ca-certificatesでインストールしました。この時点でtrue | gnutls-cli mysite.localは幸せで、true | openssl s_client -connect mysite.local:443は幸せですが、python2およびpython3要求モジュールは証明書に満足していないと主張します。

python2:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/adapters.py", line 497, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)

python3

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/bin/python3.5/site-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/adapters.py", line 497, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)

pythonがシステムCA証明書のバンドルを無視するのはなぜですか。どのように統合しますか?

23
ThorSummoner

https://stackoverflow.com/a/33717517/169568 から

pythonリクエストがシステムca-certificatesバンドルを使用するようにするには、独自の組み込みバンドルで使用するように指示する必要があります

export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt

リクエストは、参照用にバンドルをここに埋め込みます:

/usr/local/lib/python2.7/site-packages/requests/cacert.pem
/usr/lib/python3/dist-packages/requests/cacert.pem
46
ThorSummoner

私は最近一週間かそこらでこれに苦労しました。最終的に、Pythonで自己署名証明書または非公開署名証明書を検証する方法を見つけました。独自の証明書バンドルファイルを作成する必要があります。ライブラリを更新するたびに不明瞭な証明書バンドルを更新したり、システム証明書ストアに何かを追加したりする必要はありません。

前に実行したopensslコマンドを実行して開始しますが、-showcertsを追加します。 openssl s_client -connect mysite.local:443 -showcertsこれにより長い出力が得られ、上部に証明書チェーン全体が表示されます。通常、これは3つの証明書、つまりWebサイトの証明書、中間証明書、およびルート証明書の順に意味します。ルート証明書と中間証明書だけを、逆の順序で次のファイルに配置する必要があります。

最後の証明書であるルート証明書を新しいテキストファイルにコピーします。次のものを含む、次のものを取得します。

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

中間証明書(別名中間証明書)をルート証明書の下の新しいテキストファイルにコピーします。繰り返しますが、開始証明書と終了証明書の行、およびその間のすべてを取得します。

このテキストファイルをPythonスクリプトが存在するディレクトリに保存します。私の推奨は、CertBundle.pemと呼ぶことです。 (別の名前を付けるか、フォルダー構造内の別の場所に配置する場合は、verify行にそれが反映されていることを確認してください。)スクリプトを更新して、新しい証明書バンドルを参照します。

response = requests.post("https://www.example.com/", headers=headerContents, json=bodyContents, verify="CertBundle.pem")

以上です。ルートのみまたは中間証明書のみがある場合、Pythonは証明書チェーン全体を検証できません。ただし、作成した証明書バンドルに両方の証明書を含めると、Pythonは中間体がルートによって署名されたことを検証でき、WebサイトにアクセスするときにWebサイトの証明書を検証できます中間証明書によって署名されました。

編集:証明書バンドルのファイル拡張子を修正しました。また、いくつかの文法上の間違いを修正しました。

6
fryad