使用Nginx从AWS S3代理文件

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



你为什么还要这个?


  1. 使用Nginx控制对文件的访问-与IaC(基础结构作为代码)的概念有关。 与访问相关的所有更改仅在项目中的配置中进行。
  2. 如果通过nginx提供文件,则可以对其进行缓存并保存对S3的请求。
  3. 这样的代理将有助于忽略不同应用程序安装文件存储类型 (毕竟,除了S3之外,还有其他解决方案)。

我们制定框架


  • 源存储桶必须是私有的 -您不能允许匿名用户直接从S3下载文件。 如果您的限制不起作用,请使用proxy_pass ,您将无法再阅读。
  • AWS的调优应该是一次“调优而遗忘”的调优,以简化操作。

我们正在寻找额头上的解决方案


如果您原来的存储桶是公开的,那么没有任何困难威胁您,代理请求S3,一切都会正常。 如果它是私有的,那么您将必须以某种方式通过S3进行身份验证。 互联网上的同事为我们提供了什么:

  1. 有使用nginx实现身份验证协议的示例 。 该解决方案不错,但不幸的是,它是针对过时的身份验证协议( Signature v2 )设计的,该协议在某些Amazon数据中心中不起作用。 如果尝试使用此解决方案,例如在法兰克福,则会收到错误消息“不支持您提供的授权机制。 请使用AWS4-HMAC-SHA256 较新版本的协议( Signature v4 )很难实现,但是尚无现成的nginx解决方案。
  2. nginx- ngx_aws_auth有一个第三方模块。 从来源来看,它支持Signature v4。 但是,该项目似乎被放弃了:一年多来,代码库没有任何变化,并且还存在与开发人员未响应的其他模块的兼容性问题 。 另外,向nginx添加其他模块本身通常是一个痛苦的步骤。
  3. 您可以使用单独的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束缚,也不依赖于其他软件。

聚苯乙烯


另请参阅我们的博客:

Source: https://habr.com/ru/post/zh-CN426739/


All Articles