1

概括

我有一个在 AWS 中运行的平台,它通过 AWS Lambda 支持的 REST API 公开。该平台将元数据存储在 DynamoDB 中,将内容存储在 S3 中。用户由 Cognito 进行身份验证并存储在用户池中。该平台管理权限以控制哪些用户可以访问(以及他们是否可以修改)哪些元数据(以及相关的内容)。

我可以使用 STS 将用户的 JWT 令牌交换为 STS 令牌(使用 Cognito 身份池),并授予他们读取或写入 S3 中特定对象的权限。创建 STS 令牌由平台处理。这在直接访问 S3 时非常有效,并且似乎是 STS 的完美用例。

两个旁白来解决一些评论:

  • 预签名的 S3 URL 不够安全,因为知道链接的任何人都可以访问内容
  • 我必须直接上传到 S3,因为我没有运行任何服务器,并且由于 Lambda 中的临时空间限制 (512MB) 和请求可以通过 API 网关执行的时间量,Lambda 不适合流式传输我的内容(29 秒)

我想在 S3 存储桶前面添加 CloudFront 以从其 CDN 功能中受益;如果可以从边缘提供内容而不是每次都从 S3 检索,这将降低数据传输成本。这是我遇到问题的地方 - 我不知道如何将 STS 令牌发送到 CloudFront,以便它将它传递给 S3。

问题:当 S3 存储桶位于 CloudFront 前端时,如何使用 STS 凭证从 S3 存储桶中读取/写入?

更多详细信息

我创建了两个可以由 STS 承担的角色。一个有s3:ListBucket,一个有s3:PutObject。然后,我使用 Postman 在我的存储桶上执行GET和请求,从 STS调用PUT中指定访问密钥、密钥和会话令牌。assume-role-with-web-identity

GET直接访问 S3 时,和操作和两者PUT都有效,但在使用 CloudFront 时均无效。有趣的是,我得到不同的错误GETPUT

错误来自GET

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>AccessDenied</Code>
    <Message>No AWSAccessKey was presented.</Message>
    <RequestId><!-- snip --></RequestId>
    <HostId><!-- snip --></HostId>
</Error>

错误来自PUT

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>SignatureDoesNotMatch</Code>
    <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
    <AWSAccessKeyId><!-- snip --></AWSAccessKeyId>
    <StringToSign><!-- snip --></StringToSign>
    <SignatureProvided><!-- snip --></SignatureProvided>
    <StringToSignBytes><!-- snip --></StringToSignBytes>
    <CanonicalRequest><!-- snip --></CanonicalRequest>
    <CanonicalRequestBytes><!-- snip --></CanonicalRequestBytes>
    <RequestId><!-- snip --></RequestId>
    <HostId><!-- snip --></HostId>
</Error>

我已经从回复中删除了一些值,但如果有必要可以提供它们。

4

0 回答 0