
はじめに
こんにちは、リテールハブ開発部でバックエンドエンジニアをしているホシと言います。
現在、小売アプリの開発でLaravel11を利用してサービス開発を行っています。
今回はサービス提供をする上でセキュリティ対策としてAWSのWAFを導入することになったお話をしようと思います。
AWS WAF(Web Application Firewall)は、Webアプリケーションを守るための強力なサービスです。 今回、私は初めてTerraformを使ってWAFを設定し、ALBやCloudFrontと連携させました。
まずはChatGPT、Cursorなどを活用して、設定やTerraformコードの作成自体は非常にスムーズに進めることができましたが、実際に運用を考えると「事前に知っておくべき重要な仕様や制限」をいくつか経験することになりました。
この記事では、初めてWAFを導入する方に向けて、Terraformと組み合わせたWAF設定で注意すべきポイントを中心にご紹介します。
特に、HTMLを投稿するFroala Editorのようなツールを使っている場合に影響を受けやすい内容も一緒にお話できたらと思います。
WAFをTerraformで構築して見えてきた「事前に知っておくべき3つのポイント」
TerraformとWAFを組み合わせて構築してみると、「知らないとハマる」「調査が必要になる」ポイントがありました。ここではその中でも特に印象的だった3つを紹介します。
ポイント1:WAFのロググループ名には「命名ルール」がある
WAFのログをCloudWatch Logsに出力する際、ロググループ名には特定の命名ルールがあります。
- 正しい命名:
aws-waf-logs-で始まる必要あり - ルールに従わないと: Terraform実行時にエラーになる(が、原因が分かりづらい)
例:Terraformでのログ設定コード
resource "aws_cloudwatch_log_group" "waf_logs" {
name = "aws-waf-logs-my-web-acl" # ← このprefixが必須!
}
resource "aws_wafv2_web_acl_logging_configuration" "example" {
log_destination_configs = [aws_cloudwatch_log_group.waf_logs.arn]
resource_arn = aws_wafv2_web_acl.main.arn
}
補足:
Terraformでのエラー内容は「ARNが無効」「リソースが見つからない」などと表示される場合が多く、命名ルールの問題にたどり着くのに時間がかかりました。
ドキュメント等を読めば難しいことではないのですが、私は名前は自由に決められると思い込んでいた部分もあり、余計にはまってしまったポイントになります。
Error: creating WAFv2 Logging Configuration: WAFInvalidParameterException: The resource ARN 'arn:aws:logs:ap-northeast-1:123456789012:log-group:invalid-name' is invalid or does not exist.
ポイント2:CloudFrontとWAFの紐付け解除には少し特別な手順が必要
ALBと違い、CloudFrontにWAFを紐付けたあとにTerraformで解除するには注意が必要です。
通常の terraform apply では解除できず、明示的な操作が必要になります。
解決方法は2つ
- 手動でWebコンソールからWAFの紐付けを解除する
- Terraformで
web_acl_id = nullを指定して「apply」を行い明示的に解除する
上記どちらかを行った上であれば、ALB同様Terraformのコードを削除するだけで簡単にWAF設定の削除ができます。
Terraform例:
resource "aws_cloudfront_distribution" "example" {
# 他の設定...
web_acl_id = null # ← 明示的に解除しないとエラーになる
}
注意:
- WAFを解除せずに削除しようとすると、「リソースがまだ関連付けられている」としてエラーになります。
- なぜALBではうまくいくのにCloudFrontだとエラーなのかが仕様として認識できておらず、はまってしまったポイントになります。
- CloudFrontはリージョンが「us-east-1」に固定されている点も含めて、ALBと挙動が異なるため、WAF設定時は追加考慮がいる認識が必要です。
ポイント3:Froala Editor × AWSマネージドルールで想定外のブロックが発生
今回はAWSのマネージドルール AWSManagedRulesCommonRuleSet を導入しました。
これは定番の汎用ルールセットで、以下のように簡単にTerraformから利用できます。
導入コード(Terraform)
rule {
name = "AWS-AWSManagedRulesCommonRuleSet"
priority = 0
override_action {
none {} # 動作確認時はblockで良いが、影響調査のためcountにするのがオススメ
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
sampled_requests_enabled = true
metric_name = "CommonRules"
}
}
まずは汎用的なものを適用して、適宜最適なものを設定していこうと考えていたのですが、
早速以下の2点で大きく影響が出ることがわかりました。
これも事前に知っているかどうかで調査、対策の時間が節約できるのではないかなと思っています。
問題①:XSS検知により投稿がブロックされる
- 対象ルール:
CrossSiteScripting_BODY - Froala EditorはHTMLを生成するため、
<script>タグに似た構文や属性が含まれる場合がある - 結果:正当な入力でもWAFがXSSと誤検知してブロックする場合がある
対応策:
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
# 「CrossSiteScripting_BODY」ルールのみcount運用にする設定を追加
rule_action_override {
name = "CrossSiteScripting_BODY"
action_to_use {
count {}
}
}
}
}
厄介なところは、すべてのHTML本文でなるわけではなく、内容によってエラーになるということです。
そのため、検証時は特に発覚することなく検知できず、本番のデータを利用したことで発覚しました。
最初はなぜ一部だけエラーになるかの原因もわからず特定まで時間がかかりました。
WAFのログの中にBLOCKしているログがあるので、それを参照することで特定のケースの場合のみBLOCKされていることがわかりました。
やはりこういうことからも、本番運用では最初はcount運用して様子を見るということが良いと思い知らされた部分でもあります。
今回はcount運用にすることでエラー回避はしていますが、実はただBLOCKしないようにしているだけであり、
セキュリティ面で考えるとベストではない状態です。
ここは場合によってはNGで、対策をさらに検討する必要があるかもしれません。
問題②:リクエストボディ8KB制限による検知漏れ・意図しないブロック
- 対象ルール:
SizeRestrictions_BODY - AWS WAFはリクエストボディの検査に 最大8KB(8192バイト) という上限がある
- Froalaから投稿された長文・装飾つきHTMLで制限を超えることがある
こちらも事前にわかっていれば対策のやりようはあったと思いますが、 マネージドルール内容のすべてを把握できていない、かつFroala Editorの仕様もしっかり把握できていない部分が重なり、 原因の特定、対応策により時間がかかってしまった部分になります。
対応策の選択肢:
countモードに変更し、ブロックせずログだけ記録する
→とはいえ、できれば事前にサイズ制限によるブロックは行いたいところです。- Froala側で入力サイズのバイト制限をかける
→これはFroalaの仕様上、8KB 以下に抑える本文を作成するのはかなり厳しそうです。 - 投稿を複数回に分割して送信するような仕組みに変更
→文章では簡単に書けますが、考慮点が非常に多く対応コストは高いです。
(分割送信用のAPI準備、同じデータの同時更新時の考慮、分割更新の制御、エラー制御)
まとめ:WAFを導入する際はユースケースと制限を事前に理解しよう
今回の内容を簡単に表にしました。
| 観点 | 内容 |
|---|---|
| ロググループ名の制約 | aws-waf-logs- で始めないとTerraformエラーに。事前に命名確認を! |
| CloudFront解除時の注意 | web_acl_id = null を明示しないと Terraform Apply 時にエラー |
| XSS検出の過検知 | HTMLエディタ使用時は count モードで様子を見るのが安全 |
| 8KB制限のインパクト | 長文・装飾投稿があるならアプリ・インフラ両面での対応が必要 |
おわりに
いかがでしたでしょうか。
AIを利用することで効率よくWAFを構築できた反面、仕様への理解が不十分だと意図せぬトラブルにもつながります。
特にFroala EditorのようにHTMLを扱うツールを使っている場合は、WAFの標準ルールと衝突しやすく、検知・ブロックの調整が重要になります。 もし予期せぬ403エラーなどが発生している場合は本記事の内容の部分を疑ってみるのも良いかもしれません。
本記事が、これからWAFを導入される方にとっての参考になれば幸いです。
最後までお読みいただきありがとうございました。