超今さらS3 + CloudFront + CloudFormationでWebサイトを公開する設定についてOriginとProtocolの注意点
※ 独自ドメイン関係の話は一切ないです。あくまで公開できる状態になるまでで S3 Web Site Hosting と CloudFront の Origin の設定と Protocol の話のみです。
S3はWeb Site Hostingにすべし
最近は AWS 側で不必要に S3 Bucket を公開してしまわないように Web UI でいろいろ警告してくれるというか分かりやすくしてくれていて、「もしかして S3 の Web Site Hosting って実は使ってほしくないのかな?」という雰囲気を感じていたんだけど、どうもそういう意図はないらしい。うっかりを防ぎたいだけっぽい。
というのも、
Web Site Hosting にしておかないと IndexDocument などの機能が効かないので / で終わる Directory へのアクセスは不可能
だから。
※ 逆に、 / で終わる URI が世界に共有されないのであれば Web Site Hosting でなくてもよい。
cf. ウェブサイトエンドポイント - Amazon Simple Storage Service
CloudFrontからS3へCustom Originで繋ぐ
CloudFront から S3 を見にいく場合、S3 Origin としてアクセスしにいくか Custom Origin としてアクセスしにいくかを選べる。
結論から言うと上と同じ理由で
Web サイトとして S3 を使う場合は Custom Origin にする
のが正解。S3 Bucket としてではなくただの Web サイトとしてアクセスしにいく方式だ。
そのため、DomainName の設定は
<bucket-name>.s3-website-<region>.amazonaws.com
にしておく必要がある。
S3 Origin としてアクセスする方式でも asset や upload 済みの「ファイルだけにアクセスさせる」場合は問題ないのだが、「HTTP でリソースにアクセスできることと Web サイトとしてアクセスできることの意味は異なる」ところがポイント。
例えば上のように / で終わる URI に対して CloudFront にアクセスがあった場合、CloudFront は S3 に対してもまったく同じように / というリソースを要求するのだが、これは S3 Object としては存在しない。あくまで S3 上では Object として存在しているのではなく Prefix として機能しているだけなので、これにアクセスすることはできないのだ。
※ トップページ / に対してだけは DefaultRootObject を設定できるのがまた事態をややこしくしている。これは本当にトップの / に対してだけしか効かない。
もし / で終わる URI にアクセスできているとしたら、それは Web Site Hosting 機能の IndexDocument のおかげである。そして Web Site Hosting に対して CloudFront からリクエストするためには Custom Origin にしておく必要がある。
ウェブサイトエンドポイント - Amazon Simple Storage Service
仕上げにCloudFrontからS3へはhttp-onlyで繋ぐ
CloudFront は Origin を複数設定できるのだが、CloudFormation の設定を YAML で書くとすると、
Origins:
- Id: <Name>
CustomOriginConfig:
OriginProtocolPolicy: http-only
としておくのが正解。
CustomOriginConfig では OriginProtocolPolicy が required なのでこれを http-only にしておく。
- CloudFront ディストリビューションの DistributionConfig - AWS CloudFormation
- CloudFront ディストリビューションのオリジン - AWS CloudFormation
- CloudFront ディストリビューションの CustomOriginConfig - AWS CloudFormation
順番に見ていくと、
- Origins の設定のところには S3OriginConfig か CustomOriginConfig のいずれかが required
- S3 Website Hosting に接続するには CustomOriginConfig が required
- CustomOriginConfig を設定するためには OriginProtocolPolicy が required
という寸法。
S3のWeb Site Hostingはhttp-only
ウェブサイトエンドポイント - Amazon Simple Storage Service
S3 の Web Site Hosting の機能で提供されるのは上の「ウェブサイトホスティング」に該当する。
ということは「SSL 接続をサポートしません」なので、上のように
Origins:
- Id: <Name>
CustomOriginConfig:
OriginProtocolPolicy: http-only
で http-only にしておくのが正解。これで CloudFront へのアクセスが http でも https のどちらであっても、S3 へは http で接続しにいく。
これを指定しておかずにうっかり https でリクエストすると謎の timeout に苦しむことになる。
cf.
おまけ
CloudFormation を使えば確かに設定をコードで管理できるようにはなるが、決してお手軽に設定できるわけではない。
その設定になる理由はすべて資料と現象の観測と収集できる情報から掘り下げていくしかない。
例えば CloudFront で /path/to/resource/ へアクセスすると timeout するが /path/to/resource/index.html へアクセスすれば ok 、http ではアクセスできて https でアクセスできない、といったことは順番に試して現象を観測して分類、整理して解決していくしかない。
そうたくさんくり返すわけでもないこの手の作業こそ基本が大切。