有没有办法通过指定发布日期来配置 Amazon Cloudfront 来延迟我的 S3 对象到达客户端之前的时间?

Is there a way to configure Amazon Cloudfront to delay the time before my S3 object reaches clients by specifying a release date?

我想将内容上传到 S3,但安排了 Cloudfront 将其交付给客户的时间,而不是在处理后立即将其出售给客户。是否有配置选项来完成此操作?

编辑:这次应该能够根据 S3 中的对象而有所不同。

一些允许这样做的配置选项,它确实允许您限制特定文件——或路径前缀——在给定的之前被提供日期和时间……虽然有点……好吧,我都不知道用什么贬义词来形容了。 :) 但这是我唯一能想到的完全使用 built-in 功能的东西。

首先,快速提醒一下,可以使用存储桶策略在存储桶级别授予对 S3 中 object 的 public/unauthenticated 读取访问权限,或者在 object 级别使用"make everything public" 在控制台中上传 object 时,或在通过 API 上传时发送 x-amz-acl: public-read。如果其中一个或两个都存在,则 object 是 public 可读的, 除了 面对任何拒绝相同访问的策略。 Deny总是胜过Allow

因此,我们可以创建一个匹配特定文件或前缀的存储桶策略语句,拒绝在特定日期和时间之前的访问。

{
    "Version": "2012-10-17",
    "Id": "Policy1445197123468",
    "Statement": [
        {
            "Sid": "Stmt1445197117172",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::example-bucket/hello.txt",
            "Condition": {
                "DateLessThan": {
                    "aws:CurrentTime": "2015-10-18T15:55:00.000-0400"
                }
            }
        }
    ]
}

使用通配符将使特定路径下的所有内容都受到相同的限制。

"Resource": "arn:aws:s3:::example-bucket/cant/see/these/yet/*",

这有效,即使 object 是 public。

此示例阻止任何 body 对匹配 object 的所有 GET 请求,无论他们可能拥有什么权限。签名 URL 等不足以覆盖此政策。

政策声明在创建时进行有效性检查;但是,匹配的 object 不一定存在,因此如果策略是在 object 之前创建的,则不会使策略无效。

现场测试:

过期时间之前:(无关request/response headers 为清楚起见删除)

$ curl -v example-bucket.s3.amazonaws.com/hello.txt
> GET /hello.txt HTTP/1.1
> Host: example-bucket.s3.amazonaws.com
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Content-Type: application/xml
< Transfer-Encoding: chunked
< Date: Sun, 18 Oct 2015 19:54:55 GMT
< Server: AmazonS3
<
<?xml version="1.0" encoding="UTF-8"?>
* Connection #0 to host example-bucket.s3.amazonaws.com left intact
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>AAAABBBBCCCCDDDD</RequestId><HostId>g0bbl3dyg00kbunc4Ofl1n3n0iz3h3rehahahasqlbot1337kenqweqwel24234kj41l1ke</HostId></Error>

在指定的日期和时间之后:

$ curl -v example-bucket.s3.amazonaws.com/hello.txt
> GET /hello.txt HTTP/1.1
> Host: example-bucket.s3.amazonaws.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sun, 18 Oct 2015 19:55:05 GMT
< Last-Modified: Sun, 18 Oct 2015 19:36:17 GMT
< ETag: "78016cea74c298162366b9f86bfc3b16"
< Accept-Ranges: bytes
< Content-Type: text/plain
< Content-Length: 15
< Server: AmazonS3
<
Hello, world!

这些测试是针对存储桶的 S3 REST 端点完成的,但同一存储桶的网站端点产生相同的结果——只有错误消息在 HTML 而不是 XML 中.

此政策的积极方面是,由于 object 是 public,因此可以在日期过后随时删除该政策,因为它 之前拒绝访问 特定时间,而不是 允许在 特定时间后访问——逻辑上相同,但实现方式不同。 (如果该策略允许之后访问而不是之前拒绝访问,则该策略将不得不无限期保留;这样,它就可以被删除。)

您可以在 S3 或 CloudFront 中使用自定义错误文档来向查看器呈现稍微更好的输出...可能是 CloudFront,因为您可以 select 单独自定义每个错误代码,创建自定义 403页。

当然,这种方法的主要缺点是必须为每个 object 或路径前缀编辑策略,即使它有效 per-object,也不是根据 object.

由于存储桶策略的大小限制,您可以包含多少策略语句是有限制的:

Note

Bucket policies are limited to 20 KB in size.

http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html


想到的另一个解决方案涉及在 CloudFront 和存储桶之间的 EC2 中部署反向代理组件(例如 HAProxy),传递请求并从 object 的响应中读取自定义元数据headers,查找 header 例如 x-amz-meta-embargo-until: 2015-10-18T19:55:00Z 并将其值与系统时钟进行比较;如果当前时间在截止时间之前,代理将断开与 S3 的连接,并将响应 headers 和 body 替换为 locally-generated 403 消息,因此客户端不会能够在指定时间过去之前获取 object。

此解决方案实施起来似乎相当简单,但需要一个非 built-in 组件,因此它不符合问题的限制,我还没有构建概念证明;但是,我已经在一些存储桶前面使用带有 Lua 的 HAProxy 来为 S3 提供一些本机不提供的其他功能,例如从响应和 modifying, and directing the browser to apply an XSL stylesheet to, the XML on S3 error responses 中删除敏感的自定义元数据,因此没有明显的原因记住为什么这个应用程序不能同样好地工作。

Lambda@edge 可以轻松应用您自定义的访问控制