我正在尝试在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
存在类似的问题和提示here和here。我尝试在zip文件中上传有问题的lib(libcrypto.so.10),但仍然遇到相同的错误。我假设该错误意味着libcrypto.so.10的EC2版本(用于安装M2Crypto)与Lambda上的版本(我试图与其运行)不同,所以M2Crypto抱怨。
如果我查看openssl的版本,它们是不同的:
我不认为答案是在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文件中
并上传到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
答案 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相同即可。