如何在AWS Lambda函数中使用GnuPG

3
我是一名有用的助手,可以为您翻译文本。

我有一个本地的Python代码,用GPG加密文件。我需要将其转换为AWS Lambda,一旦文件被添加到触发此Lambda的AWS S3中。

我的本地代码

import os
import os.path
import time
import sys
gpg = gnupg.GPG(gnupghome='/home/ec2-user/.gnupg')

path = '/home/ec2-user/2021/05/28/'
ptfile = sys.argv[1]

with open(path + ptfile, 'rb')as f:
        status = gpg.encrypt_file(f, recipients=['user@email.com'], output=path + ptfile + ".gpg")

print(status.ok)
print(status.stderr)

当我执行python3 encrypt.py file.csv时,它的效果非常好,结果是file.csv.gpg
我正在尝试将其移植到AWS Lambda,并在上传到S3的file.csv文件时调用。
import json
import urllib.parse
import boto3
import gnupg
import os
import os.path
import time

s3 = boto3.client('s3')

def lambda_handler(event, context):
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    
    try:
        gpg = gnupg.GPG(gnupghome='/.gnupg')
        ind = key.rfind('/')
        ptfile = key[ind + 1:]
        with open(ptfile, 'rb')as f:
            status = gpg.encrypt_file(f, recipients=['email@company.com'], output= ptfile + ".gpg")
        print(status.ok)
        print(status.stderr)

