概要
API Gatewayを使うとき手が届かないむずかゆいところがたくさんあります(HTTPSのみしか受け付けないとか、前段にWAFおけないとか)。
そのときに使われるのがCloudFrontになりますが(もちろん、API Gateway内部にCloudFrontが暗黙的に使われており、多段CloudFrontになるため遅延が大きいというのは承知)、API Gatewayの前段用にCloudFront使うのもなんなのでS3オリジンの配信もやっちゃいたい、という内容です。
- CloudFront + API Gateway + S3
- S3はOAI(Object Access Identity)でアクセス制限
- API Gatewayはカスタムオリジンヘッダによるアクセス制限はしない
- めんどいので
- API Gatewayはキャッシュしない
- Route53で取得したドメインを利用
- ACMで取得した証明書をHTTPS通信に利用
アーキテクチャ構成
手順
Route53の設定(その1)
CloudFrontのエンドポイントを覚えやすいドメイン名にするため、Route53でドメイン名を取得して設定する必要があります。
- Domain Resigtration
ACM(Amazon Certificate Manager)で証明書作成
独自ドメインに対してhttpsアクセスするために証明書を作成します。
-
確定画面
設定を確認し、確定します。確定するとドメインに関連付けられているメールアドレスにValidationメールが送付されます。
-
ダッシュボード
完了までするとステータスが発行済みとなり、使用中でないことを確認してください。以後、これを使ってHTTPS通信における証明をします。
API Gatewayの設定
詳細は割愛しますが、下記手順で実施します。完了後にAPI Gatewayのデプロイ完了画面が表示されるはずです。下記画像の通り、各リソースごと(メソッドごと)にURLエンドポイントが発行されています。
- API作成
- リソース作成
- メソッドの作成
- APIをステージへデプロイ
ここで使うのはURLの、「https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/prod」
までの部分です。
CloudFrontの設定(その1)
CloudFrontの設定に入ります。その1としているのは後でS3の設定が入るからです。
注意として、CloudFrontのデプロイにはめちゃくちゃ時間がかかる(20分くらい)ので、あせらず実施してください。時間のあるときにやってください。
- 注意点としては、HOSTヘッダーはForwardさせてはいけない。なぜかというとAPI Gateway自体がSNI前提のバーチャルホスト構成なのでHOSTが切り替えられなくなってしまうため。
- 見切れている下記オプションについて
- ダッシュボードに戻り、Statusが「In Progress」になります。ここから20分ほど、ぐつぐつ煮込んでください)
- StateがEnabledになったら無事完了です。
Route53の設定(その2)
CloudFrontの代替名を独自ドメインにしたのでRoute53の設定が必要です。
- 上記で取得したドメインをCloudFrontへルーティングするためにDNSリソースレコードを追加する必要があります。[DNS management]->[Domain Name]を選ぶと作成したDNSリソースが記載された画面に移動します。
- [Create Record Set]を選択
- Record setを下記の通り設定します。
- Name:ZoneApexを指定のため何も入力しない
- Type:Aレコード
- Alias:Yes
- Alias Target:CloudFrontDistribution名(xxxx.cloudfront.net.)
- Routing policy: Simple
- Evaluate Target Health: No
- Record setを下記の通り設定します。
中間CP
いったん、ここまでの設定が動作確認してみます。
- API Gatewayは単純にSuccessと返すだけのMockエンドポイントを用意し、prodステージにデプロイしました。
- リソース名:success
- ブラウザから動作確認
CloudFrontの設定(その2)
現在の設定ではAPI Gatewayに対してのパスしかないので、S3オリジンとパスを追加します。
S3のバケットプロパティの確認
CloudFrontからコンテンツ配信するために下記設定を確認してください。
-
Static website hosting:Enabledとなっていること
-
バケットポリシーはOAIのみAllowとなっていること
- 例えば以前にS3からStatic website hostingしていた場合、下記の設定が残っていることがあります。
bucket.json{ "Version": "2008-10-17", "Id": "test", "Statement": [ { "Sid": "1", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::bucket-name/*" } ] }
- 上記の場合、CloudFrontからのアクセス+S3への直接アクセスも許可していることになり、OAIで絞り込んでいる意味がないため削除し、プリンシパルがCloudFrontのみのアクセスだけ残してください。
bucket.json{ "Version": "2008-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [ { "Sid": "1", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXXXXXXXXXXX" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::bucket-name/*" } ] }
結果
長かったですが、ここまでの設定内容を確認したら完了です。
- Route53で取得したドメイン名でAPIコールが出来ること
- Route53で取得したドメイン名でS3コンテンツを取得できること
- S3のドメイン名でS3コンテンツを取得できないこと
まとめ
- CloudFront経由でAPI GatewayとS3を配信する構成を作成できました。
- CloudFrontの設定が多く結構手こずりました。
- Blackbeltの資料など読んで各設定が何を意味しているか頭にいれておくとよいです。