S3的一次性POST文件上传策略?

时间:2016-08-25 23:11:25

标签: amazon-web-services amazon-s3

我知道可以创建一个预签名策略,允许用户将文件上传到具有过期时间的特定密钥前缀,但问题是可以多次使用相同的预签名策略进行上传当策略尚未过期时,许多文件都会进入存储桶。

例如,如果我们通过实际密钥为a/b/的策略强制执行密钥前缀a/b/${filename},则用户可以多次重复使用该策略以将文件上载到该密钥前缀。 / p>

有没有办法让政策成为一次性政策,在上传成功后,政策会失效?

1 个答案:

答案 0 :(得分:1)

这真的很难做到,但从技术上来说,如果你不介意跳过一些箍,自定义编码你的Url预设步骤,以及Lambda函数!

预签名URL的工作方式是它们由生成它们的身份的AccessKey和SecretKey签名。签名受时间限制,操作受限,并包含在URL中以及AccessKey和Expiry时间。使用亚马逊对AccessKey的了解来验证签名,以确保它与操作匹配且尚未过期。

所以亚马逊没有关于预先签名的URL存在的记录 - 它不需要 - 所有验证URL的信息都包含在签名和AccessKey / SecretKey对中。

由于亚马逊没有关于预先签名的Url的记录,因此除了访问密钥本身之外,您无法禁用或删除它。如果您删除或停用用于预设Url的访问密钥,则Url将停止工作。

这是一个棘手的问题,因为如果您使用访问密钥对Url进行签名,那么您可能希望继续使用访问密钥。但如果您不介意在每个预先签名的Url上轮换密钥,那么有一种机制可以使用S3 Events和Lambda。

我们走了......

生成预签名网址

要生成可以停用的预签名网址,请在每次要生成网址时执行以下操作:

  1. 为您的帐户添加新的访问密钥/密钥 - 请参阅CreateAccessKey API
  2. 存储新的访问密钥,因为您将不得不将其用于下一个请求
  3. 获取有关要签名的网址的一些独特信息 - 每个预先签名的网址应该是唯一的。可能的密钥前缀?如果密钥前缀不是唯一的,那么这个解决方案会有点棘手......
  4. 将数据(例如DyanmoDb)添加到数据库(例如DyanmoDb),Lambda函数可以将该数据作为键映射到当前的AccessKeyId作为值。
  5. 使用您当前的访问密钥签署网址
  6. 分发预先签名的网址
  7. 轮换您的配置以在下一个请求中使用新的访问密钥
  8. Lambda函数

    创建一个lambda函数,该函数将由每个s3:ObjectCreated:*事件触发。

    在lambda函数中,您将收到事件记录作为方法参数。每个事件都有关于存储桶和密钥的许多字段。查找存储AccessKeyId时用作密钥的信息。

    lambda函数应查找数据库记录以获取与该信息关联的AccessKey。

    禁用访问密钥

    获得AWSAccessKey后,您的lambda函数可以使用DeleteAccessKey API调用来删除访问密钥。

    预先签名的网址将不再有效。

    您可能还想从数据库中删除记录,只是为了清理房屋。

    配置S3以在事件上触发Lambda

    在s3控制台中,进入存储桶,然后进入事件区域,您可以选择Lambda作为通知类型并放入lambda函数的arn。

    结论

    正如你所看到的 - 这并不容易,但据我所知,这是唯一可行的方法。如果有一种更简单的方法,我完全错过了它,但很想知道!

    关于实例角色的说明

    如果您在EC2实例上使用Iam Instance Roles来预设Url,则无法保证上述解决方案。我必须对其中的含义进行更多研究,因此建议您是否采用上述技术,确保使用常规Iam角色(不幸的是,在Ec2实例上运行软件时,这违反了最佳实践建议)。

    进一步阅读

    有关将lambda与s3一起使用的详细信息,请参阅http://docs.aws.amazon.com/lambda/latest/dg/with-s3.htmlhttp://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html。第二个例子是这种方法的灵感。