我的AWS Lambda代码压缩包在AWS中创建了一个文件夹结构。 在这里输入图片描述 我在运行时看到的错误是[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'gnupg' Traceback (most recent call last):

首先,您需要使用.zip文件归档在AWS Lambda上部署Python Lambda函数,以包含gnupg库。进程所需的任何文件(例如私钥)都需要包含在Zip中或从S3下载。 - John Rotenstein
@JohnRotenstein 我更新了代码结构,发现运行时出现了错误。 - Some Java Guy
1
gnupg 库不是标准的 Python 库。它需要被包含在 部署包 中,以便 Python 可以使用该库(而不仅仅是您的.gnupg目录)。这与尝试在没有安装 gnupg 的新计算机上运行程序的情况相同--您需要使用 pip 安装它。对于 Lambda 函数,您需要在虚拟环境中进行该安装,然后按照我之前的评论中提供的说明将结果打包成 zip 文件。 - John Rotenstein
6个回答

6

您可以从 GnuPG 1.4源码 中创建一个适用于 AWS Lambda 上 python-gnupg 的 gpg 二进制文件。 您需要:

  • GCC 和相关工具(在 Amazon Linux 2 上运行sudo yum install -y gcc make glibc-static
  • pip
  • zip

在下载 GnuPG 源码包并验证其签名后,使用以下命令构建二进制文件:

$ tar xjf gnupg-1.4.23.tar.bz2
$ cd gnupg-1.4.23
$ ./configure
$ make CFLAGS='-static'
$ cp g10/gpg /path/to/your/lambda/

您还需要从python-gnupg中获取gnupg.py模块,可以使用pip获取:

$ cd /path/to/your/lambda/
$ pip install -t . python-gnupg

您的Lambda函数源代码结构现在将看起来像这样:
.
├── gnupg.py
├── gpg
└── lambda_function.py

更新你的函数,将 gpg 二进制文件的位置传递给 python-gnupg 构造器:

gpg = gnupg.GPG(gnupghome='/.gnupg', gpgbinary='./gpg')

使用 zip 命令打包 Lambda 函数:

$ chmod o+r gnupg.py lambda_function.py 
$ chmod o+rx gpg
$ zip lambda_function.zip gnupg.py gpg lambda_function.py 

嗨Daniel,我尝试了上面的方法,但是一直得到以下错误:raise OSError(msg)g.py",第945行的__init__y='./gpg':无法运行 gpg(./gpg)-可能不可用。 END我正在构建AWS Lambda函数,在Python Notebook中工作良好。 - Swapnil
我想知道是否可以只下载GnuPG的二进制文件,而不是从源代码编译。 - undefined

2
由于在Python中使用gpg需要一些系统依赖,例如 gnupg 本身,因此您需要使用容器运行时环境来构建Lambda代码:https://docs.aws.amazon.com/lambda/latest/dg/lambda-images.html 使用Docker将允许您安装底层的系统依赖项,并导入您的密钥。
Dockerfile如下所示:
FROM public.ecr.aws/lambda/python:3.8

RUN apt-get update && apt-get install gnupg

# copy handler file
COPY app.py <path-to-keys> ./

# Add keys to gpg
RUN gpg --import <path-to-private-key>
RUN gpg --import <path-to-public-key>

# Install dependencies and open port
RUN pip3 install -r requirements.txt

CMD ["app.lambda_handler"]  

app.py将是您的lambda代码。 除主要的lambda处理程序外,可以自由复制任何必要的文件。

构建并上传容器映像后,Lambda现在可以使用该映像(包括其所有依赖项)。 Lambda代码将在容器化环境中运行,其中包含gnupg和导入的密钥。

资源:

https://docs.aws.amazon.com/lambda/latest/dg/python-image.html https://docs.aws.amazon.com/lambda/latest/dg/lambda-images.html https://medium.com/@julianespinel/how-to-use-python-gnupg-to-decrypt-a-file-into-a-docker-container-8c4fb05a0593


1
最好的方法是为你的Python Lambda添加一个Lambda Layer
你需要创建一个虚拟环境,在其中执行pip install gnupg,然后将所有已安装的Python包打包成zip文件,上传至AWS作为Lambda Layer。这个Lambda Layer可以在所有需要gnupg的Lambda函数中使用。要创建Lambda Layer,你基本上需要执行以下操作:
python3.9 -m venv my_venv
 ./my_venv/bin/pip3.9 install gnupg
cp -r ./my_venv/lib/python3.9/site-packages/ python
zip -r lambda_layer.zip python

您需要确保Lambda函数中使用的Python版本与上述版本匹配。

如果您不想使用层,还可以执行以下操作:

zip -r lambda_layer.zip ./.gnupg
zip lambda_layer.zip lambda_funtion.py

您将获得一个zip文件,可用作lambda部署包


1

gpg现在已经安装在public.ecr.aws/lambda/python:3.8中。

然而,尽管如此,似乎Lambda中并没有可用的gpg。因此,您仍需要将gpg可执行文件放入Lambda环境中。

我使用了一个docker镜像来完成这个任务。

我的Dockerfile只有:

FROM public.ecr.aws/lambda/python:3.8

COPY .venv/lib/python3.8/site-packages/ ./
COPY test_gpg.py .

CMD ["test_gpg.lambda_handler"]

.venv 是包含我所需Python软件包的虚拟环境的目录。


1

最终我使用了一个Dockerfile镜像,因为该库已经在AWS提供的Amazon Linux或Lambda Python基础镜像之一中可用,您可以在此处找到https://gallery.ecr.aws/lambda/python(在标签图像选项卡中,您将根据您的要求找到所有所需的Python版本)。

您需要在开发环境中创建以下3个文件:

  • Dockerfile
  • requirements.txt
  • lambda脚本

requirements.txt包含python-gnupg以进行导入以及根据您的要求的所有其他库:

boto3==1.15.11            # via -r requirements.in
urllib3==1.25.10          # via botocore
python-gnupg==0.5.0       # required for gpg encryption

这是 Dockerfile 文件:

# Python 3.9 lambda base image
FROM public.ecr.aws/lambda/python:3.9

# Install pip-tools so we can manage requirements
RUN yum install python-pip -y

# Copy requirements.txt file locally
COPY requirements.txt ./

# Install dependencies into current directory
RUN python3.9 -m pip install -r requirements.txt

# Copy lambda file locally
COPY s3_to_sftp_batch.py .

# Define handler file name
CMD ["s3_to_sftp_batch.on_trigger_event_test"]

然后在您的 lambda 代码中添加:

# define library path to point system libraries
os.environ["LD_LIBRARY_PATH"] = "/usr/bin/"

# create instance of GPG class and specify path that contains gpg binary
gpg = gnupg.GPG(gnupghome='/tmp', gpgbinary='/usr/bin/gpg')

保存这些文件,然后转到 AWS ECR 并创建一个私有的仓库,然后进入仓库,在右上角点击 查看推送命令 并运行它们以将您的镜像推送到 AWS。 最后,使用容器镜像创建 Lambda 函数。


0

Python-gnupg软件包要求您安装可工作的gpg可执行文件,正如他们官方文档中部署要求所述;我还没有找到一种从lambda访问gpg可执行文件的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接