目的
AWS WAF に複数のルールを適用し、いくつかのルールに個別の設定がある場合に、
冗長な実装とならないようにする(以下のようにrule
ブロックを複数使用しない)
resource "aws_wafv2_web_acl" "foo" {
name = "foo"
description = "foo"
scope = "REGIONAL"
default_action {
block {}
}
rule {
name = "AWS-AWSManagedRulesLinuxRuleSet"
priority = 0
override_action {
count {}
}
statement {
managed_rule_group_statement {
name = "AWS-AWSManagedRulesLinuxRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = false
metric_name = "foo_name"
sampled_requests_enabled = false
}
}
rule {
name = "AWS-AWSManagedRulesSQLiRuleSet"
priority = 1
override_action {
count {}
}
statement {
managed_rule_group_statement {
name = "AWS-AWSManagedRulesSQLiRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = false
metric_name = "foo_name"
sampled_requests_enabled = false
}
}
visibility_config {
metric_name = "foo"
sampled_requests_enabled = false
cloudwatch_metrics_enabled = false
}
実装
variable "web_acl_association_arn" {}
locals {
web_acl_name = "test-web-acl"
# WAFに適用するルールのリスト
# 個別設定がある場合は、それを判定できる("bot_control" : true)フラグを加えておく
rules = [
{ "name" : "AWSManagedRulesCommonRuleSet" },
{ "name" : "AWSManagedRulesAdminProtectionRuleSet" },
{ "name" : "AWSManagedRulesBotControlRuleSet", "bot_control" : true },
]
# list → map (listの並び順のルール優先度とするためkeyをindexとしておく)
rules_map = { for i, j in local.rules : i => j }
}
resource "aws_wafv2_web_acl" "web_acl" {
default_action {
allow {}
}
name = local.web_acl_name
scope = "REGIONAL"
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = local.web_acl_name
sampled_requests_enabled = true
}
dynamic "rule" {
for_each = local.rules_map
content {
name = "AWS-${rule.value.name}"
override_action {
count {}
}
priority = rule.key # listのindexをルール優先度とする
statement {
managed_rule_group_statement {
name = rule.value.name
vendor_name = "AWS"
dynamic "managed_rule_group_configs" {
# 個別設定がある(判定用フラグが立っている)場合、for_eachで1回ループを回して設定する
for_each = can(rule.value.bot_control) ? [1] : []
content {
aws_managed_rules_bot_control_rule_set {
inspection_level = "TARGETED"
}
}
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWS-${rule.value.name}"
sampled_requests_enabled = true
}
}
}
}
# WAFのアタッチ
resource "aws_wafv2_web_acl_association" "web_acl_association" {
resource_arn = var.web_acl_association_arn
web_acl_arn = aws_wafv2_web_acl.web_acl.arn
}