はじめに
こんにちは、やくもです。
今回はCloudFrontとS3を使った静的ウェブサイトの配信についてです。
この辺は業務でもがっつり触ったこともあまり無いですが、試験では頻繁に出るイメージなので実際に触ってみて色々知見を得ることができました。
なぜCloudFrontとS3 なのか
静的コンテンツ配信だとこの組み合わせは王道(?)とよく言われています。
S3単体でも静的サイトのホスティングは可能ですが、CloudFrontを組み合わせることでより高速に安全にコンテンツの配信を行うことができます。
具体的なメリットは以下になります。
- 高速なコンテンツ配信: エッジロケーションからのキャッシュ配信により、世界中どこからでも低レイテンシでアクセス可能
- コスト削減: S3 へのリクエスト数を削減し、データ転送コストも最適化
- セキュリティ向上: S3 バケットを非公開にし、CloudFront 経由のみアクセスを許可
今回作ったもの
今回はシンプルな静的 Web サイトを CloudFront と S3 で配信する環境を構築しました。
- S3 バケットは完全非公開(パブリックアクセス全ブロック)
- Origin Access Control(OAC)による安全なアクセス制御
- HTTPS 通信の強制
- キャッシュによる高速配信
構築手順
それでは、実際に環境を構築していきます。
S3バケットの作成
まず、静的コンテンツを格納する S3 バケットを作成します。
バケットのパブリックアクセスがオフになっていることを確認します。
バケット作成後、以下のようになります。
コンテンツの作成とアップロード
動作確認のため、実際に表示するHTMLファイルを作成、格納します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CloudFront + S3 デモサイト</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 50px auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1 {
color: #232F3E;
}
</style>
</head>
<body>
<div class="container">
<h1>CloudFront + S3 で配信中!</h1>
<p>このサイトは Amazon CloudFront と S3 で配信されています。</p>
<p>高速で安全なコンテンツ配信が実現できました!</p>
</div>
</body>
</html>
作成した上記のhtmlファイルをS3にアップロードします。
CloudFrontの設定
次に、CloudFront Distribution を作成します。
今回は無料プランで実施しています。
オリジンの作成や設定を行います。
先ほど作成したバケットを指定します。
デフォルトルートオブジェクトでindex.htmlを入力
また、そのほかのオプションでWAFなどの設定を有効にできますが今回はすべてデフォルトにしておきます。
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:::hogehoge/*",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:cloudfront::hogehoge/gehogeho"
}
}
}
]
}
アクセスしてみる
それでは実際にアクセスして動作を確認します。
作成したディストリビューションの画面を開き、「ディストリビューションドメイン名」をコピーしブラウザで開きます。

以下のようにS3に用意していたコンテンツが表示されれば成功です。
エラーが発生する場合
アクセス時、以下のようにアクセスエラーが発生する場合があります。原因は大体以下です。
- バケットポリシーの権限不足
- 指定したファイル名の誤り
- デフォルトルートオブジェクトの指定誤り
キャッシュの確認
2回目以降のアクセスでは、CloudFront のキャッシュから配信されます。開発者ツールで以下を確認できます。
このヘッダーが表示されれば、キャッシュから高速に配信されていることが確認できます。
セキュリティのベストプラクティス
CloudFront と S3 を使用する際のセキュリティ対策についても少しまとめておきます。
1. Origin Access Control (OAC) の使用
今回の構築で設定した OAC により、S3 バケットへの直接アクセスを完全に遮断しています。
OACを利用することによってリソースをパブリックにせず、CloudFront経由のアクセスを強制できます。
2. HTTPS 通信の強制
設定で「Redirect HTTP to HTTPS」、もしくは「HTPPS only」を選択することで、自動的にHTTPSでの通信が強制され通信が暗号化されます。
3. セキュリティヘッダーの追加
CloudFront Functions を使用して、レスポンスにセキュリティヘッダーを追加できます。
今回はAWSサンプルを用意してくれていたので、そちらを使用してみました。必要に応じて機能拡張などしてみて下さい。
function handler(event) {
var response = event.response;
var headers = response.headers;
// Set HTTP security headers
// Since JavaScript doesn't allow for hyphens in variable names, we use the dict["key"] notation
headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubdomains; preload'};
headers['content-security-policy'] = { value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"};
headers['x-content-type-options'] = { value: 'nosniff'};
headers['x-frame-options'] = {value: 'DENY'};
headers['x-xss-protection'] = {value: '1; mode=block'};
// Return the response to viewers
return response;
}
適用後、再度CloudFrontにアクセスして、セキュリティヘッダが追加されていることを確認します。
4. AWS WAF の導入(オプション)
り高度なセキュリティが必要な場合、AWS WAFも導入できます。
少しコストがネックになってくるので、今回は使っていません...
さいごに
CloudFront と S3 を組み合わせることで、高速・安全・低コストな静的コンテンツ配信環境を構築してみました。
試験勉強の知識だけでなく、改めて使ってみないとわからない学びも多かったのでやってみてよかったです。この記事がみなさんの参考になれば幸いです。
参考











