似乎在nginx上实现AWS前端的任务听起来像StackOverflow的典型情况-毕竟,从S3代理文件不会有问题吗? 实际上,事实证明,现成的解决方案并不是那么容易找到,因此本文应该纠正这种情况。

你为什么还要这个?
- 使用Nginx控制对文件的访问-与IaC(基础结构作为代码)的概念有关。 与访问相关的所有更改将仅在项目中的配置中进行。
- 如果通过nginx提供文件,则可以对其进行缓存并保存对S3的请求。
- 这样的代理将有助于忽略不同应用程序安装的文件存储类型 (毕竟,除了S3之外,还有其他解决方案)。
我们制定框架
- 源存储桶必须是私有的 -您不能允许匿名用户直接从S3下载文件。 如果您的限制不起作用,请使用
proxy_pass
,您将无法再阅读。 - AWS的调优应该是一次“调优而遗忘”的调优,以简化操作。
我们正在寻找额头上的解决方案
如果您原来的存储桶是公开的,那么没有任何困难威胁您,代理请求S3,一切都会正常。 如果它是私有的,那么您将必须以某种方式通过S3进行身份验证。 互联网上的同事为我们提供了什么:
- 有使用nginx实现身份验证协议的示例 。 该解决方案不错,但不幸的是,它是针对过时的身份验证协议( Signature v2 )设计的,该协议在某些Amazon数据中心中不起作用。 如果尝试使用此解决方案,例如在法兰克福,则会收到错误消息“不支持您提供的授权机制。 请使用AWS4-HMAC-SHA256 。 “ 较新版本的协议( Signature v4 )很难实现,但是尚无现成的nginx解决方案。
- nginx- ngx_aws_auth有一个第三方模块。 从来源来看,它支持Signature v4。 但是,该项目似乎被放弃了:一年多来,代码库没有任何变化,并且还存在与开发人员未响应的其他模块的兼容性问题 。 另外,向nginx添加其他模块本身通常是一个痛苦的步骤。
- 您可以使用单独的s3代理,其中已经编写了很多内容。 就个人而言,我喜欢Go解决方案-aws-s3-proxy :它在DockerHub上具有现成的且相当流行的映像。 但是在这种情况下,该应用程序将获得具有潜在问题的另一个组件。
套用AWS Bucket政策
通常,AWS的复杂性和文档量使新用户感到恐惧。 但是,如果您看一下,就会了解它的设计非常合逻辑且灵活。 亚马逊还为我们的任务找到了解决方案
-S3存储桶策略 。 通过此机制,您可以根据客户端或请求的不同参数为存储桶构建灵活的授权规则。
策略生成器界面-AWS Policy Generator您可以绑定以下一些有趣的选项:
- IP(
aws:SourceIp
), - Referer标头(
aws:Referer
), - User-Agent标头(
aws:UserAgent
), - 其余在文档中描述。
仅当应用程序具有一定的居住地时,IP绑定才是一个不错的选择,而在我们这个时代,这种情况很少见。 因此,您需要与其他事物建立联系。 作为解决方案,我建议
生成一个秘密的User-Agent或Referer ,并将文件仅提供给那些知道秘密标头的用户。 这是类似的策略的样子:
{ "Version": "2012-10-17", "Id": "http custom auth secret", "Statement": [ { "Sid": "Allow requests with my secret.", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::example-bucket-for-habr/*", "Condition": { "StringLike": { "aws:UserAgent": [ "xxxyyyzzz" ] } } } ] }
一点解释:
"Version": "2012-10-17"
是您不需要编辑的内部AWS厨房;Principal
-受此规则影响的人。 您可以指定它仅适用于特定的AWS账户,但在我们的情况下,它的价格为"*"
-这表示该规则适用于所有人,包括匿名用户;Resource
-ARN(Amazon资源名称)存储桶和存储桶中文件的模板。 在我们的案例中,该策略适用于example-bucket-for-habr
中的所有文件;Condition
-这是为了使策略生效而必须收敛的条件。 在本例中,我们将预定义的User-Agent标头与xxxyyyzzz
行进行比较。
这是从匿名用户的角度来看此规则的工作方式:
$ curl -I https://s3.eu-central-1.amazonaws.com/example-bucket-for-habr/hello.txt HTTP/1.1 403 Forbidden $ curl -I https://s3.eu-central-1.amazonaws.com/example-bucket-for-habr/hello.txt -H 'User-Agent: xxxyyyzzz' HTTP/1.1 200 OK
仍然需要
配置nginx进行代理:
location /s3-media/ { limit_except GET { deny all; } set $aws_bucket "example-bucket-for-habr"; set $aws_endpoint "s3.eu-central-1.amazonaws.com:443"; set $aws_custom_secret "xxxyyyzzz"; proxy_set_header User-Agent $aws_custom_secret; rewrite ^/s3-media/(.*)$ /$aws_bucket/$1 break; proxy_buffering off; proxy_pass https://$aws_endpoint; }
结论
总体而言,一旦我们为存储桶编写了简单的策略,我们就有机会使用nginx安全地代理文件。 但是,我们不受IP束缚,也不依赖于其他软件。
聚苯乙烯
另请参阅我们的博客: