Il semblerait que la tâche d'implémenter le frontend pour AWS sur nginx ressemble à un cas typique pour StackOverflow - après tout, il ne peut y avoir aucun problème avec les fichiers proxy de S3? En fait, il s'est avéré qu'une solution toute faite n'est pas si facile à trouver, et cet article devrait corriger cette situation.

Pourquoi auriez-vous même besoin de ça?
- Contrôlez l'accès aux fichiers à l'aide de nginx - pertinent pour le concept d'IaC (infrastructure en tant que code). Toutes les modifications liées à l'accès seront effectuées uniquement dans les configurations présentes dans le projet.
- Si vous donnez des fichiers via votre nginx, vous pouvez les mettre en cache et enregistrer sur les demandes à S3.
- Un tel proxy aidera à ignorer le type de stockage de fichiers pour différentes installations d'application (après tout, il existe d'autres solutions que S3).
Nous formulons le cadre
- Le compartiment source doit être privé - vous ne pouvez pas autoriser des utilisateurs anonymes à télécharger des fichiers directement depuis S3. Si dans votre cas, cette restriction ne fonctionne pas, utilisez simplement
proxy_pass
et vous ne pourrez plus lire. - Le réglage par AWS doit être ponctuel sur une base «réglé et oublié» pour simplifier le fonctionnement.
Nous recherchons une solution dans le front
Si votre compartiment d'origine est public, aucune difficulté ne vous menace, les demandes de proxy pour S3 et tout fonctionneront. S'il est privé, vous devrez vous authentifier avec S3 d'une manière ou d'une autre. Que nous offrent les collègues d'Internet:
- Il existe des exemples d' implémentation du protocole d'authentification à l'aide de nginx. La solution est bonne, mais malheureusement, elle est conçue pour un protocole d'authentification obsolète ( Signature v2 ), qui ne fonctionne pas dans certains centres de données Amazon . Si vous essayez d'utiliser cette solution, par exemple à Francfort, vous obtiendrez l'erreur "Le mécanisme d'autorisation que vous avez fourni n'est pas pris en charge. Veuillez utiliser AWS4-HMAC-SHA256 . " Une version plus récente du protocole ( Signature v4 ) est beaucoup plus difficile à implémenter, mais il n'y a pas de solutions prêtes à l'emploi pour nginx.
- Il existe un module tiers pour nginx - ngx_aws_auth . À en juger par la source, il prend en charge Signature v4. Cependant, le projet semble abandonné: depuis plus d'un an, il n'y a eu aucun changement dans la base de code, et il y a aussi un problème de compatibilité avec d'autres modules auxquels le développeur ne répond pas. De plus, l'ajout de modules supplémentaires à nginx est souvent une étape douloureuse en soi.
- Vous pouvez utiliser un proxy s3 distinct, dont beaucoup ont été écrits. Personnellement, j'ai aimé la solution Go - aws-s3-proxy : elle a une image prête à l'emploi et assez populaire sur DockerHub. Mais dans ce cas, l'application va acquérir un autre composant avec ses problèmes potentiels.
Appliquer la stratégie de compartiment AWS
AWS, en règle générale, fait peur aux nouveaux utilisateurs avec sa complexité et son volume de documentation. Mais si vous regardez, vous comprenez qu'il est conçu de manière très logique et flexible. Amazon a également trouvé une solution pour notre tâche -
S3 Bucket Policy . Ce mécanisme vous permet de créer des règles d'autorisation flexibles pour le compartiment en fonction de différents paramètres du client ou de la demande.
Interface du générateur de stratégie - AWS Policy GeneratorVoici quelques options intéressantes auxquelles vous pouvez vous lier:
- IP (
aws:SourceIp
), - En-tête de référent (
aws:Referer
), - En-tête User-Agent (
aws:UserAgent
), - le reste est décrit dans la documentation .
La liaison IP n'est une bonne option que si l'application a un certain lieu de résidence, et à notre époque, elle est rare. En conséquence, vous devez vous attacher à autre chose. Comme solution, je propose de
générer un User-Agent ou Referer secret et de ne donner des fichiers qu'aux utilisateurs qui connaissent l'en-tête secret. Voici à quoi ressemble une politique similaire:
{ "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" ] } } } ] }
Une petite explication:
"Version": "2012-10-17"
est la cuisine AWS interne que vous n'avez pas besoin de modifier;Principal
- qui est concerné par cette règle. Vous pouvez indiquer que cela ne fonctionne que pour un compte AWS spécifique, mais dans notre cas, cela coûte "*"
- cela signifie que la règle fonctionne pour tout le monde, y compris les utilisateurs anonymes;Resource
- compartiment ARN (Amazon Resource Name) et modèle pour les fichiers à l'intérieur du compartiment. Dans notre cas, la stratégie s'applique à tous les fichiers qui se trouvent dans le example-bucket-for-habr
;Condition
- voici les conditions qui doivent converger pour que la politique fonctionne. Dans notre cas, nous comparons l'en-tête prédéfini de l'agent utilisateur avec la ligne xxxyyyzzz
.
Et voici à quoi ressemble le travail de cette règle du point de vue d'un utilisateur anonyme:
$ 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
Il reste à
configurer nginx pour le 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; }
Conclusion
Au total, une fois que nous avons écrit une politique simple pour le bucket, nous avons eu l'opportunité de proxy en toute sécurité des fichiers en utilisant nginx. Cependant, nous ne sommes pas liés par IP et ne dépendons pas de logiciels supplémentaires.
PS
Lisez aussi dans notre blog: