13
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SGG(すごくなりたいがくせいぐるーぷ)Advent Calendar 2020

Day 20

nuxt generate+S3+CloudFrontで403エラーを防ぐ方法

Last updated at Posted at 2020-12-20

nuxt generate+S3+CloudFrontで403エラーを防ぐ方法

本記事はSGG(すごくなりたいがくせいぐるーぷ) Advent Calendar 2020の20日目の記事になります。

はじめに

CloudFrontではデフォルトルートオブジェクトを設定できるため、http://ドメイン名/index.htmlにアクセスしたい場合、デフォルトルートオブジェクトにindex.htmlを設定すればhttp://ドメイン名にアクセスしても該当ページが表示されます。

しかし、デフォルトルートオブジェクトの設定はサブディレクトリには効かないため、http://ドメイン名/hoge/index.htmlへアクセスしたい場合に、http://ドメイン名/hogeとしてしまうと403エラーが発生します。

そのため、nuxt generateで生成したファイルをS3+CloudFrontで静的ホスティングした場合、ルート以外のパスに直接アクセスしたりリロードしたりすると、403エラーが返ってしまいます。

/
 index.html //←`http://ドメイン名`でアクセス可能
 hoge/
    index.html //←`http://ドメイン名/hoge`ではアクセスできない

このエラーの回避方法はいくつかあり、いろいろな方が記事を書いて下さっています。

しかし、前者はLambda@Edgeを実装するのに少し手間がかかり(加えて僕の環境では動作しませんでした。多分僕のやり方が悪い。)、後者はエラーが起きたらトップページにリダイレクトさせるという仕様になってしまいます。

そこで、S3の静的ウェブサイトホスティングと組み合わせるという方法を考えました。

概要

前述の通り、CloudFrontのデフォルトルートオブジェクトはサブディレクトリに適用されません。
しかし、S3の静的ウェブサイトホスティングでインデックスドキュメントにindex.htmlを設定すると、サブディレクトリを指定した場合でもサブディレクトリ配下のindex.htmlを返してくれます。

/
 index.html //←`http://ドメイン名`でアクセス可能
 hoge/
    index.html //←`http://ドメイン名/hoge`でアクセス可能

また、静的ウェブサイトホスティングの設定をする場合、S3バケットのパブリックアクセスを許可しなければなりませんが、これをするとバケットへ直接アクセスできる様になってしまいます。

これはセキュリティ的によろしくないので、Refererヘッダーを使ってアクセス制限をかけ、CloudFrontディストリビューションからしかアクセスできないようにしていきます。

実装方法

S3バケットを作成し、Webサイトをアップロード

割愛

S3で静的ホスティングの設定を行う

まずはS3でWebサイトを静的ホスティングします。

「プロパティ」→「静的ウェブサイトホスティング」から静的ウェブサイトホスティングを有効にし、インデックスドキュメントにindex.htmlを指定します。

スクリーンショット 2020-12-20 14.41.53.png

設定が完了すると以下の様にエンドポイントが表示されます。
後ほど使用するため、メモしておきましょう。

スクリーンショット 2020-12-20 14.49.16.png

CloudFrontを作成

次に、CloudFrontを作成します。

※すでにCloudFrontを作成済みの場合は、該当ディストリビューションを開き、「Origins and Origin Groups」から現存するOriginを以下手順と同じように書き換えてください。

「Create Distribution」からWebを選択します。

スクリーンショット 2020-12-20 14.51.52.png

Origin Domain Nameに、「静的ウェブサイトホスティングのエンドポイントからhttp://を除いたものを設定します。

例: http://XXXXX.s3-website-ap-northeast-1.amazonaws.comXXXXX.s3-website-ap-northeast-1.amazonaws.com

また、Origin Custom Headersの、Header NameRefererValueにランダムな文字列(暗号論的擬似乱数など)を設定してください。

スクリーンショット 2020-12-20 15.00.30.png

残りの項目はユースケースに合わせてよしなに設定してください。

S3バケットポリシーの設定

バケットポリシーを介したパブリックアクセスをブロックしているとアクセスができないため、S3バケットのページに戻り、「アクセス許可」から「ブロックパブリックアクセス」を開き、下2つを解除します。

スクリーンショット 2020-12-20 13.47.48.png

次に、バケットポリシーを以下のものに変更します。

<バケット名>と<CloudFrontのOrigin Custom Headersで設定したランダム文字列>は該当のものに書き換えてください。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<バケット名>/*",
            "Condition": {
                "StringLike": {
                    "aws:Referer": "<CloudFrontのOrigin Custom Headersで設定したランダム文字列>"
                }
            }
        }
    ]
}

上記のバケットポリシーを適用することで、Refererヘッダーに正規の文字列を含んでいないリクエストをブロックすることができるため、当該CloudFrontディストリビューション以外からはバケットにアクセスできなくなります。

これで手順はすべて終わりです。

参考文献

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?