LoginSignup
6
1

More than 3 years have passed since last update.

S3 + CloudFront で配信してる画像をRailsアプリの認証がないとみれなくする

Last updated at Posted at 2019-08-07

何がしたいか

S3 にアップロードして CloudFront で配信してるファイルのURLをRailsアプリで許可したユーザにしか見れなくしたくなった。

どうするか

CloudFront の署名付きURL機能をつかう。 閲覧制限時間を設定できるので、たとえそのURLが漏れたとしても(制限時間が切れてれば)悪意の第三者は閲覧できない。

ユーザが画像を見るときは以下のような手順になる。

  1. ユーザが制限付きの画像URL(https://your-cloud-front-domain/private/image.jpg とする) を含むリソース(https://your-app-domain/index.html とする)をアプリにリクエストする
  2. アプリは CloudFront の署名付きURL(https://your-cloud-front-domain/private/image.jpg?認証用のクエリ を発行する
  3. アプリは 署名付きURLを含んだ index.html をユーザに返却する
  4. ユーザは署名つきURLで画像にアクセスし、画像を閲覧する

設定手順

前提

(フォルダ名は任意。)

  • 運用中の S3, CloudFront がある
  • S3 は public/ ってフォルダ(オブジェクトキーのprefix)以下に配信用の画像を置いてる
  • 制限付きで配信するリソースを配置するS3のフォルダは private/ とする
  • アプリ側はRailsで実装されてることにする(ただしRails固有の記述は本記事中にないと思う。)

手順

AWS のセキュリティ認証情報で CloudFront 用の秘密鍵のペアを作成する

署名付き URL と署名付き Cookie (信頼された署名者) の作成が可能な AWS アカウントの指定 - Amazon CloudFront 開発者ガイド

ここで作った鍵のペアは安全なとこに保存する。

IAM ユーザーは CloudFront キーペアを作成できません。キーペアを作成するには、ルート認証情報を使用してログインする必要があります。

同一アカウントで作った開発・ステージング・商用などのCloudFrontがあるとき、環境ごとに鍵を分けられないらしい。まじ注意。

CloudFront の設定

  • Origins に以下を設定する。これで設定するとS3のバケットポリシーが更新される。
    • Restrict Bucket Access: Yes
    • Origin Access Identity: Yes
    • Grant Read Permissions on Bucket: Yes, Update Bucket Policy
  • Behaviors に以下を新規作成する。
    • path pattern: /private/*
    • Restrict Viewer Access: Yes

こんな感じ
f949c9177fa8eca3d1030917743e7779.png

S3 の設定

CloudFront の設定手順でバケットポリシーが更新されているので、 Resource に今回適用したいフォルダ(prefix)を追記する。

追加された設定
[
  {
    // 既存の設定
  },
  {
    "Sid": "適当な番号",
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity 認証用の文字列"
    },
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::バケットの名前/*"
  }
]
変更した設定
[
  {
    // 既存の設定
  },
  {
    "Sid": "適当な番号",
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity 認証用の文字列"
    },
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::バケットの名前/private/*"
  }
]

設定のテスト

AWS の設定はこれで終わり。以下でちゃんとアクセス制限されてるか確認する。

S3の private/ にファイルをアップロードし、S3はAccessDenied 、CloudFrontは MissingKey エラーになって見れないことを確認する。

見れちゃう場合は設定が間違ってるのでS3バケットポリシーが適切に設定されてるか確認する。また CloudFront は設定変更が整うまで結構時間かかるのでステータスが delpoying になってないか確認する。

次の手順通りに署名付きのURLを発行し、見れることを確認する。
Perl を使用して URL 署名を作成する - Amazon CloudFront 開発者ガイド

実装

https://qiita.com/chorori/items/162fead6f9b5d4a933f2
こちらの記事の通り。
リクエストしたユーザの権限をチェックしてチェックが通った場合だけ署名付きURLを発行するようにすればよい

参考ページ

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1