【问题标题】:How to increase expiration time in AWS signature v4 pre-signed links for API Gateway from default 5 min?如何将 API Gateway 的 AWS 签名 v4 预签名链接的过期时间从默认的 5 分钟延长?
【发布时间】:2021-06-27 12:01:13
【问题描述】:

我正在尝试生成到 API 网关(使用 IAM 身份验证)的预签名链接,因此客户端可以访问此 API 网关后面的我的 Lambda 函数之一,而无需验证请求。这主要是为了方便客户端,因此它可能会透明地使用响应中的一些链接,无论它们指向同一个经过身份验证的 API 网关、某个 S3 存储桶还是 Internet 中的任意 URL。

为此,我使用查询参数制作 API 签名 v4(请参阅 docsexample

所以,如果我尝试在us-west-2 区域和execute-api 服务范围内的以下链接上签名:

https://example.com/some/path?some=params

我会得到以下结果(using Node.js aws4 library,但在这里没关系):

https://example.com/some/path?some=params&
X-Amz-Security-Token=<Session Token Removed>
X-Amz-Date=20210330T180303Z&
X-Amz-Algorithm=AWS4-HMAC-SHA256&
X-Amz-Credential=<Access Key Removed>%2F20210330%2Fus-west-2%2Fexecute-api%2Faws4_request&
X-Amz-SignedHeaders=host&
X-Amz-Signature=884f132ad6f0c7a850e6b1d22b5fed169c13e2189b6e0d0d568d11f967f4a8bd

而且它有效!但仅在生成后的前 5 分钟......

五分钟后,我会收到以下错误响应:

{"message":"Signature expired: 20210330T175821Z is now earlier than 20210330T180403Z (20210330T180903Z - 5 min.)"}

更多详情请见this response to this question

我尝试使用各种值(小于和大于 300 秒)添加文档中提到的 X-Amz-Expires 查询参数,但没有运气:行为不会改变。

我需要至少几个小时,最多 allowed 6 hours for links generated by IAM instance credentials,因为链接正在由另一个 Lambda 函数签名。

有什么方法可以增加 API 网关访问的预签名链接有效期?

【问题讨论】:

标签: amazon-web-services aws-api-gateway pre-signed-url sigv4


【解决方案1】:

我在其中一个用例中遇到了同样的问题。就像用户想要在有限的时间内访问 S3 中的 CSV 文件一样。

我最终构建了以下架构:

  • 一个处理“用户访问请求”的 lambda 函数。它位于 API 网关后面,负责将 CSV 文件放入 S3(您可能不需要此部分)。 Lambda 正在生成一个带有一些散列的 URL,触发了 API GW 后面的另一个 lambda (#2)。
  • 我的第二个 lambda 也在 API GW 之后,并且可以由第一个 lambda 生成的 URL 触发。这是用户出现的地方,因为来自第一个 lambda 的 URL 被提供给实际用户以点击它。第二个 lambda 所做的很简单。它为 S3 对象动态生成了一个 6 小时长的预签名 URL,并发送回一个带有预签名 URL 的 HTTP 302,因此用户的浏览器会立即下载 CSV。

这样,几乎所有 lambda 生成的 URL 都可以与任何人共享,并且该 URL 将一直有效,直到 S3 对象存在为止。

如果您需要某种策略以使 URL 可访问 30 天或其他时间,您可以设置存储桶策略以在之后删除该对象。

【讨论】:

    【解决方案2】:

    这是一个非常有趣的问题! 起初,我认为在 S3 文档中清楚地记录了 X-Amz-Expires 被所有服务(包括 API 网关)支持。 [1][2]

    经过一番研究,结果发现,除了 S3 以外的服务是否支持 X-Amz-Expires 参数,根本不清楚

    有各种消息来源声称只有 S3 尊重该参数。以下是 AWS 员工在 aws-sdk for go 上工作的声明:

    过期时间仅与 S3 服务相关。其他服务有自己固定的过期时间。通常这是 15 分钟,但看起来物联网数据服务使用 5 分钟的到期时间。 [3]

    他们跟进:

    SDK 没有任何可用的元数据数据来提供哪些服务使用或不使用到期值。 [4]

    然后在GitHub上相应的源码中添加注释:

    所有其他 AWS 服务将使用 15 分钟的固定到期时间。 [5]

    有大量示例表明 AWS 正在使用 S3 服务的参数,例如[1][6]。 但是,AWS 文档中也有一些示例显示了对 IAM 服务的参数的使用,例如[7][8]。 这很令人困惑。

    AWS 的一位 SDE 发表的评论可以追溯到 2018 年,其中他做出了同样令人困惑的观察 [9]:

    如果 S3 是唯一支持此标头的服务,我同意更新 SDK 的文档以反映这一点 - 在 S3 的 SigV4 文档中的此标头描述中包含一条注释,说明此标头专用于此标头的预签名 URL服务也会很有帮助。

    FWIW 我与来自 AWS Auth 的一些人进行了交谈,他们知道使用标头的唯一服务是 S3(有趣的是,您使用 IAM 找到了一个代码示例)。他们建议 STS 预签名 URL 的 15 分钟到期时间不会改变。

    另一位前 AWS 员工进一步注意到:

    我能够使用 EC2、IAM、STS 和 Route 53 的预签名 URL 在适用于 Go 和 PHP 的 AWS 开发工具包上重现此行为。我观察到的唯一服务在“ x-amz-expires" 标头(而不是默认的 15 分钟)是 S3。

    因此,我想不可能增加 API 网关访问的预签名链接有效期。我认为 AWS 没有设计签名签名算法来支持您的用例。我认为 S3 预签名 URL 操作是 AWS 允许延长有效期的少数例外情况之一。

    查看他们创建签名算法的动机时,我注意到他们试图最小化重放攻击的攻击面:

    防止潜在的重放攻击
    在大多数情况下,请求必须在请求时间戳的五分钟内到达 AWS。否则,AWS 会拒绝该请求。 [10]

    还有更多资源 [11][12] 得出的结论是,让客户选择较长的到期值会破坏该参数的原始安全目的

    我认为没有通用的方法可以创建指向 AWS 服务的 REST API 的预签名 URL 并在很远的将来执行它。

    如果我在你的位置,我会使用 JWT 和 API Gateway Lambda 授权者实施自定义身份验证策略。 [13] 这样您就可以自行控制签名算法,尤其是其到期时间。我想补充一点,JWT 与 AWS 签名查询字符串参数一样是 URL 安全的。 [14]

    [1]https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
    [2]https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html
    [3]https://github.com/aws/aws-sdk-go/issues/2304#issuecomment-441755864
    [4]https://github.com/aws/aws-sdk-go/issues/2304#issuecomment-441758599
    [5]https://github.com/aws/aws-sdk-go/blob/6212dfa8032336d438c526c086918c8d2ceb6432/aws/request/request.go#L310
    [6]https://github.com/mhart/aws4/blob/master/aws4.js#L130
    [7]https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
    [8]https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html
    [9]https://github.com/aws/aws-sdk-go/issues/2167#issuecomment-428764319
    [10]https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html
    [11] https://aws.amazon.com/de/articles/making-secure-requests-to-amazon-web-services/?nc1=h_ls(“重放攻击”部分)
    [12]https://stackoverflow.com/a/12267408/10473469
    [13]https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html
    [14]https://stackoverflow.com/a/56273952/10473469

    【讨论】:

    • 多么了不起的研究啊!谢谢!可悲的是,这只是证实了可能没有解决方案。
    • 至少没有内置解决方案;) 如果您愿意,我们可以讨论您的具体用例以及“C​​ognito - JWT - Lambda Authorizer”解决方案的外观。我相信你的用例可以通过在游戏中引入更多的 AWS 服务来覆盖,而不仅仅是简单的 IAM 和 STS。
    猜你喜欢
    • 1970-01-01
    • 2023-01-27
    • 1970-01-01
    • 1970-01-01
    • 2017-01-31
    • 2016-07-02
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多