[AWS][やってみた] API Gateway を用いて、S3 で静的ウェブサイトホスティングで公開したVue アプリをHTTPS化してみた。

コンストラクションソリューション 開発部の橋崎です。

API Gateway を用いて、S3 で静的ウェブサイトホスティングで公開したVue アプリに対してHTTPSでアクセスできるようにしてみました。その際の手順を紹介します。Vue の勉強がてら、いろいろと試行錯誤をしていた時に見つけた方法です。

かわいい犬

画像と以下の内容には関係がありませんが、和みますね。


サーバレスなシングルページアプリケーション (SPA) を、Amazon S3 の静的ウェブサイトホスティング機能を用いて構築して、かつ、それをHTTPS化をしたいという要求はたびたび起こることかと思います。Amazon による下記の公式ドキュメントでは、CloudFront を使用して Amazon S3 バケットに対する HTTPS リクエストを処理する方法が述べられています [4]。
CloudFront を使用して Amazon S3 バケットに対する HTTPS リクエストを処理する

CloudFront はコンテンツ配信ネットワークとしての目的が第一であることを考えると、個人的には「スズメを撃つのに大砲を使う」感がありました。一方で、Nginx のような Web サーバをリバースプロキシとして使うという手段も考えられますが、これだとせっかくのサーバレス構成の良さを失ってしまいます。そこで、CloudFront や Nginx を使うことなく、S3 で公開するSPA を HTTPS 化する方法はないか? そうして、しばらく検索をしたところ、Stack Overflow[5] に次のような回答を見つけました。
In AWS API Gateway, you can create a proxy resource /{proxy+} that maps to s3-website.

API Gateway をプロキシとして用いることで実現できる、と。ただし、回答者は、この手法は十分に良い方法であるとは言えないと断っています。ひとつは、返しうるエラーコードをすべて手動で設定しなくてはならない点。もうひとつは、ひとつのリクエストあたりのペイロードが10MBに制限される点を挙げています。なので、静的ウェブサイトホスティングの HTTPS 化には、CloudFront の使用をまずは検討してください。ただ、実際にAPI Gatewayを使ってやってみたというひとは珍しいと思いますので、Vue の初期プロジェクトが HTTPS リクエストで見られるようになるまでの手順を公開します。あくまでも「やってみた系」のネタ記事として、あるいはAWS アンチパターンの他山の石として、割引いて読んでくださると幸いです。


    • 手順1

まず、Vue の初期プロジェクトをビルドして、S3 の静的ウェブサイトホスティングの機能をつかって、公開します。このやり方については、例えば、[7]を参考にしてください。すると、下図のように、S3に対するエンドポイントが作成されます。そこにアクセスすると、Vue アプリ(プロジェクトの初期画面)が表示されます。しかし、ここには HTTPS でアクセスすることはできません。

    • 手順2

Identity and Access Management (IAM) の画面から、 API Gateway に設定するためのロールを作ります。API Gateway 用のロールにデフォルトでアタッチされているポリシー AmazonAPIGatewayPushToCloudWatchLogs の他に、S3 から読み込みを行う権限も付与します。今回は簡単のために、ポリシー AmazonS3ReadOnlyAccess をアタッチしています。

    • 手順3

API Gateway の画面から REST APIを作成します。

    • 手順4

プルダウンメニュー「アクション」から、「リソースのアクション – リソースの作成」を選択します。 そして、下図、赤枠で囲ったように設定して、ボタン「リソースの作成」をクリックしてください。

    • 手順5

メソッド “ANY” のセットアップをします。「エンドポイント URL」を “https://s3.ap-northeast-1.amazonaws.com/<S3バケット名>/{proxy}”、残りの項目を下図のように設定して、ボタン「保存」をクリックします。

    • 手順6

メソッド “ANY” の「メソッドリクエスト」において、「HTTPリクエストヘッダー」に対して、”Accept”と”Content-Type”を設定します。

    • 手順7

メソッド “ANY” の「統合リクエスト」を下図のように設定します。とりわけ、「パス上書き」には、”<S3バケット名>/{proxy}”を、実行ロールには、手順2で作成したものを設定してください。

    • 手順8

メソッド “ANY” の「メソッドレスポンス」において、「200のレスポンスヘッダー」を”Content-Type”、「200のレスポンス本文」の「コンテンツタイプ」を “text/html”、「モデル」を”Empty”として設定します。

    • 手順9

メソッド “ANY” の「統合レスポンス」において、「ヘッダーのマッピング」の「レスポンスヘッダー」を”Content-Type”、「マッピングの値」を” integration.response.header.Content-Type”に設定します。残りの項目も下図のように設定してください。

ここまでで、メソッド “ANY”はつぎのようになっています。

    • 手順10

画像を表示できるようにするために、バイナリメディアタイプを追加する必要があります。API Gateway の左ペインから「設定」をクリックし、バイナリメディアタイプとして”image/*”を追加します[1]。

    • 手順11

プルダウンメニュー「アクション」から、「API – APIのデプロイ」を選択します。そして、「新しいステージ」としてデプロイします。ここでは、ステージ名を「test」としています。

    • 手順12

API Gatewayの画面から、API Gateway にアクセスするために用いるカスタムドメインを作成します。またこの際に、赤枠で示した部分のように、カスタムドメインに対応した AWS Certificate Manager 証明書をプルダウンメニューから選択してください。これが、TLS / SSL 通信で使用される証明書となります。

    • 手順13

API マッピングを追加します。手順3で作成したAPIと、手順11でデプロイしたステージをプルダウンメニューから選択してください。

    • 手順14

カスタムドメインをRoute 53 に登録します。詳しい手順は、[2]をご参照ください。

    • 手順15

URL “https://<カスタムドメイン>/index.html” にアクセスします。すると、下図のようにHTTPS を使ったアクセスが成功します。


参考文献:
[1] Amazon.com, Inc. REST API のバイナリメディアタイプの使用 – Amazon API Gateway. Amazon Web Services. https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-payload-encodings.html
[2] Amazon.com, Inc. ドメイン名を使用してトラフィックを Amazon API Gateway API にルーティングする – Amazon Route 53. Amazon Web Services. https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/routing-to-api-gateway.html
[3] Amazon.com, Inc. チュートリアル: HTTP プロキシ統合を使用して REST API をビルドする – Amazon API Gateway. Amazon Web Services. https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-http.html
[4] Amazon.com, Inc. (2020, September 20). CloudFront を使用して Amazon S3 バケットに対する HTTPS リクエストを処理する. Amazon Web Services, Inc. https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudfront-https-requests-s3/
[5] https on S3 WITHOUT cloudfront possible? (2017, February 24). Stack Overflow. https://stackoverflow.com/questions/42441828/https-on-s3-without-cloudfront-possible
[6] Iravani, Justin. (2017, June 8). How to use Amazon API Gateway {proxy+}. 1Strategy. https://www.1strategy.com/blog/2017/06/06/how-to-use-amazon-api-gateway-proxy/
[7] きよきよ. (2019, November 12). Amazon S3でSPAをサクッと公開する. Qiita. https://qiita.com/kiyokiyo_kzsby/items/77bdb81a1ce1852b30ca
[8] 水垣. (2020, August 26). CloudFrontを使わずにS3をカスタムドメイン+HTTPS化してみる. Serverworks ENGINEER BLOG. https://blog.serverworks.co.jp/s3-custom-domain-https

※この記事は、すべての環境において同様な結果が得られることを主張するものではありません。また、実行結果によって、不具合や不都合が生じた場合についても、著者およびエコモットは一切の責任を負いません。