Amazon S3バケット内画像へのアクセスをAmazon CloudFront経由に制限してみた

CloudFrontでは、ALBなどのデフォルトのオリジンのほかに、パスパターン付きのS3をオリジンとして設定し。マルチオリジン構成を取ることがあります。そういった際に、S3側ではどういう設定が必要なのかまとめてみました。
2024.05.13

Amazon S3の画像に対して、Amazon CloudFront経由のアクセスのみに制限したい

おのやんです。

みなさん。Amazon S3(以下、S3)バケットをパブリックアクセス可能にすることなく、Amazon CloudFront(以下、CloudFront)からのアクセスのみを許可したいと思ったことはありませんか?私はあります。

CloudFrontには、S3へのオブジェクトに対してCloudFron経由のアクセスのみに制限する オリジンアクセスコントロール(以下、OAC)機能があります。AWS認定試験などでは主にオリジンアクセスアイデンティティ(以下、OAI)としてよく出てくるアクセス制限機能ですが、S3バケット側でAWS Key Management Service(以下、AWS KMS)を使った暗号化であるSSE-KMSを使用した場合に使用できないという特徴がありました。これに対して、SSE-KMSで暗号化されているS3バケットに対してもダウンロード、アップロードができるようになったのがOACです。OACの詳細は、こちらのアップデートブログにまとめられていますので参考にしてください。

CloudFrontでは、ALBやS3などの複数オリジンを設定する構成(マルチオリジン構成)が可能です。そういった際に、S3側ではどういう設定が必要なのかまとめてみたいと思います。

アーキテクチャ・アクセス方法の想定

今回は以下のアーキテクチャを想定しています。S3バケットには、imagesというフォルダを作成して、その中に画像ファイルを保存しています。この画像ファイルに対して、CloudFront経由でアクセスします。この際、CloudFrontのドメインからアクセスするのですが、パスパターンを設定して<ドメイン>/images/xxxx.pngのようなURLでアクセスできるようにします。

画像保存用S3バケットの作成

それでは、AWSリソースの作成に移っていきます。まずは、画像を保存するためのS3バケットを作成します。S3バケット作成画面では、こちらのような設定にしていきます。バケットタイプは「汎用」にして、バケット名はaws-test-images-<アカウントID>にします。

オブジェクト所有者では、「ACL無効」にします。

パブリックアクセスブロックはすべてブロックとして設定しておきます。

サーバーの暗号化などは、今回はそのままにしておきます。以上の設定ができたら、「バケットを作成」を押下してS3バケットを作成します。

S3バケットでフォルダ作成・画像アップロード

