罠の概要
CloudFormationを用いて、以下のような構成でAWS上のインフラを構築した。
- CloudFront
- HTTPS化・キャッシュ
- S3
- 静的サイトホスティング
構築完了後、CloudFrontで生成されたディストリビューションドメインにアクセスするとAccessDenied
で拒否された。
調べると、CloudFrontのディストリビューションドメインにアクセスしたはずが、URLがS3オリジンのものになっている。ネットワークの状況を見ると307リダイレクトされていた。
以上の罠があったので備忘録をかねて記事にする。
解決策
今回の問題の解決策を手っ取り早く知りたい人のために、私が解決に至った方法を先に提示しておく。
この問題の原因は、CloudFrontとS3のリージョンにおける兼ね合いにある。どうやら、S3オリジンをデフォルトにした場合、CloudFrontはus-east-1のS3バケットを見に行き、そこにない場合は即座に反映してくれないようである。(最悪24時間程度かかるらしい)
対策としては以下を行えば良い。
AWSコンソールから構築した場合
ディストリビューションの作成時にリージョン名を追加する。
参考:https://dev.classmethod.jp/articles/s3-cloudfront-redirect/
CloudFormationを用いて構築した場合
テンプレート上でCloudFront.DistributionConfig.OriginsからS3オリジンを参照している箇所を以下のように書き換える。
Before
CloudFront:
Properties:
DistributionConfig:
Origins:
- DomainName: !GetAtt TargetBucket.DomainName
After
CloudFront:
Properties:
DistributionConfig:
Origins:
- DomainName: !Sub "${TargetBucket}.s3.${AWS::Region}.amazonaws.com"
自身がハマった現象について
自身も解決策で提示した[before]の設定でインフラ構築をしていた。
当然アクセスが拒否される中で、リージョン名が設定できていないことを疑いCloudFrontの設定を見に行ったのだが、以下の画像のようにしっかりとリージョン名は設定されていた。
しばらく沼にはまっていたが、ここであることに気づく。ページを開いてからオリジンドメインにxxx.s3.ap-northeast-1.amazonaws.com
が表示されるまでに一瞬間がある。JavaScriptもしくはそれに準ずるもので書き換えがされていそうだった。
まさかと思い何も変更しないまま設定を保存すると、ちゃんとサイトへアクセスできるようになった。
「設定画面上で操作した場合に限り、AWS側で良しなにリージョン名をつけてくれるので、コンソール上は正しく設定できているように見える」 がまさかの答えだとは...
なかなかどうしてAWSと気持ちを通じ合うのは難しい...(まぁ私の設定が悪いだけなのだが)
この記事で少しでも救われる人がいますように。