がじぇったー

お金と家電とプログラミングのブログ

【AWS】CloudFront→S3の構成においてサブディレクトリへのアクセスでもindex.htmlの補完を有効化する方法

こんにちわ

がじぇったー (@hackmylife7) | Twitter


です。


掲題の通りであるが、デフォルトでS3のサブディレクトへのアクセスはindex.html置いていても表示されない。

ユースケースとしてはS3バケットの複数ディレクトリでコンテンツを管理し、index.htmlを表示したい、というケースである。


それを実現する方法を記載する




TL;DR(要約)

  • S3のサブディレクトリへのアクセスでindex.htmlの補完を有効にするには、

方法が考えられ、企業内で使うなら後者の方がバケットポリシーでアクセス元をCloudFrontに絞れるため、おすすめする。さらにCloudFrontの前段にWAFを設置することにより、アクセス元IPを社内環境に制限することができる。

どの実装方法がおすすめか

個人サイトならば前者のWEBサイトホスティングの機能を有効化する方が簡単であるが、
企業内で実装するならば後者のLambda@Edgeを用いる方法がおすすめである。


何故ならば静的WEBサイトホスティングを有効化する実装の場合、ホスティング機能を有効にしつつバケットポリシーでアクセス元のIPを絞る、という制限をかけることができないからである。

基本的にWEBホスティングの方法をとる場合、グローバルからアクセスできるようにしなければ、機能が有効化されず、
つまりサブディレクトリのindex.htmlの補完も有効化されない。


企業で使うのであれば、開発環境やステージング、本番環境があり、本番環境以外へのアクセス経路は社内IPから飲みに絞りたいはずである。

しかし静的WEBサイトホスティングを有効化すると、
バケットポリシーのCondition節などを使ってアクセス元IPを絞ったり、ヘッター等で制限をかけることはできない
例えば以下のようなポリシーで制限をかけるとコンテンツにはアクセスできず、403が返ってくる

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "2",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::test-bucket/*",
            "Condition": {
                "StringLike": {
                    "aws:name": "test-header"
                }
            }
        }
    ]
}


もう少し詳細をいうと、CloudFront のオリジンアクセスアイデンティティは S3 バケットを S3 オリジンとして設定した場合にのみ利用することができ、
S3 のウェブサイトホスティング機能を有効化し、ウェブサイトエンドポイントを CloudFront のオリジンとして指定した場合、そのオリジンはカスタムオリジンとして認識される。

そのため、ウェブサイトエンドポイントをオリジンとして指定する際は、オリジンアクセスアイデンティティによるアクセス制限が行えず、その結果 403 エラーが発生する。

補足

オリジンアクセスアイデンティティ

オリジンアクセスアイデンティティを使用して Amazon S3 コンテンツへのアクセスを制限する
Amazon S3 バケットから配信するコンテンツへのアクセスを制限するには、CloudFront 署名付き URL または署名付き Cookie を作成して Amazon S3 バケット内のファイルへのアクセスを制限してから、オリジンアクセスアイデンティティ (OAI) という特別な CloudFront ユーザーを作成して配布に関連付けます。次に、CloudFront が OAI を使用してファイルにアクセスしてユーザーに提供できるようにアクセス許可を構成しますが、ユーザーは S3 バケットへの直接 URL を使用してファイルにアクセスすることはできません。これらのステップを踏むことは、CloudFront を通じてあなたが提供するファイルへの安全なアクセスを維持するのを助けます
オリジンアクセスアイデンティティを使用して Amazon S3 コンテンツへのアクセスを制限する - Amazon CloudFront


Lambda@Edgeをおすすめする理由は、WEBサイトホスティングの機能を有効化しないで使える→つまりアクセス元をバケットポリシーでクラウドフロントに絞ることができるからである


具体的にはLambda@Edge を使用し、受け取ったリクエストの URL のパスの末尾が / だった場合に、
URL に index.html 等のオブジェクトをパスに追加する関数を作成し、リクエストがオリジンに転送されるよりも前にサブディレクトリの補完を行う

そのため、サブディレクトリの補完のために S3 ウェブサイトホスティング機能を有効化する必要がなく、S3 オリジンのオリジンアクセスアイデンティティ機能によるアクセス制限を使用できる。


詳しい実装方法は下記のドキュメントを参照してください

注意点としては、2019年11月20日現在、Lambda@Edgeを用いた方法で実装するにはバージニア北部リージョンにLambdaとS3を設置しなければならないことである

CloudFrontはリージョングローバル なので、気にする必要はない。



Implementing Default Directory Indexes in Amazon S3-backed Amazon CloudFront Origins Using Lambda@Edge | AWS Compute Blog

できた!S3 オリジンへの直接アクセス制限と、インデックスドキュメント機能を共存させる方法 | Developers.IO