@kotyのブログ

PythonとかAWSとか勉強会のこととかを、田舎者SEがつづります。記事のライセンスは"CC BY"でお願いします。

nginx+django storage s3 backendでdjango本体と同じドメインを使い、かつIPによるアクセス制限をかける

この記事は JSL (日本システム技研) Advent Calendar 2018 - Qiita の7日目の記事です。

以下の要件がありました。

  • APIへのアクセスをIP制限したい
    • APIはnginx+gunicorn(Django, Django Rest Framework)で動いている
    • APIの戻り値の中にS3に置いた画像へのURLがある。
    • 画像はImageField+Django storage+S3 backendを使って保存している
  • APIと画像のドメインは同じにしたい
  • このURLもAPIと同様にアクセスをIP制限したい

順を追って設定していきます。3番目の要件は1番めと2番目が実現できればおのずと実現できそうです。

APIへのアクセス制限

AWSのセキュリティグループで80と443ポートについて制限

ImageField+Django storage + S3 backendの基本的な使い方については割愛します。

APIと画像のドメインを同じにする

settigns.pyにAWS_S3_CUSTOM_DOMAIN = 'www.example.com' を追記します。

この設定についてはdjango storageのS3 backend Amazon S3 — django-storages 1.7.1 documentation に記載されています。CloudFrontの項にあるのですが、CloudFrontを使うかどうかは特に関係ないようです。単にImageFieldのホスト名がここで設定した値になります。http://https:// は書きません。既定でhttps://が付加されます。検証環境など http://で使いたい場合は AWS_S3_SECURE_URLS = False をsettings.pyで設定します。

画像のURLへのアクセスをS3に向ける

nginx.confを設定します。

        location ~  ^/images/ {
            proxy_buffering        off;
            resolver 8.8.8.8;
            proxy_pass http://my-bucket-name.s3-website-ap-northeast-1.amazonaws.com;
        }

参考: Nginx のDNS 名前解決とS3 やELB へのリバースプロキシ :: by and for engineers

S3をEC2からのアクセスのみに制限する

VPCエンドポイントなるものを設定します。

参考:nginxとS3を使って静的コンテンツを利用者を限定した形で利用できるようにする | DevelopersIO

上記の記事ではバケットポリシーに aws:sourceVpcVPCのIDを指定していますが、VPCエンドポイントを作って aws:sourceVpceVPCエンドポイントIDを指定しないとうまくいきませんでした。

画像のURLをAPIと同様にアクセス制限する

以上の設定をしていると、画像のURLをアクセス制限できます。