search
LoginSignup
48

More than 5 years have passed since last update.

posted at

macOS用公式インストーラーのPython 3.6でCERTIFICATE_VERIFY_FAILEDとなる問題

この記事の内容はインストーラーの大切な情報にすべて書いてありますが、気づかないとハマるので残しておきます。

Pythonインストーラーの大切な情報

問題

python.orgで配布されているmacOS用の公式インストーラーでインストールしたPython 3.6を使い、urllib.request.urlopen()https://のWebページを取得しようとすると、以下のエラーが発生します。

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 1318, in do_open
    encode_chunked=req.has_header('Transfer-encoding'))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1026, in _send_output
    self.send(msg)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 964, in send
    self.connect()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/http/client.py", line 1400, in connect
    server_hostname=server_hostname)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 401, in wrap_socket
    _context=self, _session=session)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 808, in __init__
    self.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 1061, in do_handshake
    self._sslobj.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 683, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 223, in urlopen
    return opener.open(url, data, timeout)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 526, in open
    response = self._open(req, data)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 544, in _open
    '_open', req)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 504, in _call_chain
    result = func(*args)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 1361, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 1320, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)>

他にもsslモジュールを使うモジュールではサーバー証明書の検証時に同様のエラーが発生するはずです。

原因

macOSに標準でインストールされているOpenSSLが古すぎるため、Python 3.6以降ではmacOS用のインストーラーにはOpenSSLが同梱され、システムのOpenSSLは参照されなくなりました。

これによって、OSにインストールされたルート証明書も参照されず、インストール直後の状態ではルート証明書が含まれていません1。このため、TLSサーバー証明書の検証に失敗します。

対処法

以下のコマンドを実行すると、certifiモジュールをダウンロードしそこに含まれるルート証明書を参照するようになります。

$ /Applications/Python\ 3.6/Install\ Certificates.command

実行前:

$ ls -l /Library/Frameworks/Python.framework/Versions/3.6/etc/openssl/

実行後:

$ ls -l /Library/Frameworks/Python.framework/Versions/3.6/etc/openssl/
total 8
lrwxr-xr-x  1 orange  admin  52  3 22 23:00 cert.pem -> ../../lib/python3.6/site-packages/certifi/cacert.pem

この場合、ルート証明書の更新に応じて適切にアップデートするために、certifiプロジェクトのメーリングリストを購読しましょうと書かれています。

今後

ユーザーが個別に証明書をアップデートしなければならない今の状態は望ましくないので、DSAS開発者の部屋:最近の Python-dev (2017-03)にあった、OpenSSL以外のTLS実装を使ってOSの証明書を利用できるようにするPEP 543の話につながっていくのだと思います。

参考


  1. pipはルート証明書を同梱しているので、pip installは動きます。 

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
What you can do with signing up
48