AWS Lamda:ClientError:调用 HeadObject 操作时发生错误(403):禁止

Posted

技术标签:

【中文标题】AWS Lamda:ClientError:调用 HeadObject 操作时发生错误(403):禁止【英文标题】:AWS Lamda: ClientError: An error occurred (403) when calling the HeadObject operation: Forbidden 【发布时间】:2021-05-06 13:00:19 【问题描述】:

我是AWS 的新手。我正在尝试使用以下AWS 服务处理xlsx 文件。 S3 Bucket,用来存储文件,SNS 订阅AWS Lamda 写在Python 中的函数。所以这是我的一段代码:

import json
import boto3
import pandas as pd
import os, tempfile
import sys
import uuid
from urllib.parse import unquote_plus

s3_client = boto3.client('s3')

def lambda_handler(event, context):
    print('coming here')
    message = event['Records'][0]['Sns']['Message']
    bucket = 'bucket1'
    newbucket = 'bucket2'
    jmessage = json.loads(message)
    key = unquote_plus(jmessage["Records"][0]['s3']['object']['key'])
    directory_name = tempfile.mkdtemp()
    download_path = os.path.join(directory_name, 'EXAMPLE2.xlsx')
    print(download_path)
    newkey= 'cleaned.csv'
    upload_path = os.path.join(directory_name, newkey)
    s3_client.download_file(bucket, key, download_path)
    df = pd.read_Excel(download_path, skiprows=3)
    header2 = ['K', 'GEN STATUS']
    df.to_csv(upload_path, columns=header2, index=False)
    s3_client.upload_file(upload_path, newbucket, newkey)

    sns = boto3.client('sns')
    response = sns.publish(
        TopicArn='arn:aws:lambda:us-east-1:<id>:function:DataClean',
        Message='Data is cleaned and save into bucket Cleaned-data. Auto data ingestion is running.'
    )
    return 
        'statusCode': 200,
        'body': json.dumps('Done with cleansing!!')
    

当我将xlsx 文件上传到s3 存储桶时,SNS 会触发上述Lambda 函数,但会呈现以下错误:

[ERROR] ClientError: 调用时发生错误 (403) HeadObject 操作:Forbidden Traceback(最近一次调用最后一次): 文件“/var/task/lambda_function.py”,第 23 行,在 lambda_handler s3_client.download_file(bucket, key, download_path)

这是完整的日志:

2021-02-02T12:16:34.838+05:00


[ERROR] ClientError: An error occurred (403) when calling the HeadObject operation: Forbidden
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 23, in lambda_handler
    s3_client.download_file(bucket, key, download_path)
  File "/var/runtime/boto3/s3/inject.py", line 172, in download_file
    extra_args=ExtraArgs, callback=Callback)
  File "/var/runtime/boto3/s3/transfer.py", line 307, in download_file
    future.result()
  File "/var/runtime/s3transfer/futures.py", line 106, in result
    return self._coordinator.result()
  File "/var/runtime/s3transfer/futures.py", line 265, in result
    raise self._exception
  File "/var/runtime/s3transfer/tasks.py", line 255, in _main
    self._submit(transfer_future=transfer_future, **kwargs)
  File "/var/runtime/s3transfer/download.py", line 343, in _submit
    **transfer_future.meta.call_args.extra_args
  File "/var/runtime/botocore/client.py", line 357, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/var/runtime/botocore/client.py", line 676, in _make_api_call
    raise error_class(parsed_response, operation_name)

这就是我的存储桶策略的样子:


    "Version": "2012-10-17",
    "Statement": [
        
            "Effect": "Allow",
            "Principal": 
                "AWS": "arn:aws:iam::<id>:root"
            ,
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::bucket1/*"
        
    ]

那么这里出了什么问题?

【问题讨论】:

【参考方案1】:

您的 lambda 角色无权访问 S3 存储桶来下载对象。

Tutorial: Using AWS Lambda with Amazon S3


    "Version": "2012-10-17",
    "Statement": [
        
            "Effect": "Allow",
            "Action": [
                "logs:PutLogEvents",
                "logs:CreateLogGroup",
                "logs:CreateLogStream"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        ,
        
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::bucket1/*"
        ,
        
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::bucket2/*"
        
    ]
         
        

NOTE:确保(IAM 角色和您的 S3 存储桶策略)都允许您的 lambda。

Identity-based policies and resource-based policies

【讨论】:

如何授予对 Lambda 的访问权限以下载对象?我是 AWS 新手,请多多包涵。我还使用 s3 存储桶策略编辑了问题。 @Saani 我将文档链接附加到答案中,看看。我可以帮你解决这个问题。 @Saani 在您的政策中允许使用一个存储桶,但在代码中您有两个存储桶 bucket = 'bucket1' newbucket = 'bucket2' @Saani 如果这对您有用,您是否可以将此问题标记为已解决。这有助于社区和将来偶然发现这个问题的任何人。 是的,我会继续尝试实施解决方案。仍然得到同样的错误。我尝试按照您建议的教程进行操作。

以上是关于AWS Lamda:ClientError:调用 HeadObject 操作时发生错误(403):禁止的主要内容,如果未能解决你的问题,请参考以下文章

使用 boto3 从 AWS S3 Bucket 下载文件会导致 ClientError: An error occurred (403): Forbidden

javascript 用于Slack消息的AWS CodeDeploy Lamda格式化程序 - node.js

ClientError:调用 HeadObject 操作时发生错误(403):尝试跨帐户复制时禁止

botocore.exceptions.ClientError:调用PutObject操作时发生错误(AccessDenied):访问被拒绝

将 SSM:GetParameter 添加到 AWS EC2 实例

调用client.request_spot_instances方法时抛出AWS Boto3 BASE64编码错误