使用对象 Lambda 进行转换
MinIO 的对象 Lambda 使开发人员能够按需以编程方式转换对象。您可以根据用例需要转换对象,例如删除个人身份信息 (PII)、用来自其他来源的信息丰富数据或在格式之间转换。
概述
一个 对象 Lambda 处理程序 是一个小型代码模块,它转换对象的內容并返回结果。与 Amazon S3 对象 Lambda 函数 一样,您可以通过应用程序发出的 GET 请求触发 MinIO 对象 Lambda 处理程序函数。处理程序从 MinIO 检索请求的对象,对其进行转换,并将修改后的数据返回 MinIO,以发送到原始应用程序。原始对象保持不变。
每个处理程序都是一个独立的进程,多个处理程序可以转换相同的数据。这允许您将同一个对象用于不同的目的,而无需维护原始对象的多个版本。
对象 Lambda 处理程序
您可以使用任何能够发送和接收 HTTP 请求的语言编写处理程序函数。它必须能够
侦听 HTTP POST 请求。
使用 URL 检索原始对象。
返回转换后的內容和授权令牌。
创建函数
处理程序函数应执行以下步骤
从传入的 POST 请求中提取对象详细信息。
JSON 请求有效负载的
getObjectContext
属性包含有关原始对象的详细信息。要构建响应,您需要以下值值
说明
inputS3Url
原始对象的 预签名 URL。调用应用程序生成 URL 并将其发送到原始请求中。这允许处理程序访问原始对象,而无需通常所需的 MinIO 凭据。URL 的有效期为一个小时。
outputRoute
一个令牌,允许 MinIO 验证转换后对象的目的地。在
x-amz-request-route
标头中使用响应返回此值。outputToken
一个令牌,允许 MinIO 验证响应。在响应中的
x-amz-request-token
标头中返回此值。从 MinIO 检索原始对象。
使用预签名 URL 从 MinIO 部署中检索对象。对象的內容位于响应的正文中。
根据需要转换对象。
执行生成转换后对象所需的任何操作。由于调用应用程序正在等待响应,因此您可能希望避免潜在的长时间运行操作。
构建包含以下信息的响应
转换后的对象內容。
具有
outputRoute
令牌的x-amz-request-route
标头。具有
outputToken
令牌的x-amz-request-token
标头。
将响应返回给对象 Lambda。
MinIO 验证响应并将转换后的数据发送回原始调用应用程序。
响应标头
处理程序**必须**在适当的响应头中包含outputRoute
和 outputToken
值。 这使得 MinIO 可以正确验证来自处理程序的响应。
注册处理程序
要使 MinIO 能够调用处理程序,请将处理程序函数注册为具有以下MinIO 服务器对象 Lambda 环境变量 的 Webhook。
MINIO_LAMBDA_WEBHOOK_ENABLE_functionname
启用或禁用处理程序函数的对象 Lambda。 对于多个处理程序,请为每个函数名称设置此环境变量。
MINIO_LAMBDA_WEBHOOK_ENDPOINT_functionname
为处理程序函数注册一个端点。 对于多个处理程序,请为每个函数端点设置此环境变量。
MinIO 还支持以下环境变量,用于经过身份验证的 Webhook 端点
MINIO_LAMBDA_WEBHOOK_AUTH_TOKEN_functionanme
指定不透明字符串或 JWT 授权令牌,用于对 Webhook 进行身份验证。
MINIO_LAMBDA_WEBHOOK_CLIENT_CERT_functionname
指定用于对 Webhook 进行 mTLS 身份验证的客户端证书。
MINIO_LAMBDA_WEBHOOK_CLIENT_KEY_functionname
指定用于对 Webhook 进行 mTLS 身份验证的私钥。
重启 MinIO 以应用更改。
从应用程序触发
要从您的应用程序请求转换后的对象
连接到 MinIO 部署。
通过添加具有所需处理程序的 ARN 的
lambdaArn
参数,设置对象 Lambda 目标。为原始对象生成一个预签名 URL。
使用生成的 URL 检索转换后的对象。
MinIO 将请求发送到目标对象 Lambda 处理程序。 处理程序将转换后的内容返回到 MinIO,MinIO 验证响应并将其发送回应用程序。
示例
使用 Python、Go 和 curl
转换对象的内容
创建并注册对象 Lambda 处理程序。
创建要转换的存储桶和对象。
请求并显示转换后的对象内容。
先决条件
现有的 MinIO 部署
有效的 Python (3.8+) 和 Golang 开发环境
创建处理程序
示例处理程序是用 Python 编写的,它使用调用者生成的预签名 URL 检索目标对象。 处理程序随后转换对象的内容并返回新文本。 它使用 Flask Web 框架 和 Python 3.8+。
以下命令安装 Flask 和其他必需的依赖项
pip install flask requests
处理程序调用 swapcase()
来更改原始文本中每个字母的大小写。 然后它将结果发送回 MinIO,MinIO 将其返回给调用者。
from flask import Flask, request, abort, make_response
import requests
app = Flask(__name__)
@app.route('/', methods=['POST'])
def get_webhook():
if request.method == 'POST':
# Get the request event from the 'POST' call
event = request.json
# Get the object context
object_context = event["getObjectContext"]
# Get the presigned URL
# Used to fetch the original object from MinIO
s3_url = object_context["inputS3Url"]
# Extract the route and request tokens from the input context
request_route = object_context["outputRoute"]
request_token = object_context["outputToken"]
# Get the original S3 object using the presigned URL
r = requests.get(s3_url)
original_object = r.content.decode('utf-8')
# Transform the text in the object by swapping the case of each char
transformed_object = original_object.swapcase()
# Return the object back to Object Lambda, with required headers
# This sends the transformed data to MinIO
# and then to the user
resp = make_response(transformed_object, 200)
resp.headers['x-amz-request-route'] = request_route
resp.headers['x-amz-request-token'] = request_token
return resp
else:
abort(400)
if __name__ == '__main__':
app.run()
启动处理程序
使用以下命令在本地开发环境中启动处理程序
python lambda_handler.py
输出类似于以下内容
* Serving Flask app 'lambda_handler'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
启动 MinIO
处理程序运行后,使用 MINIO_LAMBDA_WEBHOOK_ENABLE
和 MINIO_LAMBDA_WEBHOOK_ENDPOINT
环境变量启动 MinIO,以将该函数注册到 MinIO。 要标识特定的对象 Lambda 处理程序,请将函数名称附加到环境变量名称的末尾。
以下命令在本地开发环境中启动 MinIO
MINIO_LAMBDA_WEBHOOK_ENABLE_myfunction=on MINIO_LAMBDA_WEBHOOK_ENDPOINT_myfunction=http://127.0.0.1:5000 minio server /data
将 myfunction
替换为您处理程序函数的名称,将 /data
替换为本地部署的 MinIO 目录的位置。 输出类似于以下内容
MinIO Object Storage Server
Copyright: 2015-2023 MinIO, Inc.
License: GNU AGPLv3 <https://www.gnu.org/licenses/agpl-3.0.html>
Version: RELEASE.2023-03-24T21-41-23Z (go1.19.7 linux/arm64)
Status: 1 Online, 0 Offline.
API: http://192.168.64.21:9000 http://127.0.0.1:9000
RootUser: minioadmin
RootPass: minioadmin
Object Lambda ARNs: arn:minio:s3-object-lambda::myfunction:webhook
测试处理程序
要测试 Lambda 处理程序函数,首先创建一个要转换的对象。 然后使用 curl
(在本例中)调用处理程序,使用来自 Go 函数的预签名 URL。
为处理程序创建要转换的存储桶和对象。
mc alias set myminio/ http://127.0.0.1:9000 minioadmin minioadmin mc mb myminio/myfunctionbucket cat > testobject << EOF Hello, World! EOF mc cp testobject myminio/myfunctionbucket/
调用处理程序
以下 Go 代码使用 MinIO Go SDK 生成预签名 URL 并将其打印到
stdout
。package main import ( "context" "log" "net/url" "time" "fmt" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" ) func main() { // Connect to the MinIO deployment s3Client, err := minio.New("localhost:9000", &minio.Options{ Creds: credentials.NewStaticV4("my_admin_user", "my_admin_password", ""), Secure: false, }) if err != nil { log.Fatalln(err) } // Set the Lambda function target using its ARN reqParams := make(url.Values) reqParams.Set("lambdaArn", "arn:minio:s3-object-lambda::myfunction:webhook") // Generate a presigned url to access the original object presignedURL, err := s3Client.PresignedGetObject(context.Background(), "myfunctionbucket", "testobject", time.Duration(1000)*time.Second, reqParams) if err != nil { log.Fatalln(err) } // Print the URL to stdout fmt.Println(presignedURL) }
在上面的代码中,替换以下值
将
my_admin_user
和my_admin_password
替换为 MinIO 部署的用户凭据。将
myfunction
替换为在MINIO_LAMBDA_WEBHOOK_ENABLE
和MINIO_LAMBDA_WEBHOOK_ENDPOINT
环境变量中设置的相同函数名称。
要检索转换后的对象,请使用
curl
执行 Go 代码以生成 GET 请求curl -v $(go run presigned.go)
curl
运行 Go 代码,然后使用对预签名 URL 的 GET 请求检索对象。 输出类似于以下内容* Trying 127.0.0.1:9000... * Connected to localhost (127.0.0.1) port 9000 (#0) > GET /myfunctionbucket/testobject?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20230406%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230406T184749Z&X-Amz-Expires=1000&X-Amz-SignedHeaders=host&lambdaArn=arn%3Aminio%3As3-object-lambda%3A%3Amyfunction%3Awebhook&X-Amz-Signature=68fe7e03929a7c0da38255121b2ae09c302840c06654d1b79d7907d942f69915 HTTP/1.1 > Host: localhost:9000 > User-Agent: curl/7.81.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Content-Security-Policy: block-all-mixed-content < Strict-Transport-Security: max-age=31536000; includeSubDomains < Vary: Origin < Vary: Accept-Encoding < X-Amz-Id-2: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 < X-Amz-Request-Id: 17536CF16130630E < X-Content-Type-Options: nosniff < X-Xss-Protection: 1; mode=block < Date: Thu, 06 Apr 2023 18:47:49 GMT < Content-Length: 14 < Content-Type: text/plain; charset=utf-8 < hELLO, wORLD! * Connection #0 to host localhost left intact