こちらのS3バケットが作成できたら、次にS3バケット内でフォルダを作成します。今回は、CloudFrontのパスパターンは/images/*に設定してあります。そのため、S3バケットに画像を保存する際にもs3-bucket-name/images/の配下に画像を保存する必要があります。

今回はアーキテクチャ図の通り、画像保存用フォルダとしてimages/を設定します。暗号化キーはデフォルトで大丈夫ですので、このままフォルダを作成します。

このimages/フォルダの中に、さきほど掲載したアーキテクチャ図の画像ファイルであるarchitecture.pngを保存しておきます。これでS3側の準備はOKです。

ちなみにこちらの画像ファイルですが、S3バケットの設定ですべてのパブリックアクセスをブロックしているため、オブジェクトURLでブラウザ上からアクセスしようとしてもAccessDeniedとなります。

CloudFrontディストリビューションの作成

それでは次にCloudFrontディストリビューションを作成していきます。ディストリビューション作成画面にて、先ほど作成したS3バケットをオリジンとして設定します。

オリジンアクセスですが、ここではOACを使ってオリジンへのアクセスを設定するため、Origin access control settings (recommended)を選択します。こちらを選択すると、項目下部にCreate new OACのボタンが表示されるので、こちらを押下します。

すると、このようにモーダルが表示されます。今回はこちらの設定のままで問題ありませんので、そのまま「Create」を押下します。

こちらが完了すると、Origin access controlの項目に作成したOACが設定されます。こちらが確認できたらOAC設定はOKです。なお、「S3バケットポリシーを更新する必要があります」の通知が表示されたかと思いますが、後ほど設定するので一旦スルーで大丈夫です。

デフォルトのキャッシュビヘイビア設定項目ではパスパターンを設定できますが、マネジメントコンソール上では最初デフォルト(パスパターンなし)から変更できません。/images/*の設定はCloudFront ディストリビューション作成後に設定するので、一旦そのままで進めます。

このビヘイビアはパスパターンがデフォルトから変更できないため使用しないのですが、一度しっかりキャッシュ設定をやっておきます。

キャッシュキーとオリジンリクエストは各々の要件に合わせて設定します。今回はアクセス制限のみ行う想定のため、キャッシュは無効(CachingDisabled)で設定しておきました。S3の画像に対してCloudFrontでキャッシュさせたい場合は、CachingOptimizedなど、それぞれ要件に合わせて設定するとよいでしょう。

その他の設定は今回はデフォルトのままで進めます。これらの設定ができたら、「ディストリビューションを作成」を押下します。

このようにディストリビューション設定がコンソール上から確認できれば作成完了です。

S3バケットポリシーを編集

次に、CloudFrontからのアクセスをS3バケットに許可するようS3バケットポリシーを編集します。CloudFrontディストリビューション画面の「オリジン」タブでオリジンとして設定したS3バケットを選択し、「編集」を押下します。

そこからオリジンアクセスの項目までスクロールしていきます。このように、「ポリシーをコピー」ボタンが表示されていますので、ここを押下してS3バケットに設定するポリシーをコピーします。正常にコピーできていると、画像のように「Policy statementをコピー済み」を表示されます。そこから「S3バケットアクセス許可に移動」を押下して、S3バケットポリシー編集画面に移動します。

するとS3バケット詳細画面に移動します。ここで「アクセス許可」タブを押下します。

こちらの画面の「バケットポリシー」の項目にて、「編集」を押下します。

バケットポリシー編集画面に遷移しますので、先ほどコピーしたバケットポリシーをペーストして保存します。これで、S3バケットポリシーの設定は完了です。

なお、今回コピーしたバケットポリシーはこのような内容となっています。CloudFrontによるS3バケットへのGet動作を、ポリシーにて許可する形となっています。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::aws-test-images-<account-id>/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::<account-id>:distribution/<distribution-id>"
                }
            }
        }
    ]
}

パスパターンの設定

最後に、パスパターンを設定していきます。今回はS3バケット上にimagesフォルダを作成して、その中に画像ファイルを格納しています。そのため、CloudFrontでもパスパターンを設定して、/images/sample.pngのようなアクセスができるようビヘイビアを設定します。

CloudFrontディストリビューション画面の「ビヘイビア」タブから「ビヘイビアを作成」を押下します。

パスパターンとして、/images/*を設定します。これで、オリジンにある/images配下のファイルを全てパスに含められるようになりました。

また、上記で一度設定したキャッシュポリシーと同じように設定します。こちらが設定できたら、ビヘイビアを作成します。

このように、パスパターンとして/images/*が表示されたビヘイビアが表示されればOKです。

実際にCloudFrontのドメインをコピーして、ブラウザ上でCloudFrontドメイン/images/architecture.pngへアクセスしてみます。するとS3バケット上ではパブリックアクセスがブロックされているにも関わらず、ファイルにアクセスできるのが確認できます。CloudFrontにてOAC設定を行ったため、S3上のファイルへCloudFront経由でのみアクセスできる状態になっている状態となります。

OACを設定することで、S3へのアクセスをCloudFront経由のものに限定できる

CloudFrontでは、デフォルトのオリジンとしてALBを、もうひとつのオリジンとしてパスパターン付きのS3を設定するマルチオリジン構成を取ることが多々あります。そういった際に、S3側ではどういう設定が必要なのか参考になるかと思います。では!