x**3な人生

基本的にはメモ

Cryptography_HAS_SSL_ST

はじめに

Ubuntu16.04でovsをコンパイルしようとしてmakeではまったので、場当たり的に対処したときのメモ。

pythonのOpenSSLの中でCryptography_HAS_SSL_STが定義されていないためAttributeErrorでこける。 Ubuntuが古いので、libraryも古かったというのが原因の模様。

本当は python - Pip Error : 'module' object has no attribute 'Cryptography_HAS_SSL_ST' - Stack Overflow にあるようにパッケージマネージャーで綺麗に入れ直した方がよいはず。

環境など

  • Ubuntu 16.04
  • python2.7
  • openvswitch-2.10.1

ovsはgithubからcloneしたので正しくは以下のコミット時点。

commit b1331295eaada5bc0e3bcd7e3b964003af3273d6
Author: Ilya Maximets <i.maximets@samsung.com>
Date:   Tue Dec 11 17:34:17 2018 +0300

    cirrus: Add Cirrus CI integration for FreeBSD build

内容

このへんの手順をみてmakeまで進めると、OpenSSLのところでエラーが出る。

Open vSwitch on Linux, FreeBSD and NetBSD — Open vSwitch 2.10.90 documentation

...
  File "/usr/local/lib/python2.7/dist-packages/OpenSSL/SSL.py", line 194, in <module>
    if _lib.Cryptography_HAS_SSL_ST:
AttributeError: 'module' object has no attribute 'Cryptography_HAS_SSL_ST'

replでimportしても確かにエラーになる。

>>> import OpenSSL
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/OpenSSL/__init__.py", line 8, in <module>
    from OpenSSL import crypto, SSL
  File "/usr/local/lib/python2.7/dist-packages/OpenSSL/SSL.py", line 194, in <module>
    if _lib.Cryptography_HAS_SSL_ST:
AttributeError: 'module' object has no attribute 'Cryptography_HAS_SSL_ST'

SSL.pyの内容を見ると、_utilというモジュールの中で_lib.Cryptography_HAS_SSL_STが定義されていることを期待している。

from OpenSSL._util import (
    UNSPECIFIED as _UNSPECIFIED,
    exception_from_error_queue as _exception_from_error_queue,
    ffi as _ffi,
    lib as _lib,
...

# 194行目
if _lib.Cryptography_HAS_SSL_ST:
    SSL_ST_INIT = _lib.SSL_ST_INIT
    SSL_ST_BEFORE = _lib.SSL_ST_BEFORE
    SSL_ST_OK = _lib.SSL_ST_OK
    SSL_ST_RENEGOTIATE = _lib.SSL_ST_RENEGOTIATE
    __all__.extend([
        'SSL_ST_INIT',
        'SSL_ST_BEFORE',
        'SSL_ST_OK',
        'SSL_ST_RENEGOTIATE',
    ])

確かに_util.pyというのがある。

$ ls /usr/local/lib/python2.7/dist-packages/OpenSSL/
SSL.py   __init__.py   _util.py   crypto.py   debug.py   rand.py   tsafe.py   version.py
SSL.pyc  __init__.pyc  _util.pyc  crypto.pyc  debug.pyc  rand.pyc  tsafe.pyc  version.pyc

ので開いてみると最初の方でBinding.liblibとして参照させている。

# 6行目
from cryptography.hazmat.bindings.openssl.binding import Binding


binding = Binding()
binding.init_static_locks()
ffi = binding.ffi
lib = binding.lib

cryptographyというのは

GitHub - pyca/cryptography: cryptography is a package designed to expose cryptographic primitives and recipes to Python developers.

のことみたいで、ソースコードの中身を見ると確かにCryptography_HAS_SSL_STが定義されている。具体的にはBinding()のクラスメソッドから_conditional.pyCONDITIONAL_NAMESを参照していて、Cryptography_HAS_SSL_STの実体は単にリストを返すメソッドであることが分かる。

# cryptography/src/cryptography/hazmat/bindings/openssl/binding.py

from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES
...

class Binding(object):
    """
    OpenSSL API wrapper.
    """
    lib = None
    ffi = ffi
...

    @classmethod
    def _ensure_ffi_initialized(cls):
        with cls._init_lock:
            if not cls._lib_loaded:
                cls.lib = build_conditional_library(lib, CONDITIONAL_NAMES)
...
# cryptography/src/cryptography/hazmat/bindings/openssl/_conditional.py

CONDITIONAL_NAMES = {
    "Cryptography_HAS_EC2M": cryptography_has_ec2m,
    "Cryptography_HAS_EC_1_0_2": cryptography_has_ec_1_0_2,
   ...
   "Cryptography_HAS_SSL_ST": cryptography_has_ssl_st,
   ...
}
...

def cryptography_has_ssl_st():
    return [
        "SSL_ST_BEFORE",
        "SSL_ST_OK",
        "SSL_ST_INIT",
        "SSL_ST_RENEGOTIATE",
    ]

とりあえずここまで分かってある程度満足したのと、ovsでSSLあたりの機能を使う予定は無いので、_util.pyの最初に無理矢理lib.Cryptography_HAS_SSL_STの定義を書くことでコンパイル終了。そのあと消したのでovsからこの辺を使うときはエラーになるはず。

# _util.py

binding = Binding()
binding.init_static_locks()
ffi = binding.ffi
lib = binding.lib

# これ
lib.Cryptography_HAS_SSL_ST = False

以上