文档

使用对象 Lambda 进行转换

MinIO 的对象 Lambda 使开发人员能够按需以编程方式转换对象。您可以根据用例需要转换对象,例如对个人身份信息 (PII) 进行脱敏处理、使用来自其他来源的信息丰富数据或在格式之间进行转换。

概述

一个 对象 Lambda 处理程序 是一个小型代码模块,它转换对象的内容并返回结果。与 Amazon S3 对象 Lambda 函数类似,您可以通过应用程序发出的 GET 请求来触发 MinIO 对象 Lambda 处理程序函数。该处理程序从 MinIO 检索请求的对象,对其进行转换,并将修改后的数据返回给 MinIO,再由 MinIO 发送给原始应用程序。原始对象保持不变。

每个处理程序都是一个独立的进程,多个处理程序可以转换相同的数据。这使您可以将同一对象用于不同目的,而无需维护原始对象的不同版本。

对象 Lambda 处理程序

您可以使用任何能够发送和接收 HTTP 请求的语言编写处理程序函数。它必须能够:

  • 监听 HTTP POST 请求。

  • 使用 URL 检索原始对象。

  • 返回转换后的内容和授权令牌。

创建一个函数

处理程序函数应执行以下步骤:

  1. 从传入的 POST 请求中提取对象详细信息。

    JSON 请求负载的 getObjectContext 属性包含有关原始对象的详细信息。要构造响应,您需要以下值:

    描述

    inputS3Url

    原始对象的预签名 URL。调用应用程序生成该 URL 并在原始请求中发送它。这允许处理程序访问原始对象,而无需通常需要的 MinIO 凭据。该 URL 有效期为一小时。

    outputRoute

    一个令牌,允许 MinIO 验证转换后对象的目标。在响应的 x-amz-request-route 标头中返回此值。

    outputToken

    一个令牌,允许 MinIO 验证响应。在响应的 x-amz-request-token 标头中返回此值。

  2. 从 MinIO 检索原始对象。

    使用预签名 URL 从 MinIO 部署中检索对象。对象的内容位于响应的正文中。

  3. 根据需要转换对象。

    执行生成转换后对象所需的任何操作。由于调用应用程序正在等待响应,您可能希望避免可能长时间运行的操作。

  4. 构造一个包含以下信息的响应:

    • 转换后的对象内容。

    • 一个带有 outputRoute 令牌的 x-amz-request-route 标头。

    • 一个带有 outputToken 令牌的 x-amz-request-token 标头。

  5. 将响应返回给对象 Lambda。

    MinIO 验证响应并将转换后的数据发送回原始调用应用程序。

响应标头

处理程序必须在相应的响应标头中包含 outputRouteoutputToken 值。这使得 MinIO 能够正确验证来自处理程序的响应。

注册处理程序

要使 MinIO 能够调用处理程序,请使用以下 MinIO 服务器对象 Lambda 环境变量 将处理程序函数注册为 webhook:

MINIO_LAMBDA_WEBHOOK_ENABLE_functionname

为一个处理程序函数启用或禁用对象 Lambda。对于多个处理程序,为每个函数名称设置此环境变量。

MINIO_LAMBDA_WEBHOOK_ENDPOINT_functionname

为处理程序函数注册一个端点。对于多个处理程序,为每个函数端点设置此环境变量。

MinIO 还支持以下用于经过身份验证的 webhook 端点的环境变量:

MINIO_LAMBDA_WEBHOOK_AUTH_TOKEN_functionanme

指定用于向 webhook 进行身份验证的不透明字符串或 JWT 授权令牌。

MINIO_LAMBDA_WEBHOOK_CLIENT_CERT_functionname

指定用于向 webhook 进行 mTLS 身份验证的客户端证书。

MINIO_LAMBDA_WEBHOOK_CLIENT_KEY_functionname

指定用于向 webhook 进行 mTLS 身份验证的私钥。

重启 MinIO 以应用更改。

或者,使用 MinIO 客户端 命令行工具配置对象 Lambda。有关更多信息,请参阅 对象 Lambda 函数设置

从应用程序触发

要从您的应用程序请求转换后的对象:

  1. 连接到 MinIO 部署。

  2. 通过添加一个 lambdaArn 参数并附上所需处理程序的 ARN 来设置对象 Lambda 目标。

  3. 为原始对象生成一个预签名 URL

  4. 使用生成的 URL 检索转换后的对象。

    MinIO 将请求发送到目标对象 Lambda 处理程序。处理程序将转换后的内容返回给 MinIO,MinIO 验证响应并将其发送回应用程序。

示例

使用 Python、Go 和 curl 转换对象的内容:

  • 创建并注册一个对象 Lambda 处理程序。

  • 创建一个存储桶和一个要转换的对象。

  • 请求并显示转换后的对象内容。

先决条件

  • 一个已有的 MinIO 部署

  • 可用的 Python (3.8+) 和 Golang 开发环境

  • MinIO Go SDK

创建处理程序

这个用 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_ENABLEMINIO_LAMBDA_WEBHOOK_ENDPOINT 环境变量启动 MinIO,以将该函数注册到 MinIO。要标识特定的对象 Lambda 处理程序,请将函数名称附加到环境变量名称的末尾。

以下命令在您的本地开发环境中启动 MinIO:

MINIO_LAMBDA_WEBHOOK_ENABLE_myfunction=on MINIO_LAMBDA_WEBHOOK_ENDPOINT_myfunction=https://:5000 minio server /data

myfunction 替换为您的处理程序函数名称,将 /data 替换为您的本地部署的 MinIO 目录位置。输出类似于以下内容:

MinIO Object Storage Server
Copyright: 2015-2023 MinIO, Inc.
License: GNU AGPLv3 <https://gnu.ac.cn/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 来调用该处理程序。

  1. 创建一个存储桶和一个对象供处理程序转换。

    mc alias set myminio/ https://:9000 minioadmin minioadmin
    mc mb myminio/myfunctionbucket
    cat > testobject << EOF
    Hello, World!
    EOF
    mc cp testobject myminio/myfunctionbucket/
    
  2. 调用处理程序

    以下 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_usermy_admin_password 替换为 MinIO 部署的用户凭据。

    • myfunction 替换为在 MINIO_LAMBDA_WEBHOOK_ENABLEMINIO_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
    
English 中文