使用 lambda 函数生成时,S3 预签名 url 不起作用

问题描述 投票:0回答:1

我从这个Boto3 S3示例中获得的以下代码,如果在本地启动以及通过调用API网关执行的lambda函数都可以正常工作:

   s3_client = boto3.client('s3')
   response = s3_client.generate_presigned_post("mybucket",
                                                "myfile.jpg"
                                                ExpiresIn=3600)

在这两种情况下,它都会返回如下响应:

{
    "url": "https://mybucket.s3.amazonaws.com/",
    "fields": {
        "key": "myfile.jpg",
        "AWSAccessKeyId": "-omissis-",
        "policy": "eyJle...dfQ==",
        "signature": "ruboM...P3R4c="
    }
}

两者之间的唯一区别是远程的(由 lambda 函数生成)还包含字段

x-amz-security-token

...
        "x-amz-security-token": "IQoJb...ZAQ==",
...

当我尝试发布文件时(使用上面链接的页面或邮递员中报告的 html 示例),当我使用本地生成的预签名 url 时一切正常(无

x-amz-security-token
),但当我尝试远程生成的网址时一切正常.

x-amz-security-token
作为表单字段发送时,它会返回以下错误消息:

403 Forbidden

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>InvalidAccessKeyId</Code>
    <Message>The AWS Access Key Id you provided does not exist in our records.</Message>
    <AWSAccessKeyId>-omissis-</AWSAccessKeyId>
    <RequestId>360...BE2</RequestId>
    <HostId>y04bl...DWhqY=</HostId>
</Error>

以及以下作为标题字段:

403 Forbidden

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>AccessDenied</Code>
    <Message>No AWSAccessKey was presented.</Message>
    <RequestId>A7592...6681</RequestId>
    <HostId>stc/+...eeUU=</HostId>
</Error>

当预签名的 url 包含

x-amz-security-token
时,我应该如何正确发出 POST 请求?

python amazon-web-services amazon-s3 aws-api-gateway boto3
1个回答
0
投票

使用 Lambda 时,由于您不使用访问密钥,而是通过其 IAM 执行角色 (STS) 承担角色。这意味着每次执行都会生成有效期较短的临时凭证,并使用它们来执行所需的任何操作(在本例中为预签名 URL)。

实际从客户端下载/上传时,您需要在正文中发送“X-Amz-Security-Token”以及预签名时获得的值。不幸的是,AWS 没有明确记录这一点。

在服务器端,在 NodeJS 中生成 sessionToken 将是:

const s3 = new AWS.S3();
const credentials = s3.config.credentials;
const sessionToken = credentials.sessionToken;

在服务器端,在 PHP 中生成 sessionToken 将是:

$credentials = $s3client->getCredentials()->wait();
$sessionToken = $credentials->getSecurityToken();

在客户端上传/下载文件时,您可以将其作为正文发送:

"acl": presignUploadData.acl, // for upload
"key": presignUploadData.key, // the key you presigned for download/upload
"X-Amz-Credential": presignUploadData.XAmzCredential,
"X-Amz-Algorithm": presignUploadData.XAmzAlgorithm,
"X-Amz-Date": presignUploadData.XAmzDate,
"Policy": presignUploadData.Policy,
"X-Amz-Signature": presignUploadData.XAmzSignature,
"X-Amz-Security-Token": presignUploadData.XAmzSecurityToken, // this is the new part

这修复了

403 Forbidden
部分。

如果您得到

Access Denied
,则可能是权限问题,最经典的是授予对资源“arn:aws:s3:::BUCKET_NAME”的访问权限,但不授予“arn:aws:s3:::BUCKET_NAME/*”的访问权限“或者没有授予足够的 s3 权限。

为了加快速度,您可以在

"s3:*"
上尝试
"Resource": "*"
看看是否有效,然后开始限制权限和资源(为了安全起见,不要跳过这部分)。

© www.soinside.com 2019 - 2024. All rights reserved.