在 Lambda 上 运行 时,Textract 无法从 S3 读取对象

Textract cannot read object from S3 when running on Lambda

我有一个简单的 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 环境中会出现什么问题。

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

我混淆了角色。本例涉及两个角色:Lambda 角色和运行 Textract 的角色。我错误地认为 Textract 角色用于其完整执行(Textract 角色具有完整的 S3 访问权限),但它仅用于发送 SNS 通知。但事实上,textract 在分配给 Lambda 的相同角色下运行,而 Lambda 没有 S3 访问权限。为 Lambda 角色添加 S3 访问权限后,一切正常。

谢谢大家!