在 S3 存储桶触发器中获取 AWS 请求 API 键?

Get AWS request API key in S3 bucket trigger?

作为异步内容处理系统的一部分,我们定义了绑定到 S3 集成服务的 API 网关方法,用于将 POST 请求转发到 S3 存储桶。然后,我们使用 S3 事件触发器将 ObjectCreated 事件触发到 SQS queue,最终由 Lambda 函数使用以进行后续处理。

我们有一个新的处理要求,要求我们在 SQS 处理程序 lambda 中识别用于验证原始 APIGW 请求的 API 密钥 ID,但我们还没有想出一种方法。我们寻找一种方法将客户端请求的 Authorization header 作为处理 lambda 接收到的事件内容的一部分传递,但没有成功——我怀疑传入请求到 S3 以创建 object 可能与 S3 触发器的上下文完全不同(无论新的 object 来自何处都会触发)。我们还寻找了一些方法来将 Authorization header(或映射的查询参数)映射到 S3 元数据,同样,没有乐趣。 AWS S3 集成服务是一个带有黑色端口的黑盒子,没有很好的文档记录,所以我不知道是否有办法做到这一点

最坏的情况下,我们可能会使用 RequestIdObjectCreated 事件与某种日志条目相关联,但这比我希望的更脆弱;如果可能的话,我更愿意将其作为代理集成配置的一部分。

有什么想法吗?

除非 API 网关中有一个 "gotcha" 使它无法按需要的方式工作,否则您可以在上传时向 S3 object 添加标签,方法是注入右边header进入request.

S3 的 PUT Object REST 方法支持请求 header、X-Amz-Tagging,它允许您指定一个或多个标签键和值,您应该能够将其注入集成请求——虽然我不确定 API 网关是否提供了足够的功能来让您进行字符串连接并应用 url-encoding 这个 header 期望的功能。您可能不需要使用 URL-encoding 除非 API 键中有字符需要它,并且可能没有任何此类字符。

我也在 Difference between object tags and object metadata? 的回答中讨论了这一点,这提出了另一个重要的观点——标签可能适用于此,但元数据不适用。每次下载 object 时,都会向客户端提供 Object 元数据,这可能会向下载 object 的不受信任方泄露这些 API 密钥。标签不包含在下载中——有一个单独的子资源用于获取这些标签。您的 Lambda 事件处理程序将需要调用 S3 来获取标签,如果事件处理程序中需要它们,或者如果您只需要将其存档 "in case" 那么标签中的存在可能就足够了。

根据 Michael 的回答,APIGW 确实支持构建的 header 映射,尽管这有点棘手。事实证明,您可以使用映射模板来设置 header 和参数,而不仅仅是转换 body。完整的解释包含在 Use a Mapping Template to Override an API's Request and Response Parameters and Status Codes 中,但是,简单地说,我创建了一个 application/json 集成请求映射模板,其中包含以下内容:

#set($tags="submitter_api_key_id=$util.urlEncode($context.identity.apiKeyId)")
#set($context.requestOverride.header.x-amz-tagging = $tags)
$input.json("$")

请注意设置 x-amz-tagging header 是作为 body 转换的 side-effect 完成的,这只是一个 pass-through ($input.json("$") 将整个 body 注入为 JSON).

唯一的其他更改是向 API 执行角色授予标记权限,ala

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObjectTagging"
            ],
            "Resource": "arn:aws:s3:::<origin-bucket>/*"
        }
    ]
}

就是这样。我的 POSTed S3 objects 现在创建了一个名为 submitter_api_key_id 的标签,其中包含与请求关联的 API 密钥的 ID。然后我可以使用该密钥映射到实际提交者的身份并执行我们的业务策略。