通过boto3更新S3对象元数据时出现签名错误



我有一个lambda函数,它从S3事件中获取S3对象,并用自定义元数据更新它。

这是boto3脚本:

import json
import boto3
s3 = boto3.resource('s3')
def lambda_handler(event, context):
key = event['Records'][0]['s3']['object']['key']
key_name = key.split('/')
bucket = event['Records'][0]['s3']['bucket']['name']
print(key)
print(bucket)
s3_object = s3.Object(bucket, key)
s3_object.metadata.update({'Cache-Control':'no-cache'})
s3_object.copy_from(CopySource={'Bucket':bucket, 'Key':key}, Metadata=s3_object.metadata, MetadataDirective='REPLACE')

当我运行脚本时,它会给我以下错误:

调用CopyObject操作时发生错误(SignatureDoesNotMatch(:我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法。:客户端错误

(注意:我已经对lambda函数角色给予了足够的权限(

我需要在此处创建签名吗?

对象的Key中可能有一些奇怪的字符。

以下是一些对我有用的稍微修改过的代码:

import boto3
import urllib
s3 = boto3.resource('s3')
def lambda_handler(event, context):
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'])
s3_object = s3.Object(bucket, key)
s3_object.metadata.update({'Cache-Control':'no-cache'})
s3_object.copy_from(CopySource={'Bucket':bucket, 'Key':key}, Metadata=s3_object.metadata, MetadataDirective='REPLACE')
约翰·罗滕斯坦的答案有效,但只有一次。运行同一个脚本两次会重现OP的错误。

我相信这与为什么有关:

用户定义的元数据是一组键值对。AmazonS3以小写形式存储用户定义的元数据密钥。

https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingMetadata.html

请注意,尽管Amazon将密钥存储为小写,但OP使用的是大写。改变";高速缓存控制";到小写";高速缓存控制";将允许您更新对象上的元数据;高速缓存控制";已是元数据项。

我已经测试了对大小写敏感的问题,能够在不使用密钥大写的情况下使事情正常工作,并在重新引入密钥大写时重现问题。

AWS的客户端和API后端的签名计算方式似乎存在差异。只有当元数据条目预先存在于对象上时,资本化问题才会表现出来。这可能需要向AWS提出关于boto3库的罚单。

最新更新