この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
CloudFront の設定項目「Restrict Bucket Access」と「Restrict Viewer Access」がそれぞれどのような役割をもっているか理解が曖昧だったので実験で検証してみました。
TL;DR
- S3バケット上のオブジェクトのACLをprivateにすると一般ユーザはS3のURLでオブジェクトへのアクセスが行えなくなる。
- Restrict Bucket Access を Yes に設定すると、ユーザ自身の代わりに「オリジンアクセスアイデンティティ」に設定された権限によりS3にアクセスできるようになる。
- Restrict Viewer Access を Yes にすると、署名付きURL(または署名付きCookie)によるアクセスしか許可しなくなる。
- Restrict Bucket Access を Yes, Restrict Viewer Access を No の組み合わせで設定したら、署名付きURL/署名なしURLいずれでもアクセス可能となる。さらに署名付きURLの期限が切れていても問題なくアクセスできてしまうので注意‼️
上記については以下の公式ドキュメントに詳しく記載されています。(といっても初見ではイマイチ理解できなかったので結局検証したんですが…😅)
CloudFront を使用してプライベートコンテンツを供給する – Amazon CloudFront
実験内容
実験方法は以下のとおり。
- S3 バケットのオブジェクトは private (オーナー以外のアクセス権なし)と、public(EveryoneのRead権あり)の 2 種類用意。
- S3 バケット自身には以下のように CloudFront のオリジンアクセスアイデンティティによる参照アクセスを許可(以下は例のためIDとかバケット名は存在しないものになっている)
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity xxxxxxxxxxxxx"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::xxxxxx-bucket/*"
}
]
}
- CloudFront で Restrict Bucket Access, Restrict Viewer Access それぞれの設定の組み合わせによって、S3の public/private それぞれのオブジェクトへのアクセス結果がどのようになるか検証。
実験結果
実験の結果は以下のとおり
実験の結果以下のことがわかりました。
(以下では、Restrict Bucket Access を “Bucket”、Restrict Viewer Access を “Viewer” と表現してます)
- Bucket:YES, Viewer:YES の場合:
- 現時点で有効な署名付きURLでのみアクセス可能。
- 署名無しのURLでアクセスするとステータス 403 でXMLのエラーメッセージとして”Missing Key”が返ってくる。
- Bucket:YES, Viewer:NO の場合:
- 署名付きURL/署名なしURLいずれでもアクセス可能。
- しかも、署名付きURLの有効期限が切れてもアクセス可能。
- Bucket:NO, Viewer:YES の場合:
- publicなS3コンテンツに署名付きURLでのみアクセス可能。
- privateなコンテンツに署名付きURLでアクセスすると、ステータス 403 でXMLのエラーメッセージは”Access Denied”が返ってくる。
- privateなコンテンツに署名なしURLでアクセスすると、ステータス 403 でXMLのエラーメッセージは”Missing Key”が返ってくる。
- Bucket:NO, Viewer:NO の場合:
- privateなコンテンツには一切アクセスできない。
- publicなコンテンツには署名付き/署名なしいずれのURLでもアクセス可能。
この結果で予想外だったのが2番目のケースで、「署名付きURLの有効期限が切れていたとしても関係なく普通にアクセスできる」という点でした。
Restrict View Access で署名付きURLによるアクセス制限をかけていないので、当たり前と言えば当たり前のことなんですが、予想外の結果でびっくりしました。
もし設定をミスっても署名付きURLで普通にアクセスできてしまい、あえて有効期限切れの場合のテストを行わないと設定ミスに気付かずそのまま本番運用…😱 なんてことにならないように注意が必要ですね。
まとめ
CloudFont + S3 でプライベートなコンテンツを配信する場合、S3及びCloudFrontを以下のように設定する必要がある。
- S3は以下のとおり設定する
- S3にオブジェクトをアップロードする際のパーミッションは private(オーナーのみアクセス可能)とすること
- S3バケットはバケットポリシーでオリジンアクセスアイデンティティによるアクセスを許可すること
- CloudFront ディストリビューションは以下のとおり設定する
- Restrict Bucket Access を Yes に設定し、S3のバケットポリシーで許可されているオリジンアクセスアイデンティティでS3にアクセスするように設定すること
- Restrict Viewer Access を Yes に設定し、署名付きURLによるアクセスを必須とすること
設定内容を正しく理解して安全にシステムを運用したいですね。