はじめに
Cloudfront
構成の場合に、一時的なメンテナンスページを表示するにはどうすればよいのかを調べて試した備忘録となる。
※今回は一例としてオリジンをS3
(静的コンテンツ表示用)とS3
(メンテナンスページ用)とする。
環境
AWS
- S3
- Cloudfront
- WAF
準備
以下の準備が完了していること
- AWSのアカウントが作成されていること
構成図
WAF
によりアクセスが許可されたもののみ、コンテンツ用のページが配信され、それ以外の場合はメンテナンスページを表示するとしている。
※今回調査するにあたり、
CloudFront Functions
を利用して実現する- WAFのルールを変更することにより実現する
上記があったが、作業者はコンテンツページを表示させたいということもありルールが簡単に定義できるWAF
で実現することにした。
全体の流れ
- 静的コンテンツ配信用のS3バケットを作成
- S3をオリジンとしたCloudFrontディストリビューションを作成
- WAFを作成し、CloudFrontと関連付け
- WAFの設定変更 (メンテナンスページ用)
- WAFの設定変更2 (メンテナンス時に特定のIPのみ許可)
作業
まずは、静的コンテンツ配信用のバケット
およびメンテナンス用のバケット
およびを作成する。
S3バケットを作成する
1. AWSコンソールより、「S3
」サービスを選択する

2. 「バケットを作成する」を選択する

3. バケットの設定を行い作成する

※後ほど、Cloudfront
経由のアクセスのみ許可するという設定にする。
そのため、「パブリックアクセスをブロックする」にはチェックを入れておくこと。
上記で、静的コンテンツ表示用のバケット
を作成した。
4. バケットを確認する
s3-static-contents-k
が作成されている。
※-k
がついているのは-k
なしでの名前が利用できなかったため。

Cloudfrontを作成する
1. AWSコンソールより、「Cloudfront
」サービスを選択する

2. ナビゲーションペインの「ディストリビューション」を選択し、「ディストリビューションを作成」を選択する

3. 設定を変更し、「ディストリビューション」を作成する

CloudFront
からのアクセスのみとしたいのでOAC
を設定する。

4. ディストリビューションが作成を確認し、バケットポリシーを更新する
「ポリシーをコピー」でコピーしておく。
その後、「S3 バケットの権限に移動してポリシーを更新する」を選択して遷移する。

5. 「アクセス許可」タブの「バケットポリシー」の「編集」を選択する

6. コピーしたポリシーを入力し「変更の保存」を選択する

7. テスト用のページをアップロードしておく
claude
に作ってもらった↓
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>テストページ</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1 {
color: #333;
text-align: center;
}
.container {
border: 1px solid #ddd;
padding: 20px;
border-radius: 5px;
background-color: #f9f9f9;
}
.test-button {
background-color: #4CAF50;
color: white;
padding: 10px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.test-button:hover {
background-color: #45a049;
}
#result {
margin-top: 20px;
padding: 10px;
border: 1px solid #ddd;
min-height: 50px;
}
</style>
</head>
<body>
<h1>テストページ</h1>
<div class="container">
<p>これはテスト用のHTMLファイルです。様々な機能をテストするために使用できます。</p>
<h2>基本的なDOM操作テスト</h2>
<button id="testButton" class="test-button">クリックしてテスト</button>
<div id="result">結果がここに表示されます</div>
</div>
<script>
// 基本的なJavaScript機能テスト
document.getElementById('testButton').addEventListener('click', function() {
const resultElement = document.getElementById('result');
const now = new Date();
resultElement.innerHTML = `
<p>テスト成功! (${now.toLocaleString()})</p>
<p>ブラウザ: ${navigator.userAgent}</p>
<p>画面サイズ: ${window.innerWidth} x ${window.innerHeight}</p>
`;
resultElement.style.backgroundColor = '#e8f5e9';
});
</script>
</body>
</html>
これを保存し、バケットにアップロードしておく。

8. 表示確認
Cloudfront
のディストリビューション名でアクセスできることを確認する。
現状の設定ではindex.html
まで指定しないと表示されないので注意

ここまでで静的コンテンツ表示用
のバケットに対する設定はできた。
WAFの設定
1. AWSコンソールより、「WAF & Shield
」サービスを選択する

