何がしたいか
S3 にアップロードして CloudFront で配信してるファイルのURLをRailsアプリで許可したユーザにしか見れなくしたくなった。
どうするか
CloudFront の署名付きURL機能をつかう。 閲覧制限時間を設定できるので、たとえそのURLが漏れたとしても(制限時間が切れてれば)悪意の第三者は閲覧できない。
ユーザが画像を見るときは以下のような手順になる。
- ユーザが制限付きの画像URL(
https://your-cloud-front-domain/private/image.jpg
とする) を含むリソース(https://your-app-domain/index.html
とする)をアプリにリクエストする - アプリは CloudFront の署名付きURL(
https://your-cloud-front-domain/private/image.jpg?認証用のクエリ
を発行する - アプリは 署名付きURLを含んだ
index.html
をユーザに返却する - ユーザは署名つき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
-
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を発行するようにすればよい