首页 > 解决方案 > 在 Lambda 上运行时,Textract 无法从 S3 读取对象

问题描述

我有一个简单的 Lambda 函数,当文件上传到 S3 时应该调用 Textract。但是,当我从桌面运行 Lambda 函数时,对 Textract 的调用可以正常工作,而当我从 Lambda 环境中运行完全相同的代码时,对 Textract 的调用将无法正常工作。

这是 Lambda 代码:

import os
import boto3

TEXTRACT_CLIENT = boto3.client('textract', region_name=os.environ['REGION'])


def lambda_handler(event, context):
    event_source = event['Records'][0]['s3']

    textract_ticket = TEXTRACT_CLIENT.start_document_analysis(
        DocumentLocation={
            'S3Object': {
                'Bucket': os.environ['REQUESTS_BUCKET'],
                'Name': event_source['object']['key']

            }
        },
        FeatureTypes=["TABLES", "FORMS"],
        NotificationChannel={
            'RoleArn': os.environ['TEXTRACT_ROLE_ARN'],
            'SNSTopicArn': os.environ['SNS_TOPIC_ARN']
        },
        OutputConfig={
            'S3Bucket': os.environ['RESULTS_BUCKET']
        }
    )

    return {
        'statusCode': 200,
        'JobId': textract_ticket['JobId']
    }

代码没什么特别的。我对 Lambda 环境和本地机器中的所有环境变量使用完全相同的值。在这两种情况下,我都使用相同的事件,指向相同的 S3 对象:

{
  "Records": [
    {
      "eventVersion": "2.0",
      "eventSource": "aws:s3",
      "awsRegion": "us-east-1",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
        "principalId": "EXAMPLE"
      },
      "requestParameters": {
        "sourceIPAddress": "127.0.0.1"
      },
      "responseElements": {
        "x-amz-request-id": "EXAMPLE123456789",
        "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "testConfigRule",
        "bucket": {
          "name": "my-bucket",
          "ownerIdentity": {
            "principalId": "EXAMPLE"
          },
          "arn": "arn:aws:s3:::example-bucket"
        },
        "object": {
          "key": "35264254-7aa6-4f24-815a-f73e1671f151.pdf",
          "size": 1024,
          "eTag": "0123456789abcdef0123456789abcdef",
          "sequencer": "0A1B2C3D4E5F678901"
        }
      }
    }
  ]
}

奇怪的是,当从我的桌面调用时,所有这些都会成功执行,但是当我从 Lambda 运行时,我得到:

{
  "errorMessage": "An error occurred (InvalidS3ObjectException) when calling the StartDocumentAnalysis operation: Unable to get object metadata from S3. Check object key, region and/or access permissions.",
  "errorType": "InvalidS3ObjectException",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 10, in lambda_handler\n    textract_ticket = TEXTRACT_CLIENT.start_document_analysis(\n",
    "  File \"/var/runtime/botocore/client.py\", line 386, in _api_call\n    return self._make_api_call(operation_name, kwargs)\n",
    "  File \"/var/runtime/botocore/client.py\", line 705, in _make_api_call\n    raise error_class(parsed_response, operation_name)\n"
  ]
}

我在这里错过了什么吗?我无法弄清楚 Lambda 环境中可能出现的问题。

标签: amazon-web-servicesamazon-s3aws-lambdaamazon-textract

解决方案


@Ronan Cunningham 和 @stijndepestel 的直觉都是正确的。

我对角色感到困惑。此示例涉及两个角色:Lambda 角色和运行 Textract 的角色。我错误地认为 Textract 角色用于其完整执行(Textract 角色具有完整的 S3 访问权限),但它仅用于发送 SNS 通知。但实际上 textract 在分配给 Lambda 的同一角色下运行,后者没有 S3 访问权限。将 S3 访问权限添加到 Lambda 角色后,一切都按预期工作。

感谢你们!


推荐阅读