在Lambda上使用M2Crypto的问题(在EC2上有效)

时间:2018-11-12 00:56:39

标签: aws-lambda m2crypto

我正在尝试在AWS Lambda中使用M2Crypto安装python函数。

我用Lambda AMI image旋转了一个EC2实例,将M2Crypto安装到virtualenv中,并且能够使我的功能在EC2上正常工作。

然后,我压缩了站点包并上传到Lambda。我收到此错误

  

无法导入模块“ epd_M2Crypto”:   /var/task/M2Crypto/_m2crypto.cpython-36m-x86_64-linux-gnu.so:符号   sk_deep_copy,文件中未定义的版本libcrypto.so.10   具有链接时间参考的libcrypto.so.10

存在类似的问题和提示herehere。我尝试在zip文件中上传有问题的lib(libcrypto.so.10),但仍然遇到相同的错误。我假设该错误意味着libcrypto.so.10的EC2版本(用于安装M2Crypto)与Lambda上的版本(我试图与其运行)不同,所以M2Crypto抱怨。

如果我查看openssl的版本,它们是不同的:

  • OpenSSL 1.0.0-fips 2010年3月29日(lambda版本)
  • OpenSSL 1.0.2k-fips 2017年1月26日(ec2版本)

我不认为答案是在ec2上降级openssl,因为1.0.0版本已过时(AWS应用了安全补丁,但该版本仍显示为1.0.0)。 (而且yum还没有这个旧版本)

这是我在EC2实例上使用的使它在EC2上运行的步骤:

$ sudo yum -y update
$ sudo yum -y install python36
$ sudo yum -y install python-virtualenv
$ sudo yum -y groupinstall "Development Tools"
$ sudo yum -y install python36-devel.x86_64
$ sudo yum -y install openssl-devel.x86_64

$ mkdir ~/forlambda
$ cd ~/forlambda
$ virtualenv -p python3 venv
$ source venv/bin/activate

$ cd ~
$ pip install M2Crypto -t ~/forlambda/venv/lib/python3.6/site-packages/

$ cd ~/forlambda/venv/lib/python3.6/site-packages/
$ (create python function that uses M2Crypto)
$ zip -r9 ~/forlambda/archive.zip .

然后将其添加到zip文件中

  • / usr / bin / openssl
  • /usr/lib64/libcrypto.so.10
  • /usr/lib64/libssl.so.10

并上传到Lambda,这就是我现在遇到的问题。

我需要做一些事情来使Lambda使用上载的zip中包含的libcrypto.so.10版本吗?

我的功能:

"""
Wrapper for M2Crypto
https://github.com/mcepl/M2Crypto
https://pypi.org/project/M2Crypto/
"""

from __future__ import print_function
from M2Crypto import RSA
import base64
import json

def decrypt_string(string_b64):
    rsa = RSA.load_key('private_key.pem')
    string_encrypted = base64.b64decode(string_b64)
    bytes = rsa.private_decrypt(string_encrypted, 1)
    string_plaintext = bytes.decode("utf-8")

    response = {
        's': string_plaintext,
        'status': "OK",
        'statuscode': 200
    };
    return response


def lambda_handler(event, context):

    response = ""
    action = event['action']

    if action == "decrypt":
        string_b64 = event['s']
        response = decrypt_string(string_b64)

    return response

4 个答案:

答案 0 :(得分:0)

首先,我在EC2实例上运行此命令,以确保在.zip文件中包含正确的.so文件:

$ ldd -v _m2crypto.cpython-36m-x86_64-linux-gnu.so 

ldd命令的输出(为简便起见进行了编辑):

    libssl.so.10 => /lib64/libssl.so.10 (0x00007fd5f1892000)
    libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007fd5f1433000)

基于上面的输出,我在.zip中包含了/lib64/libcrypto.so.10。

(在AWS Support的建议下)也在Lambda控制台的“环境变量”下,我添加了一个键“ LD_LIBRARY_PATH”,其值为“ / var / task”。

我不确定是否需要同时进行这两个更改来解决问题,但是它现在可以正常工作,并且经过三天的故障排除后,我怕触摸它以查看是否是使它起作用的一个或另一个。

答案 1 :(得分:0)

这也许太残酷了,但是可以使用LD_PRELOAD来强制使用您首选的OpenSSL库版本吗?

答案 2 :(得分:0)

AWS支持提供了一个解决方案,升级为使用可解决问题的Python 3.7:

  

我们的内部团队已确认问题出在Lambda的Python   运行。在少数情况下,当Lambda函数被   初始化后,Lambda无法链接到正确的OpenSSL   库-链接到Lambda自己的内置OpenSSL   二进制文件。

     

团队建议在Python3.7环境中尝试此操作,其中   此行为已得到修复。此外,python3.7是使用   较新的openssl 1.0.2,您不必在其中包含二进制文件   Lambda软件包。 ...仍然必须在其中包含OpenSSL二进制文件   包,无法使用默认库。

答案 3 :(得分:0)

AWS lambda在旧版本的Amazon Linux(amzn-ami-hvm-2017.03.1.20170812-x86_64-gp2)上运行代码,如官方文档中所述 https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html

因此,要运行依赖于共享库的代码,需要在同一环境中对其进行编译,以便可以正确链接。

在这种情况下,我通常要做的是使用docker容器创建virtualenv。然后可以将virtualenv与lambda代码打包在一起。

请注意,如果需要使用yum(在Docker容器中)安装任何东西,则必须使用与Amazon Linux版本相同的发行服务器:

yum --releasever=2017.03 install ...

virtualenv也可以使用EC2实例而不是docker容器来构建(尽管我发现docker方法更容易)。只要确保用于EC2的AMI与lambda使用的AMI相同即可。