WSL(Ubunu) 環境 Python のSSL: CERTIFICATE_VERIFY_FAILED を対処する

2月 25, 2024Python,Ubuntu(WSL)

概要

  • 今回、PCにCA 証明書を配置する必要があり、WSL(Ubunu) 環境にてPython の SSL: CERTIFICATE_VERIFY_FAILED を経験しましたので対処方法をまとめます。

 

エラーの発生状況

  • WSL(Ubunu) 環境でAWS を管理する際に使用している aws-mfa のツールを実行した際に、以下のエラーを経験しました。(エラーメッセージの詳細は後述)
    • " [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain"
  • エラーメッセージからCA 証明書を配置する必要があることは分かりましたが、Ubuntu のOS が参照する全般の証明書は配置済みであり、この(Pythonで出来ている)ツールをエラーなく実行するために何を行えば良いか調べることにしました。

エラーメッセージの詳細

Traceback (most recent call last):
  File "/home/niikawa/.local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 468, in _make_request
    self._validate_conn(conn)
  File "/home/niikawa/.local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 1097, in _validate_conn
    conn.connect()
  File "/home/niikawa/.local/lib/python3.10/site-packages/urllib3/connection.py", line 642, in connect
    sock_and_verified = _ssl_wrap_socket_and_match_hostname(
  File "/home/niikawa/.local/lib/python3.10/site-packages/urllib3/connection.py", line 783, in _ssl_wrap_socket_and_match_hostname
    ssl_sock = ssl_wrap_socket(
  File "/home/niikawa/.local/lib/python3.10/site-packages/urllib3/util/ssl_.py", line 471, in ssl_wrap_socket
    ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname)
  File "/home/niikawa/.local/lib/python3.10/site-packages/urllib3/util/ssl_.py", line 515, in _ssl_wrap_socket_impl
    return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/lib/python3.10/ssl.py", line 513, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/lib/python3.10/ssl.py", line 1100, in _create
    self.do_handshake()
  File "/usr/lib/python3.10/ssl.py", line 1371, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1007)

** 省略 **

 

対処方法

前提作業

  • WSL(Ubunu) 環境にCA 証明書を配置する必要があります。以下、オペレーション例です。CA 証明書は、PEM形式で準備しておきます。
  • これでUbuntu のOS は、配置されたCA 証明書を参照します。しかし、Python は個別でCA 証明書を設定する必要がありました。
% sudo su -
# mkdir /usr/share/ca-certificates/myca
# cp myca-certificates.pem /usr/share/ca-certificates/myca
# echo "myca/myca-certificates.pem" >> /etc/ca-certificates.conf
# update-ca-certificates

 

Python環境変数に CA_BUNDLE パスを設定する

  • aws-mfa のツールでSSL証明書の検証が行われています。こちらのドキュメントによれば、requests の API にverify 引数を指定してCA_BUNDLE パスを渡せる様です。しかし、間接的にPython のrequests を使用しているだけであり、ツール自体に手を加えたくはありません。
  • そのため、今回は環境変数 のREQUESTS_CA_BUNDLE を設定し、CA_BUNDLE パスを指定してaws-mfa のツール (Python) を実行します。
  • 必要に応じて、シェル起動時のスクリプトに環境変数を追記ください。
## Pythonの cacert.pem のパスを確認する
$ sudo find /usr -name cacert.pem -print

## cacert.pem にCA 証明書の内容を追記する
$ sudo vi /usr/local/lib/python3.10/dist-packages/pip/_vendor/certifi/cacert.pem

## 環境変数 REQUESTS_CA_BUNDLE を設定する
$ export REQUESTS_CA_BUNDLE="/usr/local/lib/python3.10/dist-packages/pip/_vendor/certifi/cacert.pem"