2. ナビゲーションペインの「Web ACLs」を選択し、「Create Web ACL」を選択する

3. Step1でAWSリソースの関連付けを行う

- Resource type: Global resources (CloudFront Distributions)
- Associated AWS resources:
作成したCloudfrontのディストリビューション
を設定しておけばここはOK
4. Step2でルールを設定する
ここでは、まだルールの設定は行わずにデフォルトのままで進める。
実際にメンテナンスページが必要となった場合に変更をして試すことにする。

5. Step3でルールの優先順位を設定する
ルールはないのでここはスルー

6. Step4でメトリックの設定
ここもスルー

7. 設定を確認し作成する

WAFの設定変更
先ほど作成したWAF
についてカスタムレスポンスボディを設定する。
1. 「Web ACLs」から作成した設定を選択する

2. 「Custom response bodies」タブから「Create custom response body」を選択する

3. メンテナンスページの作成

以下をResponse body
に入れる。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>メンテナンス中</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
background-color: #f8f9fa;
padding: 50px;
}
.container {
max-width: 600px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
}
h1 {
color: #333;
}
p {
color: #666;
}
</style>
</head>
<body>
<div class="container">
<h1>メンテナンス中</h1>
<p>現在、システムメンテナンスを実施しております。<br>
ご不便をおかけして申し訳ありません。</p>
<p>しばらく経ってから再度アクセスしてください。</p>
</div>
</body>
</html>
WAFの設定変更2
1. 「Web ACLs」から作成した設定を選択する

2. 「Rules」タブから「Default web ACL action for requests that don’t match any rules」の「Edit」を選択する

3. 「Block」を選択し「Save」する
以下で設定を行った。
設定項目 | 内容 |
---|---|
デフォルトアクション | Block |
カスタムレスポンスの有効化 | Enable |
レスポンスコード | 503 |
レスポンスボディの指定方法 | maintenance(作成したカスタムレスポンス) |

4. 確認
CloudFront
のディストリビューション名でアクセスし、メンテナンスページが表示されることを確認

WAFの設定変更3
今度は自IPの場合はメンテナンスページを表示したくないため、IP Sets
を設定する。
1. ナビゲーションペインから「IP Sets」を選択し、「Create IP Set」を選択する

2. IP addressesに許可IPを設定する
※はじめはIPv4
で指定していたが上手く動作しなかったため、IPv6
で作り直した。

3. ナビゲーションペインから「Web ACLs」を選択し、作成した設定を選択する

4. 「Rules」タブから「Add rules」の「Add my own rules and rule groups」を選択する

5. Ruleを設定する
ルールとして先ほど作成したIP set
を選択する。
6. 動作確認
自分のIPでアクセスした時は表示されることを確認できる。

これで動作確認はOK
気になった点
この構成だと、以下が問題になるのではないかと思った。
※多分、Terraform, aws-cli, Lambdaなどで自動化する必要がありそう。
- メンテナンス時にWAFをつけたりかえたりしないといけない ※既存のWAFルールに追加する形だと問題が発生する
参考
AWS WAFでメンテナンスモード(アクセス制限)
https://qiita.com/mitzi2funk/items/7dfd07ec00b916b8dfc6AWS/WAFでメンテナンスページを表示する
https://zenn.dev/not75743/articles/c65556b642a599AWS CloudFrontでメンテナンスページに切り替える方法
https://zenn.dev/nnydtmg/articles/aws-cloudfront-maintenancepageCloudFront + S3の静的ホスティングでメンテナンス画面の表示
https://qiita.com/kosukeobata/items/2d45cf93455ddbdc1d2cHTTP 503 を返すメンテナンス画面を CloudFront と S3 を使って構築する方法
https://zenn.dev/toyocy/articles/1717a0d06eb9adAmazon S3 を使用して静的ウェブサイトをホスティングする
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/WebsiteHosting.html
おわりに
S3
+Cloudfront
構成でメンテナンス画面を表示するということをやってみた。S3
のバケットを2つ用意して、S3
のカスタムレスポンスでやってみる~だとだめだったので、WAF
のカスタムレスポンスでやった。
うまくいったのだが、カスタムレスポンスは4KB以下でないとだめなので、ちょっと凝ったメンテナンスページだと返せなくなるな~と思ったところ。
何かほかにも良い方法がないか調べてみようと思う。