2018/10/10

Python 3.5 を Ubuntu 18.04 上でビルドしたらテストが通らなかった

Ubuntu 18.04 で Python 3.5 系の動作確認をするため1、ソースコードからビルドしてみました。

しかし、以下のように test_alpn_protocols が通りません。

$ cd Python-3.5.6
$ ./configure --prefix=${HOME}/opt/python-3.5.6
$ make
$ make test
 
省略
 
======================================================================
FAIL: test_alpn_protocols (test.test_ssl.ThreadedTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/yusuke/Downloads/Python-3.5.6/Lib/test/test_ssl.py", line 3183, in test_alpn_protocols
    self.assertIsInstance(stats, ssl.SSLError)
AssertionError: {'client_npn_protocol': None, 'compression': None, 'server_npn_protocols': [None], 'server_alpn_protocols': [None], 'client_alpn_protocol': None, 'version': 'TLSv1.2', 'peercert': {}, 'server_shared_ciphers': [[('ECDHE-ECDSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('ECDHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('ECDHE-RSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('ECDHE-ECDSA-CHACHA20-POLY1305', 'TLSv1.2', 256), ('ECDHE-RSA-CHACHA20-POLY1305', 'TLSv1.2', 256), ('DHE-DSS-AES256-GCM-SHA384', 'TLSv1.2', 256), ('DHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256), ('DHE-DSS-AES128-GCM-SHA256', 'TLSv1.2', 128), ('DHE-RSA-AES128-GCM-SHA256', 'TLSv1.2', 128), ('DHE-RSA-CHACHA20-POLY1305', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES256-CCM8', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES256-CCM', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES256-SHA384', 'TLSv1.2', 256), ('ECDHE-RSA-AES256-SHA384', 'TLSv1.2', 256), ('ECDHE-ECDSA-AES256-SHA', 'TLSv1.0', 256), ('ECDHE-RSA-AES256-SHA', 'TLSv1.0', 256), ('DHE-RSA-AES256-CCM8', 'TLSv1.2', 256), ('DHE-RSA-AES256-CCM', 'TLSv1.2', 256), ('DHE-RSA-AES256-SHA256', 'TLSv1.2', 256), ('DHE-DSS-AES256-SHA256', 'TLSv1.2', 256), ('DHE-RSA-AES256-SHA', 'SSLv3', 256), ('DHE-DSS-AES256-SHA', 'SSLv3', 256), ('ECDHE-ECDSA-AES128-CCM8', 'TLSv1.2', 128), ('ECDHE-ECDSA-AES128-CCM', 'TLSv1.2', 128), ('ECDHE-ECDSA-AES128-SHA256', 'TLSv1.2', 128), ('ECDHE-RSA-AES128-SHA256', 'TLSv1.2', 128), ('ECDHE-ECDSA-AES128-SHA', 'TLSv1.0', 128), ('ECDHE-RSA-AES128-SHA', 'TLSv1.0', 128), ('DHE-RSA-AES128-CCM8', 'TLSv1.2', 128), ('DHE-RSA-AES128-CCM', 'TLSv1.2', 128), ('DHE-RSA-AES128-SHA256', 'TLSv1.2', 128), ('DHE-DSS-AES128-SHA256', 'TLSv1.2', 128), ('DHE-RSA-AES128-SHA', 'SSLv3', 128), ('DHE-DSS-AES128-SHA', 'SSLv3', 128), ('ECDHE-ECDSA-CAMELLIA256-SHA384', 'TLSv1.2', 256), ('ECDHE-RSA-CAMELLIA256-SHA384', 'TLSv1.2', 256), ('ECDHE-ECDSA-CAMELLIA128-SHA256', 'TLSv1.2', 128), ('ECDHE-RSA-CAMELLIA128-SHA256', 'TLSv1.2', 128), ('DHE-RSA-CAMELLIA256-SHA256', 'TLSv1.2', 256), ('DHE-DSS-CAMELLIA256-SHA256', 'TLSv1.2', 256), ('DHE-RSA-CAMELLIA128-SHA256', 'TLSv1.2', 128), ('DHE-DSS-CAMELLIA128-SHA256', 'TLSv1.2', 128), ('DHE-RSA-CAMELLIA256-SHA', 'SSLv3', 256), ('DHE-DSS-CAMELLIA256-SHA', 'SSLv3', 256), ('DHE-RSA-CAMELLIA128-SHA', 'SSLv3', 128), ('DHE-DSS-CAMELLIA128-SHA', 'SSLv3', 128), ('AES256-GCM-SHA384', 'TLSv1.2', 256), ('AES128-GCM-SHA256', 'TLSv1.2', 128), ('AES256-CCM8', 'TLSv1.2', 256), ('AES256-CCM', 'TLSv1.2', 256), ('AES128-CCM8', 'TLSv1.2', 128), ('AES128-CCM', 'TLSv1.2', 128), ('AES256-SHA256', 'TLSv1.2', 256), ('AES128-SHA256', 'TLSv1.2', 128), ('AES256-SHA', 'SSLv3', 256), ('AES128-SHA', 'SSLv3', 128), ('CAMELLIA256-SHA256', 'TLSv1.2', 256), ('CAMELLIA128-SHA256', 'TLSv1.2', 128), ('CAMELLIA256-SHA', 'SSLv3', 256), ('CAMELLIA128-SHA', 'SSLv3', 128)]], 'cipher': ('ECDHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256)} is not an instance of <class 'ssl.sslerror'="">

原因

原因は OpenSSL の仕様がバージョン 1.1.0e 以降で変わったことのようです。

参考

Issue 30714: test_ssl fails with openssl 1.1.0f: test_alpn_protocols() - Python tracker

私の環境で Open SSL のバージョンを調べてみると 1.1.0g

$ openssl version
OpenSSL 1.1.0g  2 Nov 2017

上記 Issue は 2.7, 3.6, 3.7 では修正されているものの、3.5 は直されていないようです。

対策

3.6 用に入れられた修正を 3.5 にも適用するとテストが通るようになります。

[3.6] bpo-30714: ALPN changes for OpenSSL 1.1.0f (#3093) · python/cpython@7f6a13b · GitHub

1
2
3
4
5
6
7
8
9
10
11
12
13
14
--- test_ssl.py.bak 2018-08-02 05:19:12.000000000 -0400
+++ Lib/test/test_ssl.py 2018-10-09 16:07:47.721018740 -0400
@@ -3178,8 +3178,9 @@ else:
                 except ssl.SSLError as e:
                     stats = e
 
-                if expected is None and IS_OPENSSL_1_1:
-                    # OpenSSL 1.1.0 raises handshake error
+                if (expected is None and IS_OPENSSL_1_1
+                        and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)):
+                    # OpenSSL 1.1.0 to 1.1.0e raises handshake error
                     self.assertIsInstance(stats, ssl.SSLError)
                 else:
                     msg = "failed trying %s (s) and %s (c).\n" \
$ make test
 
省略
 
377 tests OK.
21 tests skipped:
    test_bz2 test_dbm_gnu test_dbm_ndbm test_devpoll test_idle
    test_kqueue test_lzma test_msilib test_ossaudiodev test_readline
    test_sqlite test_startfile test_tcl test_tix test_tk
    test_ttk_guionly test_ttk_textonly test_turtle test_winreg
    test_winsound test_zipfile64
Tests result: SUCCESS

対策 (番外編)

仮想環境を作って、そこに 検証したい環境2を完全に再現するのが実は正攻法かもしれません。

しかし Python には virtualenv があるので、そこまでしなくてもという気も。

  1. Ubuntu 18.04 のデフォルトは Python 3.6 なので 
  2. Ubuntu 16.04 等 
?

0 件のコメント: