CloudFront×S3でセキュアに静的サイトを配信をする

こんにちわ。
システムソリューション部のリンです。
インフラエンジニア3年目に突入した私ですが、ようやく「S3についてあまり知らないので、勉強してみようかな~('ω')」と思いながら、ネットサーフィンしていたら、こんな記事を見つけました。
「次は、Cloudfrontと連携して配信を行う方法を書きたいと思います。」と絞められているものの記事が無かった為、せっかくなので約9年の時を経て、リレー形式で書いてみたいと思います。
全体の流れ
S3バケットの作成
↓
バケットにhtmlファイルのアップロード
↓
CloudFrontディストリビューションの作成
↓
S3バケットのポリシー設定
↓
アクセスしてみる
実際にやってみる
S3バケットの作成
① S3コンソールに移動後、「バケットの作成」をクリックします。

② バケットタイプは「汎用」を指定し、バケット名を入力します
※ バケット名は世界中で一意である必要があります。

③ その他の設定はデフォルトでOKなのですが、パブリックアクセス設定で「パブリックアクセスを全てブロック」となっている事を確認してください。
※今回はCloudFrontを経由してのみ、S3バケット内のファイルを配信出来る様にしたい為です。

③ 確認が出来たら、「バケットを作成」をクリックして下さい。

作成できました!
④ファイルをアップロードする
バケット一覧画面からバケット名を押下 > アップロード

表示させたい静的ファイルをアップロードします。
今回私は、こちらのhtmlファイル(index.html)をアップロードしました。(ChatGPT作)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ありがとう</title>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E%0A%20%20%20%20%20%20%20%20body%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20font-family%3A%20Arial%2C%20sans-serif%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20background-color%3A%20%23f0f0f0%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3A%20%23333%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20text-align%3A%20center%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20padding%3A%2050px%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20h1%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20font-size%3A%202.5em%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20p%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20font-size%3A%201.2em%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" />
</head>
<body>
<h1>この記事を読んでくれてありがとう!</h1>
<p>CloudFront×S3でセキュアに静的サイトの配信を学んでいただけたでしょうか。</p>
</body>
</html>
CloudFrontの設定
配信したいファイルの設置が完了したので、続いてCloudFrontの設定を行っていきます。
CloudFront > ディストリビューションを作成 と画面遷移してください。
| 設定項目 | 値 |
| Distribution options | Single website or app |
| Origin domain | 作成したS3バケット |
| 名前 | 任意で指定 |
| オリジンアクセス | Origin access control settings (recommended) |
オリジンアクセス に「Origin access control settings (recommended)」を選択したら、OAC(origin access control)を新規作成していきます。


OACが作成出来たら、Origin access controlに自動で今作成したOACが入ります。
その他の設定項目はデフォルトでOKなので、ディストリビューションの作成を押下します。
こんな感じでディストリビューションが作成できていればOKです!

ちなみに OAC(Origin Access Control) とは?
CloudFrontからS3バケットへのアクセスを制御するポリシーです。
CloudFrontからの要求をS3バケットが認識し、それ以外からのアクセスをブロック出来る様になります。
またOACはOAI(Origin Access Identity)の後継として2022年に登場しました。
OACはOAIよりも詳細なポリシー設定が可能で、OAIではサポートされていなかった以下についてもサポートされています。
・AWS KMS による Amazon S3 サーバー側の暗号化 (SSE-KMS)
・Amazon S3 に対する動的なリクエスト (PUT と DELETE)
S3バケットのポリシー設定
CloudFront > ディストリビューション > 作成したディストリビューションを押下 > オリジンのタブを押下
選択したオリジンに対して「編集」を押してください。

オリジンアクセスまで移動し、画像のように表示されているポリシーをコピーしてから、S3バケットのアクセス許可に遷移してください。

S3バケットの画面に遷移したら、アクセス許可のタブを選択、バケットポリシーを編集します。

先ほどコピーしたポリシーを貼り付けし、変更を保存してください。
ちなみにコピーされるポリシーは下記の様になります。
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::cloudfront-s3-rin-test-bucket/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::xxxxxxxxxx:distribution/EE49MGYO530OK"
}
}
}
]
}
各ポリシーの意味 (重要ポイントのみ抜粋)
| Principal | CloudFrontのサービスが指定されています。 これにより、CloudFrontのみがS3バケットのオブジェクトにアクセスできます。 |
| Action | "s3:GetObject"は、オブジェクトを取得するための許可を示しています。 |
| Resource | バケット内のすべてのオブジェクトを指定しています。 |
| Condition | 特定のCloudFrontディストリビューションからのリクエストのみを許可するためのものです。 |
ここまで来れば準備完了です!
アクセスしてみる
今回は独自のドメインを紐づけていないので、ディストリビューションドメインに直接アクセスしていきます。
ディストリビューションドメイン名は、ディストリビューションの一般から確認できます。

無事アップロードしたHTMLファイルを表示できました!

S3のパブリックアクセスができないことも確認しておきたいので、S3のURLにもアクセスしてみます。

想定通りAccessDeniedになっていますね!
2