Parece que a tarefa de implementar o frontend da AWS no nginx parece um caso típico do StackOverflow - afinal, não há problemas com o proxy de arquivos do S3? De fato, descobriu-se que uma solução pronta não é tão fácil de encontrar, e este artigo deve corrigir essa situação.

Por que você precisaria disso?
- Controle o acesso aos arquivos usando o nginx - relevante para o conceito de IaC (infraestrutura como código). Todas as alterações relacionadas ao acesso serão feitas apenas nas configurações que estão no projeto.
- Se você fornecer arquivos através do seu nginx, poderá armazená-los em cache e salvar os pedidos no S3.
- Esse proxy ajudará a ignorar o tipo de armazenamento de arquivo para diferentes instalações de aplicativos (afinal, existem outras soluções além do S3).
Formulamos a estrutura
- O bucket de origem deve ser privado - você não pode permitir que usuários anônimos baixem arquivos diretamente do S3. Se, no seu caso, essa restrição não funcionar, use
proxy_pass
e você não poderá mais ler. - O ajuste pela AWS deve ser único, “ajustado e esquecido”, para simplificar a operação.
Estamos à procura de uma solução na testa
Se o seu bucket original for público, nenhuma dificuldade o ameaçará, solicitações de proxy para o S3 e tudo funcionará. Se for privado, você precisará se autenticar no S3 de alguma forma. O que os colegas da Internet nos oferecem:
- Existem exemplos de implementação do protocolo de autenticação usando o nginx. A solução é boa, mas infelizmente foi projetada para um protocolo de autenticação desatualizado ( Signature v2 ), que não funciona em alguns data centers da Amazon . Se você tentar usar esta solução, por exemplo, em Frankfurt, receberá o erro "O mecanismo de autorização que você forneceu não é suportado. Por favor, use AWS4-HMAC-SHA256 . " Uma versão mais recente do protocolo ( Signature v4 ) é muito mais difícil de implementar, mas não há soluções prontas para o nginx com ele.
- Há um módulo de terceiros para o nginx - ngx_aws_auth . A julgar pela fonte, ele suporta a assinatura v4. No entanto, o projeto parece abandonado: por mais de um ano não houve alterações na base de código e também há um problema de compatibilidade com outros módulos aos quais o desenvolvedor não responde. Além disso, adicionar módulos adicionais ao nginx geralmente é um passo doloroso.
- Você pode usar um proxy s3 separado, dos quais muitos foram escritos. Pessoalmente, gostei da solução Go - aws-s3-proxy : ela tem uma imagem pronta e bastante popular no DockerHub. Mas, neste caso, o aplicativo adquirirá outro componente com seus possíveis problemas.
Aplicar política de bucket da AWS
A AWS, via de regra, assusta os novos usuários com sua complexidade e volume de documentação. Mas se você olhar, entende que ele foi projetado de maneira muito lógica e flexível. A Amazon também encontrou uma solução para a nossa tarefa - a
política de balde S3 . Esse mecanismo permite criar regras de autorização flexíveis para o bucket com base em diferentes parâmetros do cliente ou solicitação.
Interface do gerador de políticas - AWS Policy GeneratorAqui estão algumas opções interessantes às quais você pode se associar:
- IP (
aws:SourceIp
), - Cabeçalho do referenciador (
aws:Referer
), - Cabeçalho do agente do usuário (
aws:UserAgent
), - o restante está descrito na documentação .
A ligação de IP é uma boa opção apenas se o aplicativo tiver um determinado local de residência e, em nosso tempo, é raro. Portanto, você precisa se apegar a outra coisa. Como solução, proponho
gerar um User-Agent ou Referer secreto e fornecer arquivos apenas para os usuários que conhecem o cabeçalho secreto. Veja como é uma política semelhante:
{ "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" ] } } } ] }
Uma pequena explicação:
"Version": "2012-10-17"
é a cozinha interna da AWS que você não precisa editar;Principal
- quem é afetado por esta regra. Você pode especificar que ele funcione apenas para uma conta específica da AWS, mas, no nosso caso, custa "*"
- isso significa que a regra funciona para todos, inclusive usuários anônimos;Resource
- bucket e modelo ARN (Amazon Resource Name) para arquivos dentro do bucket. No nosso caso, a política se aplica a todos os arquivos que estão no example-bucket-for-habr
;Condition
- aqui estão as condições que devem convergir para que a política funcione. No nosso caso, estamos comparando o cabeçalho predefinido User-Agent com a linha xxxyyyzzz
.
E aqui está como o trabalho desta regra se parece do ponto de vista de um usuário anônimo:
$ 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
Resta
configurar o nginx para proxy:
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; }
Conclusão
No total, depois que escrevemos uma política simples para o bucket, tivemos a oportunidade de fazer proxy de arquivos com segurança usando o nginx. No entanto, não estamos vinculados pelo IP e não dependemos de software adicional.
PS
Leia também em nosso